Explorar o código

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
Nirav Shah %!s(int64=8) %!d(string=hai) anos
pai
achega
7f337dbb7a

+ 6 - 1
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);
 

+ 2 - 23
core/dp/htt/htt_t2h.c

@@ -50,6 +50,7 @@
 #include <ol_htt_tx_api.h>
 #include <ol_txrx_peer_find.h>
 #include <cdp_txrx_ipa.h>
+#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

+ 0 - 1
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 */
 

+ 2 - 0
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_ */

+ 14 - 1
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_ */

+ 195 - 0
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 */

+ 91 - 72
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);
-
-			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
-			 */
-		}
+		if (pl_dev->mt_pktlog_enabled == false)
+			fill_ieee80211_hdr_data(txrx_pdev, &pl_msdu_info, data);
+
 		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,

+ 4 - 1
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)