From eaa20d87514eccdc55f4ef30d0d4221928ece01d Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Mon, 25 Apr 2016 18:01:05 +0530 Subject: [PATCH] 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 --- hif/src/ce/ce_main.c | 2 +- hif/src/ce/ce_service.c | 7 +- htc/htc_send.c | 4 +- qdf/inc/qdf_nbuf.h | 121 ++++++- qdf/inc/qdf_trace.h | 99 +++++- qdf/linux/src/i_qdf_nbuf.h | 10 + qdf/linux/src/qdf_nbuf.c | 90 +++++ qdf/linux/src/qdf_trace.c | 682 +++++++++++++++++++++++++++++++------ 8 files changed, 872 insertions(+), 143 deletions(-) diff --git a/hif/src/ce/ce_main.c b/hif/src/ce/ce_main.c index 90a2613f2585..0052889a5d25 100644 --- a/hif/src/ce/ce_main.c +++ b/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); diff --git a/hif/src/ce/ce_service.c b/hif/src/ce/ce_service.c index 26a326ad5a94..625673bd930d 100644 --- a/hif/src/ce/ce_service.c +++ b/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 */ diff --git a/htc/htc_send.c b/htc/htc_send.c index 858767a88dcd..a7ffd2b4a748 100644 --- a/htc/htc_send.c +++ b/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 */ diff --git a/qdf/inc/qdf_nbuf.h b/qdf/inc/qdf_nbuf.h index e16b3e43fea6..9689ba59a829 100644 --- a/qdf/inc/qdf_nbuf.h +++ b/qdf/inc/qdf_nbuf.h @@ -40,13 +40,33 @@ #include #include -#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 * diff --git a/qdf/inc/qdf_trace.h b/qdf/inc/qdf_trace.h index 3d1d6a13a952..39cae4014219 100644 --- a/qdf/inc/qdf_trace.h +++ b/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); /** diff --git a/qdf/linux/src/i_qdf_nbuf.h b/qdf/linux/src/i_qdf_nbuf.h index 68be6a150503..de3a7fef9abe 100644 --- a/qdf/linux/src/i_qdf_nbuf.h +++ b/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 diff --git a/qdf/linux/src/qdf_nbuf.c b/qdf/linux/src/qdf_nbuf.c index 74a46c5db0b6..38f507c1d736 100644 --- a/qdf/linux/src/qdf_nbuf.c +++ b/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 diff --git a/qdf/linux/src/qdf_trace.c b/qdf/linux/src/qdf_trace.c index 938773759894..1c5ed3291677 100644 --- a/qdf/linux/src/qdf_trace.c +++ b/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) + 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_MEDIUM - && (code <= QDF_DP_TRACE_HIF_PACKET_PTR_RECORD)) - 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; + switch (dir) { + case QDF_TX: + return "->"; + case QDF_RX: + return "<-"; + default: + return "invalid"; + } +} +EXPORT_SYMBOL(qdf_dp_dir_to_str); +/** + * 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); + +/** + * 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); + +/** + * 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; + return false; - /* 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; + if (qdf_dp_trace_enable_track(code) == false) + return false; - default: - return; - } - } + if ((nbuf) && ((QDF_NBUF_CB_TX_PACKET_TRACK(nbuf) != + QDF_NBUF_TX_PKT_DATA_TRACK) || + (!QDF_NBUF_CB_TX_DP_TRACE(nbuf)))) + return false; - /* Return when the packet is not a data packet */ - if (QDF_NBUF_GET_PACKET_TRACK(nbuf) != QDF_NBUF_TX_PKT_DATA_TRACK) - return; - - /* 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; - - /* Acquire the lock so that only one thread at a time can fill the ring - * buffer - */ - -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; - - 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); - break; - default: - 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)); + + mask = eapol_key_info & EAPOL_MASK; + switch (mask) { + case EAPOL_M1_BIT_MASK: + subtype = QDF_PROTO_EAPOL_M1; + break; + 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; + } + 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);