From 7f337dbb7ab82382141291c56b793df0cca76f84 Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Wed, 25 May 2016 10:49:02 +0530 Subject: [PATCH] qcacld-3.0: Use different copy engine for packetlog Create new endpoint and use CE11 for packetlog messages from target to host. CRs-Fixed: 995628 Change-Id: I0df597468b0b7399dc545b5a4d4fd1a4c04a1df0 --- core/cds/src/cds_api.c | 7 +- core/dp/htt/htt_t2h.c | 25 +--- core/dp/txrx/ol_txrx.c | 1 - core/dp/txrx/ol_txrx.h | 2 + core/utils/pktlog/include/pktlog_ac.h | 15 +- core/utils/pktlog/pktlog_ac.c | 195 ++++++++++++++++++++++++++ core/utils/pktlog/pktlog_internal.c | 161 +++++++++++---------- target/inc/htc_services.h | 5 +- 8 files changed, 313 insertions(+), 98 deletions(-) diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index 393ffff08477..670f08e945dc 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -57,7 +57,8 @@ #include "cds_utils.h" #include "wlan_logging_sock_svc.h" #include "wma.h" - +#include "ol_txrx.h" +#include "pktlog_ac.h" #include "wlan_hdd_ipa.h" /* Preprocessor Definitions and Constants */ @@ -550,6 +551,10 @@ QDF_STATUS cds_pre_enable(v_CONTEXT_t cds_context) return QDF_STATUS_E_FAILURE; } + /* call Packetlog connect service */ + htt_pkt_log_init(gp_cds_context->pdev_txrx_ctx, scn); + pktlog_htc_attach(); + /* Reset wma wait event */ qdf_event_reset(&gp_cds_context->wmaCompleteEvent); diff --git a/core/dp/htt/htt_t2h.c b/core/dp/htt/htt_t2h.c index 63fbe2eab7ce..08eb3c28f991 100644 --- a/core/dp/htt/htt_t2h.c +++ b/core/dp/htt/htt_t2h.c @@ -50,6 +50,7 @@ #include #include #include +#include "pktlog_ac.h" /*--- target->host HTT message dispatch function ----------------------------*/ @@ -315,29 +316,7 @@ void htt_t2h_lp_msg_handler(void *context, qdf_nbuf_t htt_t2h_msg, #ifndef REMOVE_PKT_LOG case HTT_T2H_MSG_TYPE_PKTLOG: { - uint32_t *pl_hdr; - uint32_t log_type; - pl_hdr = (msg_word + 1); - log_type = - (*(pl_hdr + 1) & ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> - ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; - if ((log_type == PKTLOG_TYPE_TX_CTRL) - || (log_type == PKTLOG_TYPE_TX_STAT) - || (log_type == PKTLOG_TYPE_TX_MSDU_ID) - || (log_type == PKTLOG_TYPE_TX_FRM_HDR) - || (log_type == PKTLOG_TYPE_TX_VIRT_ADDR)) - wdi_event_handler(WDI_EVENT_TX_STATUS, - pdev->txrx_pdev, pl_hdr); - else if (log_type == PKTLOG_TYPE_RC_FIND) - wdi_event_handler(WDI_EVENT_RATE_FIND, - pdev->txrx_pdev, pl_hdr); - else if (log_type == PKTLOG_TYPE_RC_UPDATE) - wdi_event_handler(WDI_EVENT_RATE_UPDATE, - pdev->txrx_pdev, pl_hdr); - else if (log_type == PKTLOG_TYPE_RX_STAT) - wdi_event_handler(WDI_EVENT_RX_DESC, - pdev->txrx_pdev, pl_hdr); - + pktlog_process_fw_msg(msg_word + 1); break; } #endif diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index a3bd7be66fbc..0618f54738ac 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -935,7 +935,6 @@ ol_txrx_pdev_post_attach(ol_txrx_pdev_handle pdev) ol_tso_seg_list_init(pdev, desc_pool_size); ol_tx_register_flow_control(pdev); - htt_pkt_log_init(pdev, osc); return 0; /* success */ diff --git a/core/dp/txrx/ol_txrx.h b/core/dp/txrx/ol_txrx.h index c65151c672d9..41f8aa5cd486 100644 --- a/core/dp/txrx/ol_txrx.h +++ b/core/dp/txrx/ol_txrx.h @@ -40,4 +40,6 @@ void ol_txrx_peer_unref_delete(struct ol_txrx_peer_t *peer); ol_txrx_vdev_handle ol_txrx_get_vdev_from_vdev_id(uint8_t vdev_id); + +void htt_pkt_log_init(struct ol_txrx_pdev_t *handle, void *scn); #endif /* _OL_TXRX__H_ */ diff --git a/core/utils/pktlog/include/pktlog_ac.h b/core/utils/pktlog/include/pktlog_ac.h index e2d895ac1a9d..7c72bbc9f23f 100644 --- a/core/utils/pktlog/include/pktlog_ac.h +++ b/core/utils/pktlog/include/pktlog_ac.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -94,9 +94,14 @@ struct ol_pktlog_dev_t { ol_ath_generic_softc_handle scn; char *name; bool tgt_pktlog_enabled; + bool mt_pktlog_enabled; + uint32_t htc_err_cnt; + uint8_t htc_endpoint; + void *htc_pdev; }; #define PKTLOG_SYSCTL_SIZE 14 +#define PKTLOG_MAX_SEND_QUEUE_DEPTH 64 /* * Linux specific pktlog state information @@ -124,6 +129,8 @@ int pktlog_setsize(struct hif_opaque_softc *scn, int32_t log_state); int pktlog_disable(struct hif_opaque_softc *scn); int pktlogmod_init(void *context); void pktlogmod_exit(void *context); +int pktlog_htc_attach(void); +void pktlog_process_fw_msg(uint32_t *msg_word); #define ol_pktlog_attach(_scn) \ do { \ @@ -158,5 +165,11 @@ static int pktlog_disable(struct hif_opaque_softc *scn) { return 0; } +static inline int pktlog_htc_attach(void) +{ + return 0; +} +static inline void pktlog_process_fw_msg(uint32_t *msg_word) +{ } #endif /* REMOVE_PKT_LOG */ #endif /* _PKTLOG_AC_H_ */ diff --git a/core/utils/pktlog/pktlog_ac.c b/core/utils/pktlog/pktlog_ac.c index 3b3f071e2d10..34c3008fa5ce 100644 --- a/core/utils/pktlog/pktlog_ac.c +++ b/core/utils/pktlog/pktlog_ac.c @@ -46,6 +46,7 @@ #include "pktlog_ac_i.h" #include "cds_api.h" #include "wma_types.h" +#include "htc.h" wdi_event_subscribe PKTLOG_TX_SUBSCRIBER; wdi_event_subscribe PKTLOG_RX_SUBSCRIBER; @@ -446,4 +447,198 @@ int pktlog_setsize(struct hif_opaque_softc *scn, int32_t size) return 0; } + +/** + * pktlog_process_fw_msg() - process packetlog message + * @buff: buffer + * + * Return: None + */ +void pktlog_process_fw_msg(uint32_t *buff) +{ + uint32_t *pl_hdr; + uint32_t log_type; + struct ol_txrx_pdev_t *txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX); + + if (!txrx_pdev) { + qdf_print("%s: txrx_pdev is NULL", __func__); + return; + } + + pl_hdr = buff; + log_type = + (*(pl_hdr + 1) & ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> + ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; + if ((log_type == PKTLOG_TYPE_TX_CTRL) + || (log_type == PKTLOG_TYPE_TX_STAT) + || (log_type == PKTLOG_TYPE_TX_MSDU_ID) + || (log_type == PKTLOG_TYPE_TX_FRM_HDR) + || (log_type == PKTLOG_TYPE_TX_VIRT_ADDR)) + wdi_event_handler(WDI_EVENT_TX_STATUS, + txrx_pdev, pl_hdr); + else if (log_type == PKTLOG_TYPE_RC_FIND) + wdi_event_handler(WDI_EVENT_RATE_FIND, + txrx_pdev, pl_hdr); + else if (log_type == PKTLOG_TYPE_RC_UPDATE) + wdi_event_handler(WDI_EVENT_RATE_UPDATE, + txrx_pdev, pl_hdr); + else if (log_type == PKTLOG_TYPE_RX_STAT) + wdi_event_handler(WDI_EVENT_RX_DESC, + txrx_pdev, pl_hdr); + +} + +/** + * pktlog_t2h_msg_handler() - Target to host message handler + * @context: pdev context + * @pkt: HTC packet + * + * Return: None + */ +void pktlog_t2h_msg_handler(void *context, HTC_PACKET *pkt) +{ + struct ol_pktlog_dev_t *pdev = (struct ol_pktlog_dev_t *)context; + qdf_nbuf_t pktlog_t2h_msg = (qdf_nbuf_t) pkt->pPktContext; + uint32_t *msg_word; + + /* check for successful message reception */ + if (pkt->Status != A_OK) { + if (pkt->Status != A_ECANCELED) + pdev->htc_err_cnt++; + qdf_nbuf_free(pktlog_t2h_msg); + return; + } + + /* confirm alignment */ + qdf_assert((((unsigned long)qdf_nbuf_data(pktlog_t2h_msg)) & 0x3) == 0); + + msg_word = (uint32_t *) qdf_nbuf_data(pktlog_t2h_msg); + pktlog_process_fw_msg(msg_word); + + qdf_nbuf_free(pktlog_t2h_msg); +} + +/** + * pktlog_tx_resume_handler() - resume callback + * @context: pdev context + * + * Return: None + */ +void pktlog_tx_resume_handler(void *context) +{ + qdf_print("%s: Not expected", __func__); + qdf_assert(0); +} + +/** + * pktlog_h2t_send_complete() - send complete indication + * @context: pdev context + * @htc_pkt: HTC packet + * + * Return: None + */ +void pktlog_h2t_send_complete(void *context, HTC_PACKET *htc_pkt) +{ + qdf_print("%s: Not expected", __func__); + qdf_assert(0); +} + +/** + * pktlog_h2t_full() - queue full indication + * @context: pdev context + * @pkt: HTC packet + * + * Return: HTC action + */ +HTC_SEND_FULL_ACTION pktlog_h2t_full(void *context, HTC_PACKET *pkt) +{ + return HTC_SEND_FULL_KEEP; +} + +/** + * pktlog_htc_connect_service() - create new endpoint for packetlog + * @pdev - pktlog pdev + * + * Return: 0 for success/failure + */ +int pktlog_htc_connect_service(struct ol_pktlog_dev_t *pdev) +{ + HTC_SERVICE_CONNECT_REQ connect; + HTC_SERVICE_CONNECT_RESP response; + A_STATUS status; + + qdf_mem_set(&connect, sizeof(connect), 0); + qdf_mem_set(&response, sizeof(response), 0); + + connect.pMetaData = NULL; + connect.MetaDataLength = 0; + connect.EpCallbacks.pContext = pdev; + connect.EpCallbacks.EpTxComplete = pktlog_h2t_send_complete; + connect.EpCallbacks.EpTxCompleteMultiple = NULL; + connect.EpCallbacks.EpRecv = pktlog_t2h_msg_handler; + connect.EpCallbacks.ep_resume_tx_queue = pktlog_tx_resume_handler; + + /* rx buffers currently are provided by HIF, not by EpRecvRefill */ + connect.EpCallbacks.EpRecvRefill = NULL; + connect.EpCallbacks.RecvRefillWaterMark = 1; + /* N/A, fill is done by HIF */ + + connect.EpCallbacks.EpSendFull = pktlog_h2t_full; + /* + * Specify how deep to let a queue get before htc_send_pkt will + * call the EpSendFull function due to excessive send queue depth. + */ + connect.MaxSendQueueDepth = PKTLOG_MAX_SEND_QUEUE_DEPTH; + + /* disable flow control for HTT data message service */ + connect.ConnectionFlags |= HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL; + + /* connect to control service */ + connect.service_id = PACKET_LOG_SVC; + + status = htc_connect_service(pdev->htc_pdev, &connect, &response); + + if (status != A_OK) { + pdev->mt_pktlog_enabled = false; + return -EIO; /* failure */ + } + + pdev->htc_endpoint = response.Endpoint; + pdev->mt_pktlog_enabled = true; + + return 0; /* success */ +} + +#if defined(QCA_WIFI_3_0_ADRASTEA) +/** + * pktlog_htc_attach() - attach pktlog HTC service + * + * Return: 0 for success/failure + */ +int pktlog_htc_attach(void) +{ + struct ol_txrx_pdev_t *txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX); + struct ol_pktlog_dev_t *pdev = NULL; + void *htc_pdev = cds_get_context(QDF_MODULE_ID_HTC); + + if ((!txrx_pdev) || (!txrx_pdev->pl_dev) || (!htc_pdev)) + return -EINVAL; + + pdev = txrx_pdev->pl_dev; + pdev->htc_pdev = htc_pdev; + return pktlog_htc_connect_service(pdev); +} +#else +int pktlog_htc_attach(void) +{ + struct ol_txrx_pdev_t *txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX); + struct ol_pktlog_dev_t *pdev = NULL; + + if (!txrx_pdev) + return -EINVAL; + pdev = txrx_pdev->pl_dev; + pdev->mt_pktlog_enabled = false; + return 0; +} +#endif #endif /* REMOVE_PKT_LOG */ diff --git a/core/utils/pktlog/pktlog_internal.c b/core/utils/pktlog/pktlog_internal.c index 0d219b628475..5d7083610323 100644 --- a/core/utils/pktlog/pktlog_internal.c +++ b/core/utils/pktlog/pktlog_internal.c @@ -261,6 +261,94 @@ static void process_ieee_hdr(void *data) } } +/** + * fill_ieee80211_hdr_data() - fill ieee802.11 data header + * @txrx_pdev: txrx pdev + * @pl_msdu_info: msdu info + * @data: data received from event + * + * Return: none + */ +void +fill_ieee80211_hdr_data(struct ol_txrx_pdev_t *txrx_pdev, + struct ath_pktlog_msdu_info *pl_msdu_info, void *data) +{ + uint32_t i; + uint32_t *htt_tx_desc; + struct ol_tx_desc_t *tx_desc; + uint8_t msdu_id_offset = MSDU_ID_INFO_ID_OFFSET; + uint16_t tx_desc_id; + uint32_t *msdu_id_info = (uint32_t *) + ((void *)data + sizeof(struct ath_pktlog_hdr)); + uint32_t *msdu_id = (uint32_t *) ((char *)msdu_id_info + + msdu_id_offset); + uint8_t *addr, *vap_addr; + uint8_t vdev_id; + qdf_nbuf_t netbuf; + uint32_t len; + + + pl_msdu_info->num_msdu = *msdu_id_info; + pl_msdu_info->priv_size = sizeof(uint32_t) * + pl_msdu_info->num_msdu + sizeof(uint32_t); + + for (i = 0; i < pl_msdu_info->num_msdu; i++) { + /* + * Handle big endianness + * Increment msdu_id once after retrieving + * lower 16 bits and uppper 16 bits + */ + if (!(i % 2)) { + tx_desc_id = ((*msdu_id & TX_DESC_ID_LOW_MASK) + >> TX_DESC_ID_LOW_SHIFT); + } else { + tx_desc_id = ((*msdu_id & TX_DESC_ID_HIGH_MASK) + >> TX_DESC_ID_HIGH_SHIFT); + msdu_id += 1; + } + tx_desc = ol_tx_desc_find(txrx_pdev, tx_desc_id); + qdf_assert(tx_desc); + netbuf = tx_desc->netbuf; + htt_tx_desc = (uint32_t *) tx_desc->htt_tx_desc; + qdf_assert(htt_tx_desc); + + qdf_nbuf_peek_header(netbuf, &addr, &len); + + if (len < (2 * IEEE80211_ADDR_LEN)) { + qdf_print("TX frame does not have a valid address\n"); + return; + } + /* Adding header information for the TX data frames */ + vdev_id = (uint8_t) (*(htt_tx_desc + + HTT_TX_VDEV_ID_WORD) >> + HTT_TX_VDEV_ID_SHIFT) & + HTT_TX_VDEV_ID_MASK; + + vap_addr = wma_get_vdev_address_by_vdev_id(vdev_id); + + frm_hdr.da_tail = (addr[IEEE80211_ADDR_LEN - 2] << 8) | + (addr[IEEE80211_ADDR_LEN - 1]); + frm_hdr.sa_tail = + (addr[2 * IEEE80211_ADDR_LEN - 2] << 8) | + (addr[2 * IEEE80211_ADDR_LEN - 1]); + if (vap_addr) { + frm_hdr.bssid_tail = + (vap_addr[IEEE80211_ADDR_LEN - 2] << 8) | + (vap_addr[IEEE80211_ADDR_LEN - 1]); + } else { + frm_hdr.bssid_tail = 0x0000; + } + pl_msdu_info->priv.msdu_len[i] = *(htt_tx_desc + + HTT_TX_MSDU_LEN_DWORD) + & HTT_TX_MSDU_LEN_MASK; + /* + * Add more information per MSDU + * e.g., protocol information + */ + } + +} + A_STATUS process_tx_info(struct ol_txrx_pdev_t *txrx_pdev, void *data) { /* @@ -394,83 +482,14 @@ A_STATUS process_tx_info(struct ol_txrx_pdev_t *txrx_pdev, void *data) if (pl_hdr.log_type == PKTLOG_TYPE_TX_MSDU_ID) { struct ath_pktlog_msdu_info pl_msdu_info; - uint32_t i; - uint32_t *htt_tx_desc; size_t log_size; - struct ol_tx_desc_t *tx_desc; - uint8_t msdu_id_offset = MSDU_ID_INFO_ID_OFFSET; - uint16_t tx_desc_id; - uint32_t *msdu_id_info = (uint32_t *) - ((void *)data + sizeof(struct ath_pktlog_hdr)); - uint32_t *msdu_id = (uint32_t *) ((char *)msdu_id_info + - msdu_id_offset); - uint8_t *addr, *vap_addr; - uint8_t vdev_id; - qdf_nbuf_t netbuf; - uint32_t len; qdf_mem_set(&pl_msdu_info, sizeof(pl_msdu_info), 0); - - pl_msdu_info.num_msdu = *msdu_id_info; - pl_msdu_info.priv_size = sizeof(uint32_t) * - pl_msdu_info.num_msdu + sizeof(uint32_t); log_size = sizeof(pl_msdu_info.priv); - for (i = 0; i < pl_msdu_info.num_msdu; i++) { - /* - * Handle big endianess - * Increment msdu_id once after retrieving - * lower 16 bits and uppper 16 bits - */ - if (!(i % 2)) { - tx_desc_id = ((*msdu_id & TX_DESC_ID_LOW_MASK) - >> TX_DESC_ID_LOW_SHIFT); - } else { - tx_desc_id = ((*msdu_id & TX_DESC_ID_HIGH_MASK) - >> TX_DESC_ID_HIGH_SHIFT); - msdu_id += 1; - } - tx_desc = ol_tx_desc_find(txrx_pdev, tx_desc_id); - qdf_assert(tx_desc); - netbuf = tx_desc->netbuf; - htt_tx_desc = (uint32_t *) tx_desc->htt_tx_desc; - qdf_assert(htt_tx_desc); + if (pl_dev->mt_pktlog_enabled == false) + fill_ieee80211_hdr_data(txrx_pdev, &pl_msdu_info, data); - qdf_nbuf_peek_header(netbuf, &addr, &len); - - if (len < (2 * IEEE80211_ADDR_LEN)) { - qdf_print("TX frame does not have a valid" - " address\n"); - return -1; - } - /* Adding header information for the TX data frames */ - vdev_id = (uint8_t) (*(htt_tx_desc + - HTT_TX_VDEV_ID_WORD) >> - HTT_TX_VDEV_ID_SHIFT) & - HTT_TX_VDEV_ID_MASK; - - vap_addr = wma_get_vdev_address_by_vdev_id(vdev_id); - - frm_hdr.da_tail = (addr[IEEE80211_ADDR_LEN - 2] << 8) | - (addr[IEEE80211_ADDR_LEN - 1]); - frm_hdr.sa_tail = - (addr[2 * IEEE80211_ADDR_LEN - 2] << 8) | - (addr[2 * IEEE80211_ADDR_LEN - 1]); - if (vap_addr) { - frm_hdr.bssid_tail = - (vap_addr[IEEE80211_ADDR_LEN - 2] << 8) | - (vap_addr[IEEE80211_ADDR_LEN - 1]); - } else { - frm_hdr.bssid_tail = 0x0000; - } - pl_msdu_info.priv.msdu_len[i] = *(htt_tx_desc + - HTT_TX_MSDU_LEN_DWORD) - & HTT_TX_MSDU_LEN_MASK; - /* - * Add more information per MSDU - * e.g., protocol information - */ - } pl_msdu_info.ath_msdu_info = pktlog_getbuf(pl_dev, pl_info, log_size, &pl_hdr); qdf_mem_copy((void *)&pl_msdu_info.priv.msdu_id_info, diff --git a/target/inc/htc_services.h b/target/inc/htc_services.h index 8efa640336a2..f94b0218a22d 100644 --- a/target/inc/htc_services.h +++ b/target/inc/htc_services.h @@ -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. * @@ -37,6 +37,7 @@ typedef enum { HTT_SERVICE_GROUP = 3, CFG_NV_SERVICE_GROUP = 4, WDI_IPA_SERVICE_GROUP = 5, + PACKET_LOG_SERVICE_GROUP = 6, HTC_TEST_GROUP = 254, HTC_SERVICE_GROUP_LAST = 255 } HTC_SERVICE_GROUP_IDS; @@ -60,6 +61,8 @@ typedef enum { #define HTT_DATA2_MSG_SVC MAKE_SERVICE_ID(HTT_SERVICE_GROUP,1) #define HTT_DATA3_MSG_SVC MAKE_SERVICE_ID(HTT_SERVICE_GROUP, 2) +#define PACKET_LOG_SVC MAKE_SERVICE_ID(PACKET_LOG_SERVICE_GROUP, 0) + /* raw stream service (i.e. flash, tcmd, calibration apps) */ #define HTC_RAW_STREAMS_SVC MAKE_SERVICE_ID(HTC_TEST_GROUP,0)