summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimanshu Agarwal <himanaga@qti.qualcomm.com>2016-03-10 22:18:50 +0530
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2016-04-22 10:23:12 +0530
commit1da2a9d57b27d56c702e18c22081794256cd58ea (patch)
treeb8bde8d114596f5d5c045fa352f30b670a590eec
parent6819dfeb56ef2df9a7304c225418c5a7daa39946 (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.h3
-rw-r--r--CORE/HDD/src/wlan_hdd_hostapd.c22
-rw-r--r--CORE/HDD/src/wlan_hdd_wext.c27
-rw-r--r--CORE/SERVICES/COMMON/adf/adf_trace.c376
-rw-r--r--CORE/SERVICES/COMMON/adf/adf_trace.h180
-rw-r--r--CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h6
-rw-r--r--CORE/VOSS/inc/vos_packet.h5
-rw-r--r--CORE/VOSS/src/vos_api.c2
-rw-r--r--CORE/VOSS/src/vos_packet.c6
-rw-r--r--Kbuild33
-rw-r--r--Kconfig4
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() -
diff --git a/Kbuild b/Kbuild
index 2faeb552d0b1..b727e652a559 100644
--- a/Kbuild
+++ b/Kbuild
@@ -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
diff --git a/Kconfig b/Kconfig
index 5743b75a6218..791b0588da3a 100644
--- a/Kconfig
+++ b/Kconfig
@@ -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