Browse Source

qcacmn: Refactor DPTRACE to support new features

Refactor DPTRACE to support new data path features like
TSO and FASTPATH and add support to log DHCP, ARP and
EAPOL packets.

Change-Id: I7f9e4be12d82fbf419b2402284928144df6824f0
CRs-Fixed: 1008087
Nirav Shah 9 years ago
parent
commit
eaa20d8751
8 changed files with 870 additions and 141 deletions
  1. 1 1
      hif/src/ce/ce_main.c
  2. 6 1
      hif/src/ce/ce_service.c
  3. 2 2
      htc/htc_send.c
  4. 111 10
      qdf/inc/qdf_nbuf.h
  5. 82 17
      qdf/inc/qdf_trace.h
  6. 10 0
      qdf/linux/src/i_qdf_nbuf.h
  7. 90 0
      qdf/linux/src/qdf_nbuf.c
  8. 568 110
      qdf/linux/src/qdf_trace.c

+ 1 - 1
hif/src/ce/ce_main.c

@@ -1222,7 +1222,7 @@ hif_send_head(struct hif_opaque_softc *hif_ctx,
 
 	QDF_NBUF_UPDATE_TX_PKT_COUNT(nbuf, QDF_NBUF_TX_PKT_HIF);
 	DPTRACE(qdf_dp_trace(nbuf, QDF_DP_TRACE_HIF_PACKET_PTR_RECORD,
-				(uint8_t *)(qdf_nbuf_data(nbuf)),
+				qdf_nbuf_data_addr(nbuf),
 				sizeof(qdf_nbuf_data(nbuf))));
 	status = ce_sendlist_send(ce_hdl, nbuf, &sendlist, transfer_id);
 	QDF_ASSERT(status == QDF_STATUS_SUCCESS);

+ 6 - 1
hif/src/ce/ce_service.c

@@ -496,7 +496,7 @@ ce_sendlist_send(struct CE_handle *copyeng,
 					QDF_NBUF_TX_PKT_CE);
 		DPTRACE(qdf_dp_trace((qdf_nbuf_t)per_transfer_context,
 			QDF_DP_TRACE_CE_PACKET_PTR_RECORD,
-			(uint8_t *)(((qdf_nbuf_t)per_transfer_context)->data),
+			(uint8_t *)&(((qdf_nbuf_t)per_transfer_context)->data),
 			sizeof(((qdf_nbuf_t)per_transfer_context)->data)));
 	} else {
 		/*
@@ -668,6 +668,11 @@ int ce_send_fast(struct CE_handle *copyeng, qdf_nbuf_t *msdus,
 		*src_desc = *shadow_src_desc;
 		src_ring->per_transfer_context[write_index] = msdu;
 		write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
+
+		DPTRACE(qdf_dp_trace(msdu,
+			QDF_DP_TRACE_CE_FAST_PACKET_PTR_RECORD,
+			qdf_nbuf_data_addr(msdu),
+			sizeof(qdf_nbuf_data(msdu))));
 	}
 
 	/* Write the final index to h/w one-shot */

+ 2 - 2
htc/htc_send.c

@@ -1410,7 +1410,7 @@ A_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, qdf_nbuf_t netbuf, int Epid,
 
 	QDF_NBUF_UPDATE_TX_PKT_COUNT(netbuf, QDF_NBUF_TX_PKT_HTC);
 	DPTRACE(qdf_dp_trace(netbuf, QDF_DP_TRACE_HTC_PACKET_PTR_RECORD,
-				(uint8_t *)(qdf_nbuf_data(netbuf)),
+				qdf_nbuf_data_addr(netbuf),
 				sizeof(qdf_nbuf_data(netbuf))));
 	status = hif_send_head(target->hif_dev,
 			       pEndpoint->UL_PipeID,
@@ -1545,7 +1545,7 @@ A_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket,
 	}
 	QDF_NBUF_UPDATE_TX_PKT_COUNT(netbuf, QDF_NBUF_TX_PKT_HTC);
 	DPTRACE(qdf_dp_trace(netbuf, QDF_DP_TRACE_HTC_PACKET_PTR_RECORD,
-				(uint8_t *)(qdf_nbuf_data(netbuf)),
+				qdf_nbuf_data_addr(netbuf),
 				sizeof(qdf_nbuf_data(netbuf))));
 
 	/* send what we can */

+ 111 - 10
qdf/inc/qdf_nbuf.h

@@ -40,13 +40,33 @@
 #include <i_qdf_trace.h>
 #include <qdf_net_types.h>
 
-#define IPA_NBUF_OWNER_ID 0xaa55aa55
-#define QDF_NBUF_PKT_TRAC_TYPE_EAPOL   0x02
-#define QDF_NBUF_PKT_TRAC_TYPE_DHCP    0x04
-#define QDF_NBUF_PKT_TRAC_TYPE_MGMT_ACTION    0x08
-#define QDF_NBUF_PKT_TRAC_MAX_STRING   12
-#define QDF_NBUF_PKT_TRAC_PROTO_STRING 4
-#define QDF_NBUF_PKT_ERROR  1
+#define IPA_NBUF_OWNER_ID			0xaa55aa55
+#define QDF_NBUF_PKT_TRAC_TYPE_EAPOL		0x02
+#define QDF_NBUF_PKT_TRAC_TYPE_DHCP		0x04
+#define QDF_NBUF_PKT_TRAC_TYPE_MGMT_ACTION	0x08
+#define QDF_NBUF_PKT_TRAC_TYPE_ARP		0x10
+#define QDF_NBUF_PKT_TRAC_MAX_STRING		12
+#define QDF_NBUF_PKT_TRAC_PROTO_STRING		4
+#define QDF_NBUF_PKT_ERROR			1
+
+#define QDF_NBUF_TRAC_IPV4_OFFSET		14
+#define QDF_NBUF_TRAC_IPV4_HEADER_SIZE		20
+#define QDF_NBUF_TRAC_DHCP_SRV_PORT		67
+#define QDF_NBUF_TRAC_DHCP_CLI_PORT		68
+#define QDF_NBUF_TRAC_ETH_TYPE_OFFSET		12
+#define QDF_NBUF_TRAC_EAPOL_ETH_TYPE		0x888E
+#define QDF_NBUF_TRAC_ARP_ETH_TYPE		0x0806
+#define QDF_NBUF_DEST_MAC_OFFSET		0
+#define QDF_NBUF_SRC_MAC_OFFSET			6
+
+/* EAPOL Related MASK */
+#define EAPOL_PACKET_TYPE_OFFSET		15
+#define EAPOL_KEY_INFO_OFFSET			19
+#define EAPOL_MASK				0x8013
+#define EAPOL_M1_BIT_MASK			0x8000
+#define EAPOL_M2_BIT_MASK			0x0001
+#define EAPOL_M3_BIT_MASK			0x8013
+#define EAPOL_M4_BIT_MASK			0x0003
 
 /* Tracked Packet types */
 #define QDF_NBUF_TX_PKT_INVALID              0
@@ -65,8 +85,6 @@
 #define QDF_NBUF_TX_PKT_FREE                 9
 #define QDF_NBUF_TX_PKT_STATE_MAX            10
 
-#define QDF_NBUF_IPA_CHECK_MASK              0x80000000
-
 /**
  * struct mon_rx_status - This will have monitor mode rx_status extracted from
  * htt_rx_desc used later to update radiotap information.
@@ -110,6 +128,23 @@ struct mon_rx_status {
 	uint8_t  beamformed;
 };
 
+/* DHCP Related Mask */
+#define DHCP_OPTION53			(0x35)
+#define DHCP_OPTION53_LENGTH		(1)
+#define DHCP_OPTION53_OFFSET		(0x11A)
+#define DHCP_OPTION53_LENGTH_OFFSET	(0x11B)
+#define DHCP_OPTION53_STATUS_OFFSET	(0x11C)
+#define DHCPDISCOVER			(1)
+#define DHCPOFFER			(2)
+#define DHCPREQUEST			(3)
+#define DHCPDECLINE			(4)
+#define DHCPACK				(5)
+#define DHCPNAK				(6)
+#define DHCPRELEASE			(7)
+#define DHCPINFORM			(8)
+
+#define QDF_NBUF_IPA_CHECK_MASK		0x80000000
+
 /**
  * @qdf_nbuf_t - Platform indepedent packet abstraction
  */
@@ -556,6 +591,17 @@ static inline uint8_t *qdf_nbuf_data(qdf_nbuf_t buf)
 	return __qdf_nbuf_data(buf);
 }
 
+/**
+ * qdf_nbuf_data_addr() - Return the address of skb->data
+ * @buf: Network buffer
+ *
+ * Return: Data address
+ */
+static inline uint8_t *qdf_nbuf_data_addr(qdf_nbuf_t buf)
+{
+	return __qdf_nbuf_data_addr(buf);
+}
+
 /**
  * qdf_nbuf_headroom() - amount of headroom int the current nbuf
  * @buf: Network buffer
@@ -1066,6 +1112,62 @@ static inline uint8_t qdf_nbuf_get_tx_parallel_dnload_frm(qdf_nbuf_t buf)
 	return __qdf_nbuf_get_tx_htt2_frm(buf);
 }
 
+/**
+ * qdf_nbuf_is_ipv4_pkt() - check if packet is a ipv4 packet or not
+ * @buf:  buffer
+ *
+ * This api is for Tx packets.
+ *
+ * Return: true if packet is ipv4 packet
+ */
+static inline
+bool qdf_nbuf_is_ipv4_pkt(qdf_nbuf_t buf)
+{
+	return __qdf_nbuf_is_ipv4_pkt(buf);
+}
+
+/**
+ * qdf_nbuf_is_ipv4_dhcp_pkt() - check if packet is a dhcp packet or not
+ * @buf:  buffer
+ *
+ * This api is for ipv4 packet.
+ *
+ * Return: true if packet is DHCP packet
+ */
+static inline
+bool qdf_nbuf_is_ipv4_dhcp_pkt(qdf_nbuf_t buf)
+{
+	return __qdf_nbuf_is_ipv4_dhcp_pkt(buf);
+}
+
+/**
+ * qdf_nbuf_is_ipv4_eapol_pkt() - check if packet is a eapol packet or not
+ * @buf:  buffer
+ *
+ * This api is for ipv4 packet.
+ *
+ * Return: true if packet is EAPOL packet
+ */
+static inline
+bool qdf_nbuf_is_ipv4_eapol_pkt(qdf_nbuf_t buf)
+{
+	return __qdf_nbuf_is_ipv4_eapol_pkt(buf);
+}
+
+/**
+ * qdf_nbuf_is_ipv4_arp_pkt() - check if packet is a arp packet or not
+ * @buf:  buffer
+ *
+ * This api is for ipv4 packet.
+ *
+ * Return: true if packet is ARP packet
+ */
+static inline
+bool qdf_nbuf_is_ipv4_arp_pkt(qdf_nbuf_t buf)
+{
+	return __qdf_nbuf_is_ipv4_arp_pkt(buf);
+}
+
 /**
  * qdf_invalidate_range() - invalidate the virtual address range specified by
  *			start and end addresses.
@@ -1162,7 +1264,6 @@ static inline qdf_nbuf_t qdf_nbuf_inc_users(qdf_nbuf_t nbuf)
 	return __qdf_nbuf_inc_users(nbuf);
 }
 
-
 /**
  * qdf_nbuf_data_attr_get() - Get data_attr field from cvg_nbuf_cb
  *

+ 82 - 17
qdf/inc/qdf_trace.h

@@ -179,27 +179,76 @@ typedef struct s_qdf_trace_data {
  * @QDF_DP_TRACE_HIF_PACKET_PTR_RECORD: nbuf->data ptr of hif
  * @QDF_DP_TRACE_HDD_TX_TIMEOUT: hdd tx timeout event
  * @QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT: hdd tx softap timeout event
- * @QDF_DP_TRACE_VDEV_PAUSE: vdev pause event
- * @QDF_DP_TRACE_VDEV_UNPAUSE: vdev unpause event
  */
 enum  QDF_DP_TRACE_ID {
-	QDF_DP_TRACE_INVALID                           = 0,
-	QDF_DP_TRACE_DROP_PACKET_RECORD                = 1,
-	QDF_DP_TRACE_HDD_PACKET_PTR_RECORD             = 2,
-	QDF_DP_TRACE_HDD_PACKET_RECORD                 = 3,
-	QDF_DP_TRACE_CE_PACKET_PTR_RECORD              = 4,
-	QDF_DP_TRACE_CE_PACKET_RECORD                  = 5,
-	QDF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD      = 6,
-	QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD            = 7,
-	QDF_DP_TRACE_HTT_PACKET_PTR_RECORD             = 8,
-	QDF_DP_TRACE_HTC_PACKET_PTR_RECORD             = 9,
-	QDF_DP_TRACE_HIF_PACKET_PTR_RECORD             = 10,
-	QDF_DP_TRACE_HDD_TX_TIMEOUT                    = 11,
-	QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT             = 12,
-	QDF_DP_TRACE_VDEV_PAUSE                        = 13,
-	QDF_DP_TRACE_VDEV_UNPAUSE                      = 14,
+	QDF_DP_TRACE_INVALID,
+	QDF_DP_TRACE_DROP_PACKET_RECORD,
+	QDF_DP_TRACE_EAPOL_PACKET_RECORD,
+	QDF_DP_TRACE_DHCP_PACKET_RECORD,
+	QDF_DP_TRACE_ARP_PACKET_RECORD,
+	QDF_DP_TRACE_DEFAULT_VERBOSITY,
+	QDF_DP_TRACE_HDD_TX_TIMEOUT,
+	QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT,
+	QDF_DP_TRACE_HDD_PACKET_PTR_RECORD,
+	QDF_DP_TRACE_CE_PACKET_PTR_RECORD,
+	QDF_DP_TRACE_CE_FAST_PACKET_PTR_RECORD,
+	QDF_DP_TRACE_FREE_PACKET_PTR_RECORD,
+	QDF_DP_TRACE_LOW_VERBOSITY,
+	QDF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD,
+	QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD,
+	QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD,
+	QDF_DP_TRACE_HTT_PACKET_PTR_RECORD,
+	QDF_DP_TRACE_HTC_PACKET_PTR_RECORD,
+	QDF_DP_TRACE_HIF_PACKET_PTR_RECORD,
+	QDF_DP_TRACE_MED_VERBOSITY,
+	QDF_DP_TRACE_HDD_PACKET_RECORD,
+	QDF_DP_TRACE_HIGH_VERBOSITY,
 	QDF_DP_TRACE_MAX
+};
+
+enum qdf_proto_type {
+	QDF_PROTO_TYPE_DHCP,
+	QDF_PROTO_TYPE_EAPOL,
+	QDF_PROTO_TYPE_ARP,
+	QDF_PROTO_TYPE_MAX
+};
 
+enum qdf_proto_subtype {
+	QDF_PROTO_INVALID,
+	QDF_PROTO_EAPOL_M1,
+	QDF_PROTO_EAPOL_M2,
+	QDF_PROTO_EAPOL_M3,
+	QDF_PROTO_EAPOL_M4,
+	QDF_PROTO_DHCP_DISCOVER,
+	QDF_PROTO_DHCP_REQUEST,
+	QDF_PROTO_DHCP_OFFER,
+	QDF_PROTO_DHCP_ACK,
+	QDF_PROTO_DHCP_NACK,
+	QDF_PROTO_DHCP_RELEASE,
+	QDF_PROTO_DHCP_INFORM,
+	QDF_PROTO_DHCP_DECLINE,
+	QDF_PROTO_ARP_SUBTYPE,
+	QDF_PROTO_SUBTYPE_MAX
+};
+
+enum qdf_proto_dir {
+	QDF_TX,
+	QDF_RX
+};
+
+struct qdf_dp_trace_ptr_buf {
+	uint64_t cookie;
+	uint16_t msdu_id;
+	uint16_t status;
+};
+
+struct qdf_dp_trace_proto_buf {
+	struct qdf_mac_addr sa;
+	struct qdf_mac_addr da;
+	uint8_t vdev_id;
+	uint8_t type;
+	uint8_t subtype;
+	uint8_t dir;
 };
 
 /**
@@ -239,6 +288,8 @@ struct s_qdf_dp_trace_data {
 	bool enable;
 	uint32_t count;
 };
+
+
 /* Function declarations and documenation */
 
 /**
@@ -293,6 +344,20 @@ void qdf_dp_trace_dump_all(uint32_t count);
 typedef void (*tp_qdf_dp_trace_cb)(struct qdf_dp_trace_record_s* , uint16_t);
 void qdf_dp_display_record(struct qdf_dp_trace_record_s *record,
 							uint16_t index);
+void qdf_dp_trace_ptr(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
+		uint8_t *data, uint8_t size, uint16_t msdu_id, uint16_t status);
+
+void qdf_dp_display_ptr_record(struct qdf_dp_trace_record_s *pRecord,
+				uint16_t recIndex);
+uint8_t qdf_dp_get_proto_bitmap(void);
+void
+qdf_dp_trace_proto_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
+		uint8_t *sa, uint8_t *da, enum qdf_proto_type type,
+		enum qdf_proto_subtype subtype, enum qdf_proto_dir dir);
+void qdf_dp_display_proto_pkt(struct qdf_dp_trace_record_s *record,
+				uint16_t index);
+void qdf_dp_trace_log_pkt(uint8_t session_id, struct sk_buff *skb,
+				uint8_t event_type);
 
 
 /**

+ 10 - 0
qdf/linux/src/i_qdf_nbuf.h

@@ -480,6 +480,11 @@ void __qdf_nbuf_trace_update(struct sk_buff *buf, char *event_string);
 #define __qdf_nbuf_trace_update(skb, event_string)
 #endif /* QCA_PKT_PROTO_TRACE */
 
+bool __qdf_nbuf_is_ipv4_pkt(struct sk_buff *skb);
+bool __qdf_nbuf_is_ipv4_dhcp_pkt(struct sk_buff *skb);
+bool __qdf_nbuf_is_ipv4_eapol_pkt(struct sk_buff *skb);
+bool __qdf_nbuf_is_ipv4_arp_pkt(struct sk_buff *skb);
+
 /**
  * __qdf_to_status() - OS to QDF status conversion
  * @error : OS error
@@ -731,6 +736,11 @@ static inline uint8_t *__qdf_nbuf_data(struct sk_buff *skb)
 	return skb->data;
 }
 
+static inline uint8_t *__qdf_nbuf_data_addr(struct sk_buff *skb)
+{
+	return (uint8_t *)&skb->data;
+}
+
 /**
  * __qdf_nbuf_get_protocol() - return the protocol value of the skb
  * @skb: Pointer to network buffer

+ 90 - 0
qdf/linux/src/qdf_nbuf.c

@@ -463,6 +463,96 @@ void __qdf_nbuf_reg_trace_cb(qdf_nbuf_trace_update_t cb_func_ptr)
 }
 EXPORT_SYMBOL(__qdf_nbuf_reg_trace_cb);
 
+/**
+ * __qdf_nbuf_is_ipv4_pkt() - check if packet is a ipv4 packet
+ * @skb: Pointer to network buffer
+ *
+ * This api is for Tx packets.
+ *
+ * Return: true if packet is ipv4 packet
+ *	   false otherwise
+ */
+bool __qdf_nbuf_is_ipv4_pkt(struct sk_buff *skb)
+{
+	if (qdf_nbuf_get_protocol(skb) == htons(ETH_P_IP))
+		return true;
+	else
+		return false;
+}
+
+/**
+ * __qdf_nbuf_is_ipv4_dhcp_pkt() - check if skb data is a dhcp packet
+ * @skb: Pointer to network buffer
+ *
+ * This api is for ipv4 packet.
+ *
+ * Return: true if packet is DHCP packet
+ *	   false otherwise
+ */
+bool __qdf_nbuf_is_ipv4_dhcp_pkt(struct sk_buff *skb)
+{
+	uint16_t sport;
+	uint16_t dport;
+
+	sport = (uint16_t)(*(uint16_t *)(skb->data + QDF_NBUF_TRAC_IPV4_OFFSET +
+					 QDF_NBUF_TRAC_IPV4_HEADER_SIZE));
+	dport = (uint16_t)(*(uint16_t *)(skb->data + QDF_NBUF_TRAC_IPV4_OFFSET +
+					 QDF_NBUF_TRAC_IPV4_HEADER_SIZE +
+					 sizeof(uint16_t)));
+
+	if (((sport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP_SRV_PORT)) &&
+	     (dport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP_CLI_PORT))) ||
+	    ((sport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP_CLI_PORT)) &&
+	     (dport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP_SRV_PORT))))
+		return true;
+	else
+		return false;
+}
+
+/**
+ * __qdf_nbuf_is_ipv4_eapol_pkt() - check if skb data is a eapol packet
+ * @skb: Pointer to network buffer
+ *
+ * This api is for ipv4 packet.
+ *
+ * Return: true if packet is EAPOL packet
+ *	   false otherwise.
+ */
+bool __qdf_nbuf_is_ipv4_eapol_pkt(struct sk_buff *skb)
+{
+	uint16_t ether_type;
+
+	ether_type = (uint16_t)(*(uint16_t *)(skb->data +
+				QDF_NBUF_TRAC_ETH_TYPE_OFFSET));
+
+	if (ether_type == QDF_SWAP_U16(QDF_NBUF_TRAC_EAPOL_ETH_TYPE))
+		return true;
+	else
+		return false;
+}
+
+/**
+ * __qdf_nbuf_is_ipv4_arp_pkt() - check if skb data is a eapol packet
+ * @skb: Pointer to network buffer
+ *
+ * This api is for ipv4 packet.
+ *
+ * Return: true if packet is ARP packet
+ *	   false otherwise.
+ */
+bool __qdf_nbuf_is_ipv4_arp_pkt(struct sk_buff *skb)
+{
+	uint16_t ether_type;
+
+	ether_type = (uint16_t)(*(uint16_t *)(skb->data +
+				QDF_NBUF_TRAC_ETH_TYPE_OFFSET));
+
+	if (ether_type == QDF_SWAP_U16(QDF_NBUF_TRAC_ARP_ETH_TYPE))
+		return true;
+	else
+		return false;
+}
+
 #ifdef QCA_PKT_PROTO_TRACE
 /**
  * __qdf_nbuf_trace_update() - update trace event

+ 568 - 110
qdf/linux/src/qdf_trace.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -736,6 +736,16 @@ void qdf_dp_trace_init(void)
 
 	for (i = 0; i < QDF_DP_TRACE_MAX; i++)
 		qdf_dp_trace_cb_table[i] = qdf_dp_display_record;
+
+	qdf_dp_trace_cb_table[QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD] =
+	qdf_dp_trace_cb_table[QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD] =
+	qdf_dp_trace_cb_table[QDF_DP_TRACE_FREE_PACKET_PTR_RECORD] =
+						qdf_dp_display_ptr_record;
+	qdf_dp_trace_cb_table[QDF_DP_TRACE_EAPOL_PACKET_RECORD] =
+	qdf_dp_trace_cb_table[QDF_DP_TRACE_DHCP_PACKET_RECORD] =
+	qdf_dp_trace_cb_table[QDF_DP_TRACE_ARP_PACKET_RECORD] =
+						qdf_dp_display_proto_pkt;
+
 }
 EXPORT_SYMBOL(qdf_dp_trace_init);
 
@@ -761,25 +771,49 @@ EXPORT_SYMBOL(qdf_dp_trace_set_value);
  * qdf_dp_trace_enable_track() - enable the tracing for netbuf
  * @code: defines the event
  *
+ * In High verbosity all codes are logged.
+ * For Med/Low and Default case code which has
+ * less value than corresponding verbosity codes
+ * are logged.
+ *
  * Return: true or false depends on whether tracing enabled
  */
 static bool qdf_dp_trace_enable_track(enum QDF_DP_TRACE_ID code)
 {
-	if (g_qdf_dp_trace_data.verbosity == QDF_DP_TRACE_VERBOSITY_HIGH)
-		return true;
-	if (g_qdf_dp_trace_data.verbosity == QDF_DP_TRACE_VERBOSITY_MEDIUM
-		&& (code <= QDF_DP_TRACE_HIF_PACKET_PTR_RECORD))
+	switch (g_qdf_dp_trace_data.verbosity) {
+	case QDF_DP_TRACE_VERBOSITY_HIGH:
 		return true;
-	if (g_qdf_dp_trace_data.verbosity == QDF_DP_TRACE_VERBOSITY_LOW
-		&& (code <= QDF_DP_TRACE_CE_PACKET_RECORD))
-		return true;
-	if (g_qdf_dp_trace_data.verbosity == QDF_DP_TRACE_VERBOSITY_DEFAULT
-		&& (code == QDF_DP_TRACE_DROP_PACKET_RECORD))
-		return true;
-	return false;
+	case QDF_DP_TRACE_VERBOSITY_MEDIUM:
+		if (code <= QDF_DP_TRACE_MED_VERBOSITY)
+			return true;
+		return false;
+	case QDF_DP_TRACE_VERBOSITY_LOW:
+		if (code <= QDF_DP_TRACE_LOW_VERBOSITY)
+			return true;
+		return false;
+	case QDF_DP_TRACE_VERBOSITY_DEFAULT:
+		if (code <= QDF_DP_TRACE_DEFAULT_VERBOSITY)
+			return true;
+		return false;
+	default:
+		return false;
+	}
 }
 EXPORT_SYMBOL(qdf_dp_trace_enable_track);
 
+/**
+ * qdf_dp_get_proto_bitmap() - get dp trace proto bitmap
+ *
+ * Return: proto bitmap
+ */
+uint8_t qdf_dp_get_proto_bitmap(void)
+{
+	if (g_qdf_dp_trace_data.enable)
+		return g_qdf_dp_trace_data.proto_bitmap;
+	else
+		return 0;
+}
+
 /**
  * qdf_dp_trace_set_track() - Marks whether the packet needs to be traced
  * @nbuf: defines the netbuf
@@ -790,12 +824,6 @@ void qdf_dp_trace_set_track(qdf_nbuf_t nbuf)
 {
 	spin_lock_bh(&l_dp_trace_lock);
 	g_qdf_dp_trace_data.count++;
-	if (g_qdf_dp_trace_data.proto_bitmap != 0) {
-		if (cds_pkt_get_proto_type(nbuf,
-			g_qdf_dp_trace_data.proto_bitmap, 0)) {
-			QDF_NBUF_CB_TX_DP_TRACE(nbuf) = 1;
-		}
-	}
 	if ((g_qdf_dp_trace_data.no_of_record != 0) &&
 		(g_qdf_dp_trace_data.count %
 			g_qdf_dp_trace_data.no_of_record == 0)) {
@@ -813,105 +841,193 @@ EXPORT_SYMBOL(qdf_dp_trace_set_track);
  *
  * Return: None
  */
-static void dump_hex_trace(uint8_t *buf, uint8_t buf_len)
+static void dump_hex_trace(char *str, uint8_t *buf, uint8_t buf_len)
 {
-	uint8_t i = 0;
+	unsigned char linebuf[BUFFER_SIZE];
+	const u8 *ptr = buf;
+	int i, linelen, remaining = buf_len;
+
 	/* Dump the bytes in the last line */
-	qdf_print("DATA: ");
-	for (i = 0; i < buf_len; i++)
-		qdf_print("%02x ", buf[i]);
-	qdf_print("\n");
+	for (i = 0; i < buf_len; i += ROW_SIZE) {
+		linelen = min(remaining, ROW_SIZE);
+		remaining -= ROW_SIZE;
+
+		hex_dump_to_buffer(ptr + i, linelen, ROW_SIZE, 1,
+				linebuf, sizeof(linebuf), false);
+
+		qdf_trace_msg(QDF_MODULE_ID_QDF,
+		   QDF_TRACE_LEVEL_ERROR, "%s: %s", str, linebuf);
+	}
 }
 EXPORT_SYMBOL(dump_hex_trace);
 
 /**
- * qdf_dp_display_trace() - Displays a record in DP trace
- * @p_record: pointer to a record in DP trace
- * @rec_index: record index
+ * qdf_dp_code_to_string() - convert dptrace code to string
+ * @code: dptrace code
  *
- * Return: None
+ * Return: string version of code
  */
-void qdf_dp_display_record(struct qdf_dp_trace_record_s *p_record,
-			   uint16_t rec_index)
+const char *qdf_dp_code_to_string(enum QDF_DP_TRACE_ID code)
 {
-	qdf_print("INDEX: %04d TIME: %012llu CODE: %02d\n", rec_index,
-						p_record->time, p_record->code);
-	switch (p_record->code) {
-	case  QDF_DP_TRACE_HDD_TX_TIMEOUT:
-		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
-						"HDD TX Timeout\n");
-		break;
-	case  QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
-		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
-						"HDD soft_aP TX Timeout\n");
-		break;
-	case  QDF_DP_TRACE_VDEV_PAUSE:
-		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
-						"VDEV Pause\n");
-		break;
-	case  QDF_DP_TRACE_VDEV_UNPAUSE:
-		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
-						"VDEV un_pause\n");
-		break;
+	switch (code) {
+	case QDF_DP_TRACE_DROP_PACKET_RECORD:
+		return "DROP:";
+	case QDF_DP_TRACE_EAPOL_PACKET_RECORD:
+		return "EAPOL:";
+	case QDF_DP_TRACE_DHCP_PACKET_RECORD:
+		return "DHCP:";
+	case QDF_DP_TRACE_ARP_PACKET_RECORD:
+		return "ARP:";
+	case QDF_DP_TRACE_HDD_PACKET_PTR_RECORD:
+		return "HDD: PTR:";
+	case QDF_DP_TRACE_HDD_PACKET_RECORD:
+		return "HDD: DATA:";
+	case QDF_DP_TRACE_CE_PACKET_PTR_RECORD:
+		return "CE: PTR:";
+	case QDF_DP_TRACE_CE_FAST_PACKET_PTR_RECORD:
+		return "CE:F: PTR:";
+	case QDF_DP_TRACE_FREE_PACKET_PTR_RECORD:
+		return "FREE: PTR:";
+	case QDF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD:
+		return "TX:Q: PTR:";
+	case QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD:
+		return "TX: PTR:";
+	case QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD:
+		return "TX:F: PTR:";
+	case QDF_DP_TRACE_HTT_PACKET_PTR_RECORD:
+		return "HTT: PTR:";
+	case QDF_DP_TRACE_HTC_PACKET_PTR_RECORD:
+		return "HTC: PTR:";
+	case QDF_DP_TRACE_HIF_PACKET_PTR_RECORD:
+		return "HIF: PTR:";
+	case QDF_DP_TRACE_HDD_TX_TIMEOUT:
+		return "STA: TO:";
+	case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
+		return "SAP: TO:";
 	default:
-		dump_hex_trace(p_record->data, p_record->size);
+		return "Invalid";
 	}
-	return;
 }
-EXPORT_SYMBOL(qdf_dp_display_record);
+EXPORT_SYMBOL(qdf_dp_code_to_string);
 
 /**
- * qdf_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
+ * qdf_dp_dir_to_str() - convert direction to string
+ * @dir: direction
  *
- * Return: None
+ * Return: string version of direction
  */
-void qdf_dp_trace(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
-		  uint8_t *data, uint8_t size)
+const char *qdf_dp_dir_to_str(enum qdf_proto_dir dir)
 {
-	struct qdf_dp_trace_record_s *rec = NULL;
-
-	/* Return when Dp trace is not enabled */
-	if (!g_qdf_dp_trace_data.enable)
-		return;
+	switch (dir) {
+	case QDF_TX:
+		return "->";
+	case QDF_RX:
+		return "<-";
+	default:
+		return "invalid";
+	}
+}
+EXPORT_SYMBOL(qdf_dp_dir_to_str);
 
-	/* If nbuf is NULL, check for VDEV PAUSE, UNPAUSE, TIMEOUT */
-	if (!nbuf) {
-		switch (code) {
-		case QDF_DP_TRACE_HDD_TX_TIMEOUT:
-		case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
-		case QDF_DP_TRACE_VDEV_PAUSE:
-		case QDF_DP_TRACE_VDEV_UNPAUSE:
-			if (qdf_dp_trace_enable_track(code))
-				goto  register_record;
-			else
-				return;
+/**
+ * qdf_dp_type_to_str() - convert packet type to string
+ * @type: type
+ *
+ * Return: string version of packet type
+ */
+const char *qdf_dp_type_to_str(enum qdf_proto_type type)
+{
+	switch (type) {
+	case QDF_PROTO_TYPE_DHCP:
+		return "DHCP";
+	case QDF_PROTO_TYPE_EAPOL:
+		return "EAPOL";
+	case QDF_PROTO_TYPE_ARP:
+		return "ARP";
+	default:
+		return "invalid";
+	}
+}
+EXPORT_SYMBOL(qdf_dp_type_to_str);
 
-		default:
-			return;
-		}
+/**
+ * qdf_dp_subtype_to_str() - convert packet subtype to string
+ * @type: type
+ *
+ * Return: string version of packet subtype
+ */
+const char *qdf_dp_subtype_to_str(enum qdf_proto_subtype subtype)
+{
+	switch (subtype) {
+	case QDF_PROTO_EAPOL_M1:
+		return "M1";
+	case QDF_PROTO_EAPOL_M2:
+		return "M2";
+	case QDF_PROTO_EAPOL_M3:
+		return "M3";
+	case QDF_PROTO_EAPOL_M4:
+		return "M4";
+	case QDF_PROTO_DHCP_DISCOVER:
+		return "DISCOVER";
+	case QDF_PROTO_DHCP_REQUEST:
+		return "REQUEST";
+	case QDF_PROTO_DHCP_OFFER:
+		return "OFFER";
+	case QDF_PROTO_DHCP_ACK:
+		return "ACK";
+	case QDF_PROTO_DHCP_NACK:
+		return "NACK";
+	case QDF_PROTO_DHCP_RELEASE:
+		return "RELEASE";
+	case QDF_PROTO_DHCP_INFORM:
+		return "INFORM";
+	case QDF_PROTO_DHCP_DECLINE:
+		return "DECLINE";
+	case QDF_PROTO_ARP_SUBTYPE:
+		return "NA";
+	default:
+		return "invalid";
 	}
+}
+EXPORT_SYMBOL(qdf_dp_subtype_to_str);
 
-	/* Return when the packet is not a data packet */
-	if (QDF_NBUF_GET_PACKET_TRACK(nbuf) != QDF_NBUF_TX_PKT_DATA_TRACK)
-		return;
+/**
+ * qdf_dp_enable_check() - check if dptrace is enable or not
+ * @nbuf: nbuf
+ * @code: dptrace code
+ *
+ * Return: true/false
+ */
+bool qdf_dp_enable_check(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code)
+{
+	/* Return when Dp trace is not enabled */
+	if (!g_qdf_dp_trace_data.enable)
+		return false;
 
-	/* Return when nbuf is not marked for dp tracing or
-	 * verbosity does not allow
-	 */
-	if (qdf_dp_trace_enable_track(code) == false ||
-			!QDF_NBUF_CB_TX_DP_TRACE(nbuf))
-		return;
+	if (qdf_dp_trace_enable_track(code) == false)
+		return false;
 
-	/* Acquire the lock so that only one thread at a time can fill the ring
-	 * buffer
-	 */
+	if ((nbuf) && ((QDF_NBUF_CB_TX_PACKET_TRACK(nbuf) !=
+		 QDF_NBUF_TX_PKT_DATA_TRACK) ||
+		 (!QDF_NBUF_CB_TX_DP_TRACE(nbuf))))
+		return false;
 
-register_record:
+	return true;
+}
+EXPORT_SYMBOL(qdf_dp_enable_check);
 
+/**
+ * qdf_dp_add_record() - add dp trace record
+ * @code: dptrace code
+ * @data: data pointer
+ * @size: size of buffer
+ *
+ * Return: none
+ */
+void qdf_dp_add_record(enum QDF_DP_TRACE_ID code,
+		       uint8_t *data, uint8_t size)
+{
+	struct qdf_dp_trace_record_s *rec = NULL;
 	spin_lock_bh(&l_dp_trace_lock);
 
 	g_qdf_dp_trace_data.num++;
@@ -946,29 +1062,371 @@ register_record:
 			size = QDF_DP_TRACE_RECORD_SIZE;
 
 		rec->size = size;
-		switch (code) {
-		case QDF_DP_TRACE_HDD_PACKET_PTR_RECORD:
-		case QDF_DP_TRACE_CE_PACKET_PTR_RECORD:
-		case QDF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD:
-		case QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD:
-		case QDF_DP_TRACE_HTT_PACKET_PTR_RECORD:
-		case QDF_DP_TRACE_HTC_PACKET_PTR_RECORD:
-		case QDF_DP_TRACE_HIF_PACKET_PTR_RECORD:
-			qdf_mem_copy(rec->data, (uint8_t *)(&data), size);
-			break;
+		qdf_mem_copy(rec->data, data, size);
+	}
+	rec->time = qdf_get_log_timestamp();
+	rec->pid = (in_interrupt() ? 0 : current->pid);
+	spin_unlock_bh(&l_dp_trace_lock);
+
+}
+EXPORT_SYMBOL(qdf_dp_add_record);
+
+/**
+ * qdf_event_eapol_log() - send event to wlan diag
+ * @skb: skb ptr
+ * @event_type: event type
+ * @eapol_key_info: eapol key info
+ *
+ * Return: None
+ */
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+static void qdf_event_eapol_log(struct sk_buff *skb, uint8_t event_type,
+				int16_t eapol_key_info)
+{
+	WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct host_event_wlan_eapol);
+
+	wlan_diag_event.event_sub_type = event_type;
+	wlan_diag_event.eapol_packet_type = (uint8_t)(*(uint8_t *)
+				(skb->data + EAPOL_PACKET_TYPE_OFFSET));
+	wlan_diag_event.eapol_key_info = eapol_key_info;
+	wlan_diag_event.eapol_rate = 0;
+	qdf_mem_copy(wlan_diag_event.dest_addr,
+			(skb->data + QDF_NBUF_DEST_MAC_OFFSET),
+			sizeof(wlan_diag_event.dest_addr));
+	qdf_mem_copy(wlan_diag_event.src_addr,
+			(skb->data + QDF_NBUF_SRC_MAC_OFFSET),
+			sizeof(wlan_diag_event.src_addr));
+
+	WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_EAPOL);
+}
+#else
+static void qdf_event_eapol_log(struct sk_buff *skb, uint8_t event_type,
+				int16_t eapol_key_info)
+{
+}
+#endif
+
+/**
+ * qdf_log_eapol_pkt() - log EAPOL packet
+ * @session_id: vdev_id
+ * @skb: skb pointer
+ * @event_type: event_type
+ *
+ * Return: true/false
+ */
+bool qdf_log_eapol_pkt(uint8_t session_id, struct sk_buff *skb,
+		       uint8_t event_type)
+{
+	uint16_t mask;
+	uint16_t eapol_key_info;
+	enum qdf_proto_subtype subtype;
+
+	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_EAPOL) &&
+		qdf_nbuf_is_ipv4_eapol_pkt(skb) == true) {
+
+		eapol_key_info = (uint16_t)(*(uint16_t *)
+					(skb->data + EAPOL_KEY_INFO_OFFSET));
 
-		case QDF_DP_TRACE_DROP_PACKET_RECORD:
-		case QDF_DP_TRACE_HDD_PACKET_RECORD:
-		case QDF_DP_TRACE_CE_PACKET_RECORD:
-			qdf_mem_copy(rec->data, data, size);
+		mask = eapol_key_info & EAPOL_MASK;
+		switch (mask) {
+		case EAPOL_M1_BIT_MASK:
+			subtype = QDF_PROTO_EAPOL_M1;
 			break;
-		default:
+		case EAPOL_M2_BIT_MASK:
+			subtype = QDF_PROTO_EAPOL_M2;
+			break;
+		case EAPOL_M3_BIT_MASK:
+			subtype = QDF_PROTO_EAPOL_M3;
 			break;
+		case EAPOL_M4_BIT_MASK:
+			subtype = QDF_PROTO_EAPOL_M4;
+			break;
+		default:
+			subtype = QDF_PROTO_INVALID;
 		}
+		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_EAPOL_PACKET_RECORD,
+			session_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
+			(skb->data + QDF_NBUF_DEST_MAC_OFFSET),
+			QDF_PROTO_TYPE_EAPOL, subtype,
+			event_type == WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED ?
+			 QDF_RX : QDF_TX));
+		qdf_event_eapol_log(skb, event_type, eapol_key_info);
+		QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
+		return true;
 	}
-	rec->time = qdf_get_log_timestamp();
-	rec->pid = (in_interrupt() ? 0 : current->pid);
-	spin_unlock_bh(&l_dp_trace_lock);
+	return false;
+}
+EXPORT_SYMBOL(qdf_log_eapol_pkt);
+
+/**
+ * qdf_log_dhcp_pkt() - log DHCP packet
+ * @session_id: vdev_id
+ * @skb: skb pointer
+ * @event_type: event_type
+ *
+ * Return: true/false
+ */
+bool qdf_log_dhcp_pkt(uint8_t session_id, struct sk_buff *skb,
+		      uint8_t event_type)
+{
+	enum qdf_proto_subtype subtype = QDF_PROTO_INVALID;
+
+	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_DHCP) &&
+		qdf_nbuf_is_ipv4_dhcp_pkt(skb) == true) {
+
+		if ((skb->data[DHCP_OPTION53_OFFSET] == DHCP_OPTION53) &&
+		    (skb->data[DHCP_OPTION53_LENGTH_OFFSET] ==
+						 DHCP_OPTION53_LENGTH)) {
+
+			switch (skb->data[DHCP_OPTION53_STATUS_OFFSET]) {
+			case DHCPDISCOVER:
+				subtype = QDF_PROTO_DHCP_DISCOVER;
+				break;
+			case DHCPREQUEST:
+				subtype = QDF_PROTO_DHCP_REQUEST;
+				break;
+			case DHCPOFFER:
+				subtype = QDF_PROTO_DHCP_OFFER;
+				break;
+			case DHCPACK:
+				subtype = QDF_PROTO_DHCP_ACK;
+				break;
+			case DHCPNAK:
+				subtype = QDF_PROTO_DHCP_NACK;
+				break;
+			case DHCPRELEASE:
+				subtype = QDF_PROTO_DHCP_RELEASE;
+				break;
+			case DHCPINFORM:
+				subtype = QDF_PROTO_DHCP_INFORM;
+				break;
+			case DHCPDECLINE:
+				subtype = QDF_PROTO_DHCP_DECLINE;
+				break;
+			default:
+				subtype = QDF_PROTO_INVALID;
+			}
+		}
+		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_DHCP_PACKET_RECORD,
+			session_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
+			(skb->data + QDF_NBUF_DEST_MAC_OFFSET),
+			QDF_PROTO_TYPE_DHCP, subtype,
+			event_type == WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED ?
+			QDF_RX : QDF_TX));
+		QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
+		return true;
+	}
+	return false;
+}
+EXPORT_SYMBOL(qdf_log_dhcp_pkt);
+
+/**
+ * qdf_log_arp_pkt() - log ARP packet
+ * @session_id: vdev_id
+ * @skb: skb pointer
+ * @event_type: event_type
+ *
+ * Return: true/false
+ */
+bool qdf_log_arp_pkt(uint8_t session_id, struct sk_buff *skb,
+		     uint8_t event_type)
+{
+	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ARP) &&
+	     qdf_nbuf_is_ipv4_arp_pkt(skb) == true) {
+		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ARP_PACKET_RECORD,
+			session_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
+			(skb->data + QDF_NBUF_DEST_MAC_OFFSET),
+			QDF_PROTO_TYPE_ARP, QDF_PROTO_ARP_SUBTYPE,
+			event_type == WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED ?
+			QDF_RX : QDF_TX));
+		QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
+		return true;
+	}
+	return false;
+}
+EXPORT_SYMBOL(qdf_log_arp_pkt);
+
+/**
+ * qdf_dp_trace_log_pkt() - log packet type enabled through iwpriv
+ * @session_id: vdev_id
+ * @skb: skb pointer
+ * @event_type: event type
+ *
+ * Return: none
+ */
+void qdf_dp_trace_log_pkt(uint8_t session_id, struct sk_buff *skb,
+			  uint8_t event_type)
+{
+	if (qdf_dp_get_proto_bitmap()) {
+		if (qdf_log_arp_pkt(session_id,
+			skb, event_type) == false) {
+			if (qdf_log_dhcp_pkt(session_id,
+				skb, event_type) == false) {
+				if (qdf_log_eapol_pkt(session_id,
+					skb, event_type) == false) {
+					return;
+				}
+			}
+		}
+	}
+}
+EXPORT_SYMBOL(qdf_dp_trace_log_pkt);
+
+/**
+ * qdf_dp_display_proto_pkt() - display proto packet
+ * @record: dptrace record
+ * @index: index
+ *
+ * Return: none
+ */
+void qdf_dp_display_proto_pkt(struct qdf_dp_trace_record_s *record,
+			      uint16_t index)
+{
+	struct qdf_dp_trace_proto_buf *buf =
+		(struct qdf_dp_trace_proto_buf *)record->data;
+
+	qdf_print("%04d: %012llu: %s vdev_id %d", index,
+		record->time, qdf_dp_code_to_string(record->code),
+		buf->vdev_id);
+	qdf_print("SA: " MAC_ADDRESS_STR " %s DA: "
+		  MAC_ADDRESS_STR " Type %s Subtype %s",
+		MAC_ADDR_ARRAY(buf->sa.bytes), qdf_dp_dir_to_str(buf->dir),
+		MAC_ADDR_ARRAY(buf->da.bytes), qdf_dp_type_to_str(buf->type),
+		qdf_dp_subtype_to_str(buf->subtype));
+}
+EXPORT_SYMBOL(qdf_dp_display_proto_pkt);
+
+/**
+ * qdf_dp_trace_proto_pkt() - record proto packet
+ * @code: dptrace code
+ * @vdev_id: vdev id
+ * @sa: source mac address
+ * @da: destination mac address
+ * @type: proto type
+ * @subtype: proto subtype
+ * @dir: direction
+ *
+ * Return: none
+ */
+void qdf_dp_trace_proto_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
+		uint8_t *sa, uint8_t *da, enum qdf_proto_type type,
+		enum qdf_proto_subtype subtype, enum qdf_proto_dir dir)
+{
+	struct qdf_dp_trace_proto_buf buf;
+	int buf_size = sizeof(struct qdf_dp_trace_ptr_buf);
+
+	if (qdf_dp_enable_check(NULL, code) == false)
+		return;
+
+	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
+		QDF_BUG(0);
+
+	memcpy(&buf.sa, sa, QDF_NET_ETH_LEN);
+	memcpy(&buf.da, da, QDF_NET_ETH_LEN);
+	buf.dir = dir;
+	buf.type = type;
+	buf.subtype = subtype;
+	buf.vdev_id = vdev_id;
+	qdf_dp_add_record(code, (uint8_t *)&buf, buf_size);
+}
+EXPORT_SYMBOL(qdf_dp_trace_proto_pkt);
+
+/**
+ * qdf_dp_display_ptr_record() - display record
+ * @record: dptrace record
+ * @index: index
+ *
+ * Return: none
+ */
+void qdf_dp_display_ptr_record(struct qdf_dp_trace_record_s *record,
+				uint16_t index)
+{
+	struct qdf_dp_trace_ptr_buf *buf =
+		(struct qdf_dp_trace_ptr_buf *)record->data;
+
+	qdf_print("%04d: %012llu: %s msdu_id: %d, status: %d", index,
+		record->time, qdf_dp_code_to_string(record->code),
+		buf->msdu_id, buf->status);
+	dump_hex_trace("cookie", (uint8_t *)&buf->cookie, sizeof(buf->cookie));
+}
+EXPORT_SYMBOL(qdf_dp_display_ptr_record);
+
+/**
+ * qdf_dp_trace_ptr() - record dptrace
+ * @code: dptrace code
+ * @data: data
+ * @size: size of data
+ * @msdu_id: msdu_id
+ * @status: return status
+ *
+ * Return: none
+ */
+void qdf_dp_trace_ptr(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
+		uint8_t *data, uint8_t size, uint16_t msdu_id, uint16_t status)
+{
+	struct qdf_dp_trace_ptr_buf buf;
+	int buf_size = sizeof(struct qdf_dp_trace_ptr_buf);
+
+	if (qdf_dp_enable_check(nbuf, code) == false)
+		return;
+
+	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
+		QDF_BUG(0);
+
+	qdf_mem_copy(&buf.cookie, data, size);
+	buf.msdu_id = msdu_id;
+	buf.status = status;
+	qdf_dp_add_record(code, (uint8_t *)&buf, buf_size);
+}
+EXPORT_SYMBOL(qdf_dp_trace_ptr);
+
+/**
+ * qdf_dp_display_trace() - Displays a record in DP trace
+ * @pRecord  : pointer to a record in DP trace
+ * @recIndex : record index
+ *
+ * Return: None
+ */
+void qdf_dp_display_record(struct qdf_dp_trace_record_s *pRecord,
+				uint16_t recIndex)
+{
+	qdf_print("%04d: %012llu: %s", recIndex,
+		pRecord->time, qdf_dp_code_to_string(pRecord->code));
+	switch (pRecord->code) {
+	case  QDF_DP_TRACE_HDD_TX_TIMEOUT:
+		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+						"HDD TX Timeout\n");
+		break;
+	case  QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
+		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+						"HDD SoftAP TX Timeout\n");
+		break;
+	case QDF_DP_TRACE_HDD_PACKET_RECORD:
+		dump_hex_trace("DATA", pRecord->data, pRecord->size);
+		break;
+	default:
+		dump_hex_trace("cookie", pRecord->data, pRecord->size);
+	}
+}
+EXPORT_SYMBOL(qdf_dp_display_record);
+
+
+/**
+ * qdf_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 qdf_dp_trace(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
+			uint8_t *data, uint8_t size)
+{
+	if (qdf_dp_enable_check(nbuf, code) == false)
+		return;
+
+	qdf_dp_add_record(code, data, size);
 }
 EXPORT_SYMBOL(qdf_dp_trace);