diff options
| author | Himanshu Agarwal <himanaga@qti.qualcomm.com> | 2016-03-10 22:18:50 +0530 |
|---|---|---|
| committer | Anjaneedevi Kapparapu <akappa@codeaurora.org> | 2016-04-22 10:23:12 +0530 |
| commit | 1da2a9d57b27d56c702e18c22081794256cd58ea (patch) | |
| tree | b8bde8d114596f5d5c045fa352f30b670a590eec | |
| parent | 6819dfeb56ef2df9a7304c225418c5a7daa39946 (diff) | |
qcacld-2.0: Add DP TRACE framework
The DP TRACE framework allows various events in the data path to be
recorded and retrieves the recent records whenever necessary.
Change-Id: I716469468c1dce2a401aad60caf729aac4c3a963
CRs-Fixed: 988801
| -rw-r--r-- | CORE/HDD/inc/qc_sap_ioctl.h | 3 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_hostapd.c | 22 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_wext.c | 27 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/adf/adf_trace.c | 376 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/adf/adf_trace.h | 180 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h | 6 | ||||
| -rw-r--r-- | CORE/VOSS/inc/vos_packet.h | 5 | ||||
| -rw-r--r-- | CORE/VOSS/src/vos_api.c | 2 | ||||
| -rw-r--r-- | CORE/VOSS/src/vos_packet.c | 6 | ||||
| -rw-r--r-- | Kbuild | 33 | ||||
| -rw-r--r-- | Kconfig | 4 |
11 files changed, 655 insertions, 9 deletions
diff --git a/CORE/HDD/inc/qc_sap_ioctl.h b/CORE/HDD/inc/qc_sap_ioctl.h index 256c14d8e2a4..439b4d77243b 100644 --- a/CORE/HDD/inc/qc_sap_ioctl.h +++ b/CORE/HDD/inc/qc_sap_ioctl.h @@ -158,7 +158,7 @@ typedef struct #define QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE (SIOCIWFIRSTPRIV+15) #define WE_SET_WLAN_DBG 1 -/* 2 is unused */ +#define WE_SET_DP_TRACE 2 #define WE_SET_SAP_CHANNELS 3 #define QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE (SIOCIWFIRSTPRIV+16) @@ -189,6 +189,7 @@ typedef struct #ifdef WLAN_DEBUG #define QCSAP_IOCTL_SET_FW_CRASH_INJECT 1 #endif +#define QCSAP_IOCTL_DUMP_DP_TRACE_LEVEL 2 #define MAX_VAR_ARGS 7 diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c index 4998af6310e4..2cd5b60df2a7 100644 --- a/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/CORE/HDD/src/wlan_hdd_hostapd.c @@ -92,6 +92,7 @@ extern int process_wma_set_command(int sessid, int paramid, #include "wlan_hdd_trace.h" #include "vos_types.h" #include "vos_trace.h" +#include "adf_trace.h" #include "wlan_hdd_cfg.h" #include <wlan_hdd_wowl.h> #include "wlan_hdd_tsf.h" @@ -118,6 +119,8 @@ extern int process_wma_set_command(int sessid, int paramid, /* EID byte + length byte + four byte WiFi OUI */ #define DOT11F_EID_HEADER_LEN (6) +#define DUMP_DP_TRACE 0 + /*--------------------------------------------------------------------------- * Function definitions *-------------------------------------------------------------------------*/ @@ -2585,6 +2588,14 @@ static int __iw_softap_set_two_ints_getnone(struct net_device *dev, value[1], value[2], GEN_CMD); break; #endif + case QCSAP_IOCTL_DUMP_DP_TRACE_LEVEL: + hddLog(LOG1, "WE_DUMP_DP_TRACE: %d %d", + value[1], value[2]); + if (value[1] == DUMP_DP_TRACE) + adf_dp_trace_dump_all(value[2]); + else + hddLog(LOGE, "unexpected value for dump_dp_trace"); + break; default: hddLog(LOGE, "%s: Invalid IOCTL command %d", __func__, sub_cmd); break; @@ -6755,6 +6766,12 @@ static const struct iw_priv_args hostapd_private_args[] = { 0, "setsapchannels" }, + /* handlers for sub-ioctl */ + { WE_SET_DP_TRACE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, + 0, + "set_dp_trace" }, + /* handlers for main ioctl */ { QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE, IW_PRIV_TYPE_INT | MAX_VAR_ARGS, @@ -6872,6 +6889,11 @@ static const struct iw_priv_args hostapd_private_args[] = { { QCASAP_SET_RADAR_DBG, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setRadarDbg" }, + + /* dump dp trace - descriptor or dp trace records */ + { QCSAP_IOCTL_DUMP_DP_TRACE_LEVEL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, "dump_dp_trace" }, }; static const iw_handler hostapd_private[] = { diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index f89ae2b972b6..536651a8b8cc 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -98,6 +98,7 @@ #include "wlan_qct_wda.h" #include "vos_trace.h" #include "wlan_hdd_assoc.h" +#include "adf_trace.h" #ifdef QCA_PKT_PROTO_TRACE #include "vos_packet.h" @@ -320,7 +321,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, /* Private ioctls and their sub-ioctls */ #define WLAN_PRIV_SET_THREE_INT_GET_NONE (SIOCIWFIRSTPRIV + 4) #define WE_SET_WLAN_DBG 1 -/* 2 is unused */ +#define WE_SET_DP_TRACE 2 #define WE_SET_SAP_CHANNELS 3 /* Private ioctls and their sub-ioctls */ @@ -455,6 +456,8 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, #define WE_SET_FW_CRASH_INJECT 2 #endif #define WE_SET_MON_MODE_CHAN 3 +#define WE_DUMP_DP_TRACE_LEVEL 4 +#define DUMP_DP_TRACE 0 #define WLAN_STATS_INVALID 0 #define WLAN_STATS_RETRY_CNT 1 @@ -8180,7 +8183,9 @@ static int __iw_set_three_ints_getnone(struct net_device *dev, case WE_SET_WLAN_DBG: vos_trace_setValue( value[1], value[2], value[3]); break; - + case WE_SET_DP_TRACE: + adf_dp_trace_set_value(value[1], value[2], value[3]); + break; case WE_SET_SAP_CHANNELS: /* value[3] the acs band is not required as start and end channels are * enough but this cmd is maintained under set three ints for historic @@ -11353,7 +11358,14 @@ static int __iw_set_two_ints_getnone(struct net_device *dev, ret = -EINVAL; } break; - + case WE_DUMP_DP_TRACE_LEVEL: + hddLog(LOG1, "WE_DUMP_DP_TRACE_LEVEL: %d %d", + value[1], value[2]); + if (value[1] == DUMP_DP_TRACE) + adf_dp_trace_dump_all(value[2]); + else + hddLog(LOGE, "unexpected value for dump_dp_trace"); + break; default: hddLog(LOGE, "%s: Invalid IOCTL command %d", __func__, sub_cmd); break; @@ -12229,6 +12241,12 @@ static const struct iw_priv_args we_private_args[] = { 0, "setwlandbg" }, + /* handlers for sub-ioctl */ + { WE_SET_DP_TRACE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, + 0, + "set_dp_trace"}, + { WE_SET_SAP_CHANNELS, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, @@ -12547,6 +12565,9 @@ static const struct iw_priv_args we_private_args[] = { { WE_SET_MON_MODE_CHAN, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setMonChan" }, + { WE_DUMP_DP_TRACE_LEVEL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, "dump_dp_trace"}, }; diff --git a/CORE/SERVICES/COMMON/adf/adf_trace.c b/CORE/SERVICES/COMMON/adf/adf_trace.c new file mode 100644 index 000000000000..3926ae715a11 --- /dev/null +++ b/CORE/SERVICES/COMMON/adf/adf_trace.c @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * DOC: adf_trace + * + * ADF trace APIs + * + * Trace, logging, and debugging definitions and APIs + * + */ + + /* Include Files */ +#include <adf_trace.h> +#include "adf_nbuf.h" +#include "adf_os_time.h" +#include "vos_trace.h" +#include "vos_packet.h" + +/* Static and Global variables */ +static spinlock_t l_dp_trace_lock; + +static struct adf_dp_trace_record_s + g_adf_dp_trace_tbl[MAX_ADF_DP_TRACE_RECORDS]; + +/* + * all the options to configure/control DP trace are + * defined in this structure + */ +static struct s_adf_dp_trace_data g_adf_dp_trace_data; +/* + * all the call back functions for dumping DPTRACE messages from ring buffer + * are stored in adf_dp_trace_cb_table, callbacks are initialized during init + */ +static tp_adf_dp_trace_cb adf_dp_trace_cb_table[ADF_DP_TRACE_MAX]; + +/** + * adf_dp_trace_init() - enables the DP trace + * Called during driver load and it enables DP trace + * + * Return: None + */ +void adf_dp_trace_init(void) +{ + uint8_t i; + + spin_lock_init(&l_dp_trace_lock); + g_adf_dp_trace_data.head = INVALID_ADF_DP_TRACE_ADDR; + g_adf_dp_trace_data.tail = INVALID_ADF_DP_TRACE_ADDR; + g_adf_dp_trace_data.num = 0; + g_adf_dp_trace_data.proto_bitmap = 0; + g_adf_dp_trace_data.no_of_record = 0; + g_adf_dp_trace_data.verbosity = ADF_DP_TRACE_VERBOSITY_DEFAULT; + g_adf_dp_trace_data.enable = true; + + for (i = 0; i < ADF_DP_TRACE_MAX; i++) + adf_dp_trace_cb_table[i] = adf_dp_display_record; +} + +/** + * adf_dp_trace_set_value() - Configure the value to control DP trace + * @proto_bitmap : defines the protocol to be tracked + * @no_of_records : defines the nth packet which is traced + * @verbosity : defines the verbosity level + * + * Return: None + */ +void adf_dp_trace_set_value(uint8_t proto_bitmap, uint8_t no_of_record, + uint8_t verbosity) +{ + spin_lock_bh(&l_dp_trace_lock); + g_adf_dp_trace_data.proto_bitmap = proto_bitmap; + g_adf_dp_trace_data.no_of_record = no_of_record; + g_adf_dp_trace_data.verbosity = verbosity; + spin_unlock_bh(&l_dp_trace_lock); +} + +/** + * adf_dp_trace_enable_track() - enable the tracing for netbuf + * @code : defines the event + * + * Return: true or false depends on whether tracing enabled + */ +static bool adf_dp_trace_enable_track(enum ADF_DP_TRACE_ID code) +{ + if (g_adf_dp_trace_data.verbosity == ADF_DP_TRACE_VERBOSITY_HIGH) + return true; + else if (g_adf_dp_trace_data.verbosity == + ADF_DP_TRACE_VERBOSITY_MEDIUM && + (code <= ADF_DP_TRACE_HIF_PACKET_PTR_RECORD)) + return true; + else if (g_adf_dp_trace_data.verbosity == + ADF_DP_TRACE_VERBOSITY_LOW && + (code <= ADF_DP_TRACE_CE_PACKET_RECORD)) + return true; + else if (g_adf_dp_trace_data.verbosity == + ADF_DP_TRACE_VERBOSITY_DEFAULT && + (code == ADF_DP_TRACE_DROP_PACKET_RECORD)) + return true; + return false; +} + +/** + * adf_dp_trace_set_track() - Marks whether the packet needs to be traced + * @nbuf : defines the netbuf + * + * Return: None + */ +void adf_dp_trace_set_track(adf_nbuf_t nbuf) +{ + spin_lock_bh(&l_dp_trace_lock); + g_adf_dp_trace_data.count++; + if (g_adf_dp_trace_data.proto_bitmap != 0) { + if (vos_pkt_get_proto_type(nbuf, + g_adf_dp_trace_data.proto_bitmap, 0)) { + ADF_NBUF_SET_DP_TRACE(nbuf, 1); + } + } + if ((g_adf_dp_trace_data.no_of_record != 0) && + (g_adf_dp_trace_data.count % + g_adf_dp_trace_data.no_of_record == 0)) { + ADF_NBUF_SET_DP_TRACE(nbuf, 1); + } + spin_unlock_bh(&l_dp_trace_lock); +} + +/** + * dump_hex_trace() - Display the data in buffer + * @buf: buffer which contains data to be displayed + * @buf_len: defines the size of the data to be displayed + * + * Return: None + */ +static void dump_hex_trace(uint8_t *buf, uint8_t buf_len) +{ + uint8_t i; + + /* Dump the bytes in the last line */ + adf_os_print("DATA: "); + for (i = 0; i < buf_len; i++) + adf_os_print("%02x ", buf[i]); + adf_os_print("\n"); +} + +/** + * adf_dp_display_trace() - Displays a record in DP trace + * @pRecord : pointer to a record in DP trace + * @recIndex : record index + * + * Return: None + */ +void adf_dp_display_record(struct adf_dp_trace_record_s *pRecord, + uint16_t recIndex) +{ + adf_os_print("INDEX: %04d TIME: %012llu CODE: %02d\n", recIndex, + pRecord->time, pRecord->code); + switch (pRecord->code) { + case ADF_DP_TRACE_HDD_TX_TIMEOUT: + VOS_TRACE(VOS_MODULE_ID_ADF, VOS_TRACE_LEVEL_ERROR, + "HDD TX Timeout\n"); + break; + case ADF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT: + VOS_TRACE(VOS_MODULE_ID_ADF, VOS_TRACE_LEVEL_ERROR, + "HDD SoftAP TX Timeout\n"); + break; + case ADF_DP_TRACE_VDEV_PAUSE: + VOS_TRACE(VOS_MODULE_ID_ADF, VOS_TRACE_LEVEL_ERROR, + "VDEV Pause\n"); + break; + case ADF_DP_TRACE_VDEV_UNPAUSE: + VOS_TRACE(VOS_MODULE_ID_ADF, VOS_TRACE_LEVEL_ERROR, + "VDEV UnPause\n"); + break; + default: + dump_hex_trace(pRecord->data, pRecord->size); + } +} + +/** + * adf_dp_trace() - Stores the data in buffer + * @nbuf : defines the netbuf + * @code : defines the event + * @data : defines the data to be stored + * @size : defines the size of the data record + * + * Return: None + */ +void adf_dp_trace(adf_nbuf_t nbuf, enum ADF_DP_TRACE_ID code, + uint8_t *data, uint8_t size) +{ + struct adf_dp_trace_record_s *rec; + + /* Return when Dp trace is not enabled */ + if (!g_adf_dp_trace_data.enable) + return; + + /* If nbuf is NULL, check for VDEV PAUSE, UNPAUSE, TIMEOUT */ + if (!nbuf) { + switch (code) { + case ADF_DP_TRACE_HDD_TX_TIMEOUT: + case ADF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT: + case ADF_DP_TRACE_VDEV_PAUSE: + case ADF_DP_TRACE_VDEV_UNPAUSE: + if (adf_dp_trace_enable_track(code)) + goto register_record; + else + return; + + default: + return; + } + } + + /* Return when the packet is not a data packet */ + if (NBUF_GET_PACKET_TRACK(nbuf) != NBUF_TX_PKT_DATA_TRACK) + return; + + /* Return when nbuf is not marked for dp tracing or + * verbosity does not allow + */ + if ((adf_dp_trace_enable_track(code) == false) || + !ADF_NBUF_GET_DP_TRACE(nbuf)) + return; + + /* Acquire the lock so that only one thread at a time can fill the ring + * buffer + */ + +register_record: + + spin_lock_bh(&l_dp_trace_lock); + + g_adf_dp_trace_data.num++; + + if (g_adf_dp_trace_data.num > MAX_ADF_DP_TRACE_RECORDS) + g_adf_dp_trace_data.num = MAX_ADF_DP_TRACE_RECORDS; + + if (INVALID_ADF_DP_TRACE_ADDR == g_adf_dp_trace_data.head) { + /* first record */ + g_adf_dp_trace_data.head = 0; + g_adf_dp_trace_data.tail = 0; + } else { + /* queue is not empty */ + g_adf_dp_trace_data.tail++; + + if (MAX_ADF_DP_TRACE_RECORDS == g_adf_dp_trace_data.tail) + g_adf_dp_trace_data.tail = 0; + + if (g_adf_dp_trace_data.head == g_adf_dp_trace_data.tail) { + /* full */ + if (MAX_ADF_DP_TRACE_RECORDS == + ++g_adf_dp_trace_data.head) + g_adf_dp_trace_data.head = 0; + } + } + + rec = &g_adf_dp_trace_tbl[g_adf_dp_trace_data.tail]; + rec->code = code; + rec->size = 0; + if (data != NULL && size > 0) { + if (size > ADF_DP_TRACE_RECORD_SIZE) + size = ADF_DP_TRACE_RECORD_SIZE; + + rec->size = size; + switch (code) { + case ADF_DP_TRACE_HDD_PACKET_PTR_RECORD: + case ADF_DP_TRACE_CE_PACKET_PTR_RECORD: + case ADF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD: + case ADF_DP_TRACE_TXRX_PACKET_PTR_RECORD: + case ADF_DP_TRACE_HTT_PACKET_PTR_RECORD: + case ADF_DP_TRACE_HTC_PACKET_PTR_RECORD: + case ADF_DP_TRACE_HIF_PACKET_PTR_RECORD: + adf_os_mem_copy(rec->data, (uint8_t *)(&data), size); + break; + + case ADF_DP_TRACE_DROP_PACKET_RECORD: + case ADF_DP_TRACE_HDD_PACKET_RECORD: + case ADF_DP_TRACE_CE_PACKET_RECORD: + adf_os_mem_copy(rec->data, data, size); + break; + default: + break; + } + } + rec->time = adf_os_gettimestamp(); + rec->pid = (in_interrupt() ? 0 : current->pid); + spin_unlock_bh(&l_dp_trace_lock); +} + +/** + * adf_dp_trace_dump_all() - Dump data from ring buffer via call back functions + * registered with ADF + * @code : Reason code + * @count : Number of lines to dump starting from tail to head + * + * Return : nothing + */ +void adf_dp_trace_dump_all(uint32_t count) +{ + struct adf_dp_trace_record_s pRecord; + int32_t i, tail; + + if (!g_adf_dp_trace_data.enable) { + VOS_TRACE(VOS_MODULE_ID_SYS, + VOS_TRACE_LEVEL_ERROR, "Tracing Disabled"); + return; + } + + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "Total Records: %d, Head: %d, Tail: %d", + g_adf_dp_trace_data.num, g_adf_dp_trace_data.head, + g_adf_dp_trace_data.tail); + + /* aquire the lock so that only one thread at a time can read + * the ring buffer + */ + spin_lock_bh(&l_dp_trace_lock); + + if (g_adf_dp_trace_data.head != INVALID_ADF_DP_TRACE_ADDR) { + i = g_adf_dp_trace_data.head; + tail = g_adf_dp_trace_data.tail; + + if (count) { + if (count > g_adf_dp_trace_data.num) + count = g_adf_dp_trace_data.num; + if (tail >= (count - 1)) + i = tail - count + 1; + else if (count != MAX_ADF_DP_TRACE_RECORDS) + i = MAX_ADF_DP_TRACE_RECORDS - ((count - 1) - + tail); + } + + pRecord = g_adf_dp_trace_tbl[i]; + spin_unlock_bh(&l_dp_trace_lock); + for (;; ) { + adf_dp_trace_cb_table[pRecord. + code] (&pRecord, (uint16_t)i); + if (i == tail) + break; + i += 1; + + spin_lock_bh(&l_dp_trace_lock); + if (MAX_ADF_DP_TRACE_RECORDS == i) + i = 0; + + pRecord = g_adf_dp_trace_tbl[i]; + spin_unlock_bh(&l_dp_trace_lock); + } + } else { + spin_unlock_bh(&l_dp_trace_lock); + } +} diff --git a/CORE/SERVICES/COMMON/adf/adf_trace.h b/CORE/SERVICES/COMMON/adf/adf_trace.h new file mode 100644 index 000000000000..deddc7a16e43 --- /dev/null +++ b/CORE/SERVICES/COMMON/adf/adf_trace.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2016 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(__ADF_TRACE_H) +#define __ADF_TRACE_H + +/** + * DOC: adf_trace + * + * Atheros driver framework trace APIs + * + * Trace, logging, and debugging definitions and APIs + * + */ + + /* Include Files */ +#include <adf_nbuf.h> + +#ifdef FEATURE_DPTRACE_ENABLE + /* DP Trace Implementation */ +#define DPTRACE(p) p +#else +#define DPTRACE(p) /*no-op*/ +#endif + +#define MAX_ADF_DP_TRACE_RECORDS 4000 +#define ADF_DP_TRACE_RECORD_SIZE 16 +#define INVALID_ADF_DP_TRACE_ADDR 0xffffffff +#define ADF_DP_TRACE_VERBOSITY_HIGH 3 +#define ADF_DP_TRACE_VERBOSITY_MEDIUM 2 +#define ADF_DP_TRACE_VERBOSITY_LOW 1 +#define ADF_DP_TRACE_VERBOSITY_DEFAULT 0 + +/** + * enum ADF_DP_TRACE_ID - Generic ID to identify various events in data path + * @ADF_DP_TRACE_INVALID: Invalid ID + * @ADF_DP_TRACE_DROP_PACKET_RECORD: Dropped packet stored with this id + * @ADF_DP_TRACE_HDD_PACKET_PTR_RECORD: nbuf->data ptr of HDD + * @ADF_DP_TRACE_HDD_PACKET_RECORD: nbuf->data stored with this id + * @ADF_DP_TRACE_CE_PACKET_PTR_RECORD: nbuf->data ptr of CE + * @ADF_DP_TRACE_CE_PACKET_RECORD: nbuf->data stored with this id + * @ADF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD: nbuf->data ptr of txrx queue + * @ADF_DP_TRACE_TXRX_PACKET_PTR_RECORD: nbuf->data ptr of txrx + * @ADF_DP_TRACE_HTT_PACKET_PTR_RECORD: nbuf->data ptr of htt + * @ADF_DP_TRACE_HTC_PACKET_PTR_RECORD: nbuf->data ptr of htc + * @ADF_DP_TRACE_HIF_PACKET_PTR_RECORD: nbuf->data ptr of hif + * @ADF_DP_TRACE_HDD_TX_TIMEOUT: hdd tx timeout event + * @ADF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT: hdd tx softap timeout event + * @ADF_DP_TRACE_VDEV_PAUSE: vdev pause event + * @ADF_DP_TRACE_VDEV_UNPAUSE: vdev unpause event + * + */ +enum ADF_DP_TRACE_ID { + ADF_DP_TRACE_INVALID = 0, + ADF_DP_TRACE_DROP_PACKET_RECORD = 1, + ADF_DP_TRACE_HDD_PACKET_PTR_RECORD = 2, + ADF_DP_TRACE_HDD_PACKET_RECORD = 3, + ADF_DP_TRACE_CE_PACKET_PTR_RECORD = 4, + ADF_DP_TRACE_CE_PACKET_RECORD = 5, + ADF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD = 6, + ADF_DP_TRACE_TXRX_PACKET_PTR_RECORD = 7, + ADF_DP_TRACE_HTT_PACKET_PTR_RECORD = 8, + ADF_DP_TRACE_HTC_PACKET_PTR_RECORD = 9, + ADF_DP_TRACE_HIF_PACKET_PTR_RECORD = 10, + ADF_DP_TRACE_HDD_TX_TIMEOUT = 11, + ADF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT = 12, + ADF_DP_TRACE_VDEV_PAUSE = 13, + ADF_DP_TRACE_VDEV_UNPAUSE = 14, + ADF_DP_TRACE_MAX + +}; + +/** + * struct adf_dp_trace_record_s - Describes a record in DP trace + * @time: time when it got stored + * @code: Describes the particular event + * @data: buffer to store data + * @size: Length of the valid data stored in this record + * @pid : process id which stored the data in this record + */ +struct adf_dp_trace_record_s { + uint64_t time; + uint8_t code; + uint8_t data[ADF_DP_TRACE_RECORD_SIZE]; + uint8_t size; + uint32_t pid; +}; + +/** + * struct adf_dp_trace_data - Parameters to configure/control DP trace + * @head: Position of first record + * @tail: Position of last record + * @num: Current index + * @proto_bitmap: defines which protocol to be traced + * @no_of_record: defines every nth packet to be traced + * @verbosity : defines verbosity level + * @enable: enable/disable DP trace + * @count: current packet number + */ +struct s_adf_dp_trace_data { + uint32_t head; + uint32_t tail; + uint32_t num; + + /* config for controlling the trace */ + uint8_t proto_bitmap; + uint8_t no_of_record; + uint8_t verbosity; + bool enable; + uint32_t count; +}; +/* Function declarations and documenation */ + +#ifdef FEATURE_DPTRACE_ENABLE +void adf_dp_trace_init(void); +void adf_dp_trace_set_value(uint8_t proto_bitmap, uint8_t no_of_records, + uint8_t verbosity); +void adf_dp_trace_set_track(adf_nbuf_t nbuf); +void adf_dp_trace(adf_nbuf_t nbuf, enum ADF_DP_TRACE_ID code, + uint8_t *data, uint8_t size); +void adf_dp_trace_dump_all(uint32_t count); +typedef void (*tp_adf_dp_trace_cb)(struct adf_dp_trace_record_s* , uint16_t); +void adf_dp_display_record(struct adf_dp_trace_record_s *record, + uint16_t index); + +#else +static inline void adf_dp_trace_init(void) +{ +} + +static inline void adf_dp_trace_set_value(uint8_t proto_bitmap, + uint8_t no_of_records, uint8_t verbosity) +{ +} + +static inline void adf_dp_trace_set_track(adf_nbuf_t nbuf) +{ +} + +static inline void adf_dp_trace(adf_nbuf_t nbuf, + enum ADF_DP_TRACE_ID code, uint8_t *data, uint8_t size) +{ +} + +static inline void adf_dp_trace_dump_all(uint32_t count) +{ +} + +static inline void adf_dp_display_record(struct adf_dp_trace_record_s *record, + uint16_t index) +{ +} +#endif + +#endif /* __ADF_TRACE_H */ + diff --git a/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h b/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h index 4ce6a48e7a00..af7ed453a195 100644 --- a/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h +++ b/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h @@ -89,6 +89,7 @@ struct cvg_nbuf_cb { struct { uint8_t packet_state; uint8_t packet_track; + uint8_t dp_trace; } trace; /* @@ -216,6 +217,11 @@ struct cvg_nbuf_cb { #define NBUF_UPDATE_TX_PKT_COUNT(skb, PACKET_STATE) \ adf_nbuf_set_state(skb, PACKET_STATE) +#define ADF_NBUF_SET_DP_TRACE(skb, enable) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->trace.dp_trace \ + = enable) +#define ADF_NBUF_GET_DP_TRACE(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->trace.dp_trace) #define __adf_nbuf_get_num_frags(skb) \ /* assume the OS provides a single fragment */ \ diff --git a/CORE/VOSS/inc/vos_packet.h b/CORE/VOSS/inc/vos_packet.h index f6422a82056f..469da0a1a923 100644 --- a/CORE/VOSS/inc/vos_packet.h +++ b/CORE/VOSS/inc/vos_packet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012,2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2012,2014,2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -57,7 +57,6 @@ struct vos_pkt_t; typedef struct vos_pkt_t vos_pkt_t; -#ifdef QCA_PKT_PROTO_TRACE #include "adf_nbuf.h" #define VOS_PKT_TRAC_TYPE_EAPOL NBUF_PKT_TRAC_TYPE_EAPOL @@ -83,6 +82,8 @@ v_U8_t vos_pkt_get_proto_type v_BOOL_t dot11_type ); +#ifdef QCA_PKT_PROTO_TRACE + /*--------------------------------------------------------------------------- * brief vos_pkt_trace_buf_update() - diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c index 620368fe11a6..23c318160a25 100644 --- a/CORE/VOSS/src/vos_api.c +++ b/CORE/VOSS/src/vos_api.c @@ -73,6 +73,7 @@ #include "sapApi.h" #include "vos_trace.h" +#include "adf_trace.h" @@ -177,6 +178,7 @@ VOS_STATUS vos_preOpen ( v_CONTEXT_t *pVosContext ) #endif vos_register_debugcb_init(); + adf_dp_trace_init(); return VOS_STATUS_SUCCESS; } /* vos_preOpen()*/ diff --git a/CORE/VOSS/src/vos_packet.c b/CORE/VOSS/src/vos_packet.c index ec4c17b39ee9..c02713c5007e 100644 --- a/CORE/VOSS/src/vos_packet.c +++ b/CORE/VOSS/src/vos_packet.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -49,7 +49,6 @@ #include "vos_memory.h" #include "adf_os_mem.h" -#ifdef QCA_PKT_PROTO_TRACE /* Protocol specific packet tracking feature */ #define VOS_PKT_TRAC_ETH_TYPE_OFFSET 12 #define VOS_PKT_TRAC_IP_OFFSET 14 @@ -57,6 +56,7 @@ #define VOS_PKT_TRAC_DHCP_SRV_PORT 67 #define VOS_PKT_TRAC_DHCP_CLI_PORT 68 #define VOS_PKT_TRAC_EAPOL_ETH_TYPE 0x888E +#ifdef QCA_PKT_PROTO_TRACE #define VOS_PKT_TRAC_MAX_STRING_LEN 12 #define VOS_PKT_TRAC_MAX_TRACE_BUF 50 #define VOS_PKT_TRAC_MAX_STRING_BUF 64 @@ -236,7 +236,6 @@ VOS_STATUS vos_pkt_extract_data( vos_pkt_t *pPacket, return VOS_STATUS_SUCCESS; } -#ifdef QCA_PKT_PROTO_TRACE /*--------------------------------------------------------------------------- * brief vos_pkt_get_proto_type() - @@ -298,6 +297,7 @@ v_U8_t vos_pkt_get_proto_type return pkt_proto_type; } +#ifdef QCA_PKT_PROTO_TRACE /*--------------------------------------------------------------------------- * brief vos_pkt_trace_buf_update() - @@ -44,6 +44,31 @@ ifeq ($(KERNEL_BUILD), 0) CONFIG_QCOM_LTE_COEX := y endif + # As per target team, build is done as follows: + # Defconfig : build with default flags + # Slub : defconfig + CONFIG_SLUB_DEBUG=y + + # CONFIG_SLUB_DEBUG_ON=y + CONFIG_PAGE_POISONING=y + # Perf : Using appropriate perf defconfig + # + # Shipment builds (user variants) should not have any debug feature + # enabled. This is identified using 'TARGET_BUILD_VARIANT'. Slub builds + # are identified using the CONFIG_SLUB_DEBUG_ON configuration. Since + # there is no other way to identify defconfig builds, QCOMs internal + # representation of perf builds (identified using the string 'perf'), + # is used to identify if the build is a slub or defconfig one. This + # way no critical debug feature will be enabled for perf and shipment + # builds. Other OEMs are also protected using the TARGET_BUILD_VARIANT + # config. + ifneq ($(TARGET_BUILD_VARIANT), user) + ifeq ($(CONFIG_SLUB_DEBUG_ON), y) + CONFIG_DPTRACE_ENABLE := y + else + ifeq ($(findstring perf,$(KERNEL_DEFCONFIG)),) + CONFIG_DPTRACE_ENABLE := y + endif + endif + endif + #Flag to enable Legacy Fast Roaming3(LFR3) CONFIG_QCACLD_WLAN_LFR3 := y @@ -313,6 +338,10 @@ ADF_OBJS := $(ADF_DIR)/adf_nbuf.o \ $(ADF_DIR)/linux/adf_os_defer_pvt.o \ $(ADF_DIR)/linux/adf_os_lock_pvt.o +ifeq ($(CONFIG_DPTRACE_ENABLE), y) +ADF_OBJS += $(ADF_DIR)/adf_trace.o +endif + ifeq ($(CONFIG_QCA_WIFI_SDIO), 1) ############ HIF ############ HIF_DIR := CORE/SERVICES/HIF @@ -1505,6 +1534,10 @@ ifeq ($(CONFIG_WLAN_FEATURE_NAN_DATAPATH),y) CDEFINES += -DWLAN_FEATURE_NAN_DATAPATH endif +ifeq ($(CONFIG_DPTRACE_ENABLE), y) +CDEFINES += -DFEATURE_DPTRACE_ENABLE +endif + KBUILD_CPPFLAGS += $(CDEFINES) # Currently, for versions of gcc which support it, the kernel Makefile @@ -78,4 +78,8 @@ config WLAN_WOW_PULSE bool "Enable WOW Pulse feature" default n +config DPTRACE_ENABLE + bool "Enable DPTRACE feature for non performance builds" + default n + endif # QCA_CLD_WLAN |
