From 58c8085e21dae7e0e754a1b5758c0b9a920a08d3 Mon Sep 17 00:00:00 2001 From: Venkateswara Swamy Bandaru Date: Mon, 29 Jan 2018 17:52:02 +0530 Subject: [PATCH] Revert "Revert "qcacmn: Mesh throughput enhancements"" This reverts commit I7421f3572c46ed27a2d96724b2bbbe40c0704e5f. Change-Id: I8c44b0e893f81aadf7aa4404538776f27a579d76 CRs-Fixed: 2180219 --- dp/inc/cdp_txrx_cmn_struct.h | 8 ++ dp/wifi3.0/dp_main.c | 16 +++- dp/wifi3.0/dp_tx.c | 139 ++++++++++++++++++++++++++--------- dp/wifi3.0/dp_tx.h | 6 +- qdf/linux/src/i_qdf_nbuf.h | 1 + 5 files changed, 130 insertions(+), 40 deletions(-) diff --git a/dp/inc/cdp_txrx_cmn_struct.h b/dp/inc/cdp_txrx_cmn_struct.h index a9190d7216..d525f6b385 100644 --- a/dp/inc/cdp_txrx_cmn_struct.h +++ b/dp/inc/cdp_txrx_cmn_struct.h @@ -1038,6 +1038,14 @@ struct cdp_tx_ingress_stats { uint32_t res_full; } dropped; + /* Mesh packets info */ + struct { + /* packets sent to fw */ + uint32_t exception_fw; + /* packets completions received from fw */ + uint32_t completion_fw; + } mesh; + /*Number of packets classified by CCE*/ uint32_t cce_classified; diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 5e78d5efb6..8adf6860ea 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -3030,7 +3030,10 @@ static void dp_vdev_register_wifi3(struct cdp_vdev *vdev_handle, vdev->me_convert = txrx_ops->me_convert; /* TODO: Enable the following once Tx code is integrated */ - txrx_ops->tx.tx = dp_tx_send; + if (vdev->mesh_vdev) + txrx_ops->tx.tx = dp_tx_send_mesh; + else + txrx_ops->tx.tx = dp_tx_send; txrx_ops->tx.tx_exception = dp_tx_send_exception; @@ -4335,6 +4338,8 @@ static inline void dp_aggregate_pdev_stats(struct dp_pdev *pdev) DP_STATS_AGGR(pdev, vdev, tx_i.dropped.res_full); DP_STATS_AGGR(pdev, vdev, tx_i.cce_classified); DP_STATS_AGGR(pdev, vdev, tx_i.cce_classified_raw); + DP_STATS_AGGR(pdev, vdev, tx_i.mesh.exception_fw); + DP_STATS_AGGR(pdev, vdev, tx_i.mesh.completion_fw); pdev->stats.tx_i.dropped.dropped_pkt.num = pdev->stats.tx_i.dropped.dma_error + @@ -4454,10 +4459,15 @@ dp_print_pdev_tx_stats(struct dp_pdev *pdev) DP_PRINT_STATS(" Bytes = %llu", pdev->stats.tx_i.nawds_mcast.bytes); DP_PRINT_STATS("CCE Classified:"); - DP_TRACE(FATAL, " CCE Classified Packets: %u", + DP_PRINT_STATS(" CCE Classified Packets: %u", pdev->stats.tx_i.cce_classified); - DP_TRACE(FATAL, " RAW CCE Classified Packets: %u", + DP_PRINT_STATS(" RAW CCE Classified Packets: %u", pdev->stats.tx_i.cce_classified_raw); + DP_PRINT_STATS("Mesh stats:"); + DP_PRINT_STATS(" frames to firmware: %u", + pdev->stats.tx_i.mesh.exception_fw); + DP_PRINT_STATS(" completions from fw: %u", + pdev->stats.tx_i.mesh.completion_fw); } /** diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 98c74c4f30..297c42535b 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -471,7 +471,8 @@ struct dp_tx_ext_desc_elem_s *dp_tx_prepare_ext_desc(struct dp_vdev *vdev, return NULL; } - if (qdf_unlikely(vdev->mesh_vdev)) { + if (msdu_info->exception_fw && + qdf_unlikely(vdev->mesh_vdev)) { qdf_mem_copy(&cached_ext_desc[HAL_TX_EXTENSION_DESC_LEN_BYTES], &msdu_info->meta_data[0], sizeof(struct htt_tx_msdu_desc_ext2_t)); @@ -527,7 +528,8 @@ struct dp_tx_ext_desc_elem_s *dp_tx_prepare_ext_desc(struct dp_vdev *vdev, */ static struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev, - qdf_nbuf_t nbuf, uint8_t desc_pool_id, uint32_t *meta_data, + qdf_nbuf_t nbuf, uint8_t desc_pool_id, + struct dp_tx_msdu_info_s *msdu_info, struct cdp_tx_exception_metadata *tx_exc_metadata) { uint8_t align_pad; @@ -589,8 +591,8 @@ struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev, * | | * |-----------------------------| */ - if (qdf_unlikely(vdev->mesh_vdev || - (vdev->opmode == wlan_op_mode_ocb))) { + if (qdf_unlikely((msdu_info->exception_fw)) || + (vdev->opmode == wlan_op_mode_ocb)) { align_pad = ((unsigned long) qdf_nbuf_data(nbuf)) & 0x7; if (qdf_nbuf_push_head(nbuf, align_pad) == NULL) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -599,7 +601,7 @@ struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev, } htt_hdr_size = dp_tx_prepare_htt_metadata(vdev, nbuf, - meta_data); + msdu_info->meta_data); if (htt_hdr_size == 0) goto failure; tx_desc->pkt_offset = align_pad + htt_hdr_size; @@ -699,7 +701,7 @@ static struct dp_tx_desc_s *dp_tx_prepare_desc(struct dp_vdev *vdev, tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW; qdf_atomic_inc(&pdev->num_tx_exception); #endif - if (qdf_unlikely(vdev->mesh_vdev)) + if (qdf_unlikely(msdu_info->exception_fw)) tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW; tx_desc->msdu_ext_desc = msdu_ext_desc; @@ -1180,21 +1182,22 @@ static void dp_non_std_tx_comp_free_buff(struct dp_tx_desc_s *tx_desc, * nbuf when it fails to send */ static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf, - uint8_t tid, struct dp_tx_queue *tx_q, - uint32_t *meta_data, uint16_t peer_id, + struct dp_tx_msdu_info_s *msdu_info, uint16_t peer_id, struct cdp_tx_exception_metadata *tx_exc_metadata) { struct dp_pdev *pdev = vdev->pdev; struct dp_soc *soc = pdev->soc; struct dp_tx_desc_s *tx_desc; QDF_STATUS status; + struct dp_tx_queue *tx_q = &(msdu_info->tx_queue); void *hal_srng = soc->tcl_data_ring[tx_q->ring_id].hal_srng; uint16_t htt_tcl_metadata = 0; + uint8_t tid = msdu_info->tid; HTT_TX_TCL_METADATA_VALID_HTT_SET(htt_tcl_metadata, 0); /* Setup Tx descriptor for an MSDU, and MSDU extension descriptor */ tx_desc = dp_tx_prepare_desc_single(vdev, nbuf, tx_q->desc_pool_id, - meta_data, tx_exc_metadata); + msdu_info, tx_exc_metadata); if (!tx_desc) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "%s Tx_desc prepare Fail vdev %pK queue %d\n", @@ -1500,14 +1503,14 @@ qdf_nbuf_t dp_tx_extract_mesh_meta_data(struct dp_vdev *vdev, qdf_nbuf_t nbuf, struct htt_tx_msdu_desc_ext2_t *meta_data = (struct htt_tx_msdu_desc_ext2_t *)&msdu_info->meta_data[0]; - nbuf = qdf_nbuf_unshare(nbuf); - if (nbuf == NULL) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "qdf_nbuf_unshare failed\n"); - return nbuf; + mhdr = (struct meta_hdr_s *)qdf_nbuf_data(nbuf); + + if (CB_FTYPE_MESH_TX_INFO != qdf_nbuf_get_tx_ftype(nbuf)) { + msdu_info->exception_fw = 0; + goto remove_meta_hdr; } - mhdr = (struct meta_hdr_s *)qdf_nbuf_data(nbuf); + msdu_info->exception_fw = 1; qdf_mem_set(meta_data, sizeof(struct htt_tx_msdu_desc_ext2_t), 0); @@ -1544,6 +1547,7 @@ qdf_nbuf_t dp_tx_extract_mesh_meta_data(struct dp_vdev *vdev, qdf_nbuf_t nbuf, meta_data->valid_key_flags = 1; meta_data->key_flags = (mhdr->keyix & 0x3); +remove_meta_hdr: if (qdf_nbuf_pull_head(nbuf, sizeof(struct meta_hdr_s)) == NULL) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "qdf_nbuf_pull_head failed\n"); @@ -1552,12 +1556,12 @@ qdf_nbuf_t dp_tx_extract_mesh_meta_data(struct dp_vdev *vdev, qdf_nbuf_t nbuf, } QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "%s , Meta hdr %0x %0x %0x %0x %0x\n", + "%s , Meta hdr %0x %0x %0x %0x %0x to_fw %d\n", __func__, msdu_info->meta_data[0], msdu_info->meta_data[1], msdu_info->meta_data[2], msdu_info->meta_data[3], - msdu_info->meta_data[4]); + msdu_info->meta_data[4], msdu_info->exception_fw); return nbuf; } @@ -1584,7 +1588,7 @@ qdf_nbuf_t dp_tx_extract_mesh_meta_data(struct dp_vdev *vdev, qdf_nbuf_t nbuf, * return: NULL on success nbuf on failure */ static qdf_nbuf_t dp_tx_prepare_nawds(struct dp_vdev *vdev, qdf_nbuf_t nbuf, - uint8_t tid, struct dp_tx_queue *tx_q, uint32_t *meta_data) + struct dp_tx_msdu_info_s *msdu_info) { struct dp_peer *peer = NULL; struct dp_soc *soc = vdev->pdev->soc; @@ -1622,8 +1626,8 @@ static qdf_nbuf_t dp_tx_prepare_nawds(struct dp_vdev *vdev, qdf_nbuf_t nbuf, } peer_id = peer->peer_ids[0]; - nbuf_copy = dp_tx_send_msdu_single(vdev, nbuf_copy, tid, - tx_q, meta_data, peer_id, NULL); + nbuf_copy = dp_tx_send_msdu_single(vdev, nbuf_copy, + msdu_info, peer_id, NULL); if (nbuf_copy != NULL) { qdf_nbuf_free(nbuf_copy); continue; @@ -1674,7 +1678,11 @@ qdf_nbuf_t dp_tx_send_exception(void *vap_dev, qdf_nbuf_t nbuf, { struct ether_header *eh = NULL; struct dp_vdev *vdev = (struct dp_vdev *) vap_dev; - struct dp_tx_queue tx_queue; + struct dp_tx_msdu_info_s msdu_info; + + qdf_mem_set(&msdu_info, sizeof(msdu_info), 0x0); + + msdu_info.tid = tx_exc_metadata->tid; eh = (struct ether_header *)qdf_nbuf_data(nbuf); QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, @@ -1731,7 +1739,7 @@ qdf_nbuf_t dp_tx_send_exception(void *vap_dev, qdf_nbuf_t nbuf, * With each ring, we also associate a unique Tx descriptor pool * to minimize lock contention for these resources. */ - dp_tx_get_queue(vdev, nbuf, &tx_queue); + dp_tx_get_queue(vdev, nbuf, &msdu_info.tx_queue); /* Reset the control block */ qdf_nbuf_reset_ctxt(nbuf); @@ -1742,8 +1750,8 @@ qdf_nbuf_t dp_tx_send_exception(void *vap_dev, qdf_nbuf_t nbuf, * prepare direct-buffer type TCL descriptor and enqueue to TCL * SRNG. There is no need to setup a MSDU extension descriptor. */ - nbuf = dp_tx_send_msdu_single(vdev, nbuf, tx_exc_metadata->tid, - &tx_queue, NULL, tx_exc_metadata->peer_id, tx_exc_metadata); + nbuf = dp_tx_send_msdu_single(vdev, nbuf, &msdu_info, + tx_exc_metadata->peer_id, tx_exc_metadata); return nbuf; @@ -1753,6 +1761,63 @@ fail: return nbuf; } +/** + * dp_tx_send_mesh() - Transmit mesh frame on a given VAP + * @vap_dev: DP vdev handle + * @nbuf: skb + * + * Entry point for Core Tx layer (DP_TX) invoked from + * hard_start_xmit in OSIF/HDD + * + * Return: NULL on success, + * nbuf when it fails to send + */ +#ifdef MESH_MODE_SUPPORT +qdf_nbuf_t dp_tx_send_mesh(void *vap_dev, qdf_nbuf_t nbuf) +{ + struct meta_hdr_s *mhdr; + qdf_nbuf_t nbuf_mesh = NULL; + qdf_nbuf_t nbuf_clone = NULL; + struct dp_vdev *vdev = (struct dp_vdev *) vap_dev; + + nbuf_mesh = qdf_nbuf_unshare(nbuf); + if (nbuf_mesh == NULL) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "qdf_nbuf_unshare failed\n"); + return nbuf; + } + nbuf = nbuf_mesh; + + mhdr = (struct meta_hdr_s *)qdf_nbuf_data(nbuf); + if (mhdr->flags & METAHDR_FLAG_INFO_UPDATED) { + nbuf_clone = qdf_nbuf_clone(nbuf); + if (nbuf_clone == NULL) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "qdf_nbuf_clone failed\n"); + return nbuf; + } + qdf_nbuf_set_tx_ftype(nbuf_clone, CB_FTYPE_MESH_TX_INFO); + } + + if (nbuf_clone) { + if (!dp_tx_send(vap_dev, nbuf_clone)) { + DP_STATS_INC(vdev, tx_i.mesh.exception_fw, 1); + } else + qdf_nbuf_free(nbuf_clone); + } + + qdf_nbuf_set_tx_ftype(nbuf, CB_FTYPE_INVALID); + return dp_tx_send(vap_dev, nbuf); +} + +#else + +qdf_nbuf_t dp_tx_send_mesh(void *vap_dev, qdf_nbuf_t nbuf) +{ + return dp_tx_send(vap_dev, nbuf); +} + +#endif /** * dp_tx_send() - Transmit a frame on a given VAP @@ -1901,8 +1966,7 @@ qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf) * prepare direct-buffer type TCL descriptor and enqueue to TCL * SRNG. There is no need to setup a MSDU extension descriptor. */ - nbuf = dp_tx_send_msdu_single(vdev, nbuf, msdu_info.tid, - &msdu_info.tx_queue, msdu_info.meta_data, peer_id, NULL); + nbuf = dp_tx_send_msdu_single(vdev, nbuf, &msdu_info, peer_id, NULL); return nbuf; @@ -2039,9 +2103,7 @@ void dp_tx_reinject_handler(struct dp_tx_desc_s *tx_desc, uint8_t *status) nbuf_copy = dp_tx_send_msdu_single(vdev, nbuf_copy, - msdu_info.tid, - &msdu_info.tx_queue, - msdu_info.meta_data, + &msdu_info, peer_id, NULL); @@ -2067,9 +2129,9 @@ void dp_tx_reinject_handler(struct dp_tx_desc_s *tx_desc, uint8_t *status) 1, qdf_nbuf_len(nbuf)); nbuf = dp_tx_send_msdu_single(vdev, - nbuf, msdu_info.tid, - &msdu_info.tx_queue, - msdu_info.meta_data, peer_id, NULL); + nbuf, + &msdu_info, + peer_id, NULL); if (nbuf) { QDF_TRACE(QDF_MODULE_ID_DP, @@ -2225,10 +2287,14 @@ static inline void dp_tx_comp_free_buf(struct dp_soc *soc, nbuf) == QDF_STATUS_SUCCESS) return; - if (!vdev->mesh_vdev) { + if (qdf_likely(!vdev->mesh_vdev)) qdf_nbuf_free(nbuf); - } else { - vdev->osif_tx_free_ext((nbuf)); + else { + if (desc->flags & DP_TX_DESC_FLAG_TO_FW) { + qdf_nbuf_free(nbuf); + DP_STATS_INC(vdev, tx_i.mesh.completion_fw, 1); + } else + vdev->osif_tx_free_ext((nbuf)); } } @@ -2528,7 +2594,8 @@ static inline void dp_tx_comp_process_tx_status(struct dp_tx_desc_s *tx_desc, (ts.status == HAL_TX_TQM_RR_REM_CMD_REM)); /* Update per-packet stats */ - if (qdf_unlikely(vdev->mesh_vdev)) + if (qdf_unlikely(vdev->mesh_vdev) && + !(tx_desc->flags & DP_TX_DESC_FLAG_TO_FW)) dp_tx_comp_fill_tx_completion_stats(tx_desc, &ts); /* Update peer level stats */ diff --git a/dp/wifi3.0/dp_tx.h b/dp/wifi3.0/dp_tx.h index 9d1f66d0c0..01a1df752b 100644 --- a/dp/wifi3.0/dp_tx.h +++ b/dp/wifi3.0/dp_tx.h @@ -115,6 +115,8 @@ struct dp_tx_queue { * @u.tso_info: TSO information for TSO frame types * (chain of the TSO segments, number of segments) * @u.sg_info: Scatter Gather information for non-TSO SG frames + * @meta_data: Mesh meta header information + * @exception_fw: Duplicate frame to be sent to firmware * * This structure holds the complete MSDU information needed to program the * Hardware TCL and MSDU extension descriptors for different frame types @@ -129,7 +131,8 @@ struct dp_tx_msdu_info_s { struct qdf_tso_info_t tso_info; struct dp_tx_sg_info_s sg_info; } u; - uint32_t meta_data[5]; + uint32_t meta_data[6]; + uint8_t exception_fw; }; QDF_STATUS dp_tx_vdev_attach(struct dp_vdev *vdev); @@ -145,6 +148,7 @@ QDF_STATUS dp_tx_pdev_attach(struct dp_pdev *pdev); qdf_nbuf_t dp_tx_send(void *data_vdev, qdf_nbuf_t nbuf); qdf_nbuf_t dp_tx_send_exception(void *data_vdev, qdf_nbuf_t nbuf, struct cdp_tx_exception_metadata *tx_exc); +qdf_nbuf_t dp_tx_send_mesh(void *data_vdev, qdf_nbuf_t nbuf); #ifdef CONVERGED_TDLS_ENABLE qdf_nbuf_t dp_tx_non_std(struct cdp_vdev *vdev_handle, diff --git a/qdf/linux/src/i_qdf_nbuf.h b/qdf/linux/src/i_qdf_nbuf.h index 8081e4be2b..4fe15a2583 100644 --- a/qdf/linux/src/i_qdf_nbuf.h +++ b/qdf/linux/src/i_qdf_nbuf.h @@ -585,6 +585,7 @@ typedef enum { CB_FTYPE_INTRABSS_FWD = 5, CB_FTYPE_RX_INFO = 6, CB_FTYPE_MESH_RX_INFO = 7, + CB_FTYPE_MESH_TX_INFO = 8, } CB_FTYPE; /*