From 0da3122669b621009dee3750fa2a626233e64e2c Mon Sep 17 00:00:00 2001 From: Dhanashri Atre Date: Thu, 23 Mar 2017 12:30:58 -0700 Subject: [PATCH] qcacmn: Lithium LRO Support in the Data Path Add support to extract LRO information provided by the hardware and utilize the support provided by QDF to perform LRO. Change-Id: I00a26573a450e9c32586b3d5fb656dbfe802cfac CRs-Fixed: 1107169 --- dp/wifi3.0/dp_main.c | 16 +++++++- dp/wifi3.0/dp_rx.c | 71 +++++++++++++++++++++++++++++++-- dp/wifi3.0/dp_rx.h | 4 +- dp/wifi3.0/dp_types.h | 3 ++ dp/wifi3.0/hal_rx.h | 91 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 179 insertions(+), 6 deletions(-) diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index f8ad8684f739..db6009119ae0 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -284,7 +285,7 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) for (ring = 0; ring < soc->num_reo_dest_rings; ring++) { if (rx_mask & (1 << ring)) { work_done = - dp_rx_process(soc, + dp_rx_process(int_ctx, soc->reo_dest_ring[ring].hal_srng, budget); budget -= work_done; @@ -312,6 +313,8 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) } } + qdf_lro_flush(int_ctx->lro_ctx); + budget_done: return dp_budget - budget; } @@ -361,6 +364,7 @@ static QDF_STATUS dp_soc_interrupt_attach(void *txrx_soc) soc->intr_ctx[i].rx_wbm_rel_ring_mask = 0x1; soc->intr_ctx[i].reo_status_ring_mask = 0x1; soc->intr_ctx[i].soc = soc; + soc->intr_ctx[i].lro_ctx = qdf_lro_init(); } qdf_timer_init(soc->osdev, &soc->int_timer, @@ -455,6 +459,7 @@ static QDF_STATUS dp_soc_interrupt_attach(void *txrx_soc) return QDF_STATUS_E_FAILURE; } + soc->intr_ctx[i].lro_ctx = qdf_lro_init(); } hif_configure_ext_group_interrupts(soc->hif_handle); @@ -477,6 +482,7 @@ static void dp_soc_interrupt_detach(void *txrx_soc) soc->intr_ctx[i].tx_ring_mask = 0; soc->intr_ctx[i].rx_ring_mask = 0; soc->intr_ctx[i].rx_mon_ring_mask = 0; + qdf_lro_deinit(soc->intr_ctx[i].lro_ctx); } } #endif @@ -1623,6 +1629,14 @@ static struct cdp_vdev *dp_vdev_attach_wifi3(struct cdp_pdev *txrx_pdev, dp_lro_hash_setup(soc); + /* LRO */ + if (wlan_cfg_is_lro_enabled(soc->wlan_cfg_ctx) && + wlan_op_mode_sta == vdev->opmode) + vdev->lro_enable = true; + + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "LRO: vdev_id %d lro_enable %d", vdev_id, vdev->lro_enable); + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "Created vdev %p (%pM)", vdev, vdev->mac_addr.raw); DP_STATS_INIT(vdev); diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 6721014b3efa..3efb73884cd8 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -568,6 +568,66 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) } #endif +/** + * dp_rx_lro() - LRO related processing + * @rx_tlv: TLV data extracted from the rx packet + * @peer: destination peer of the msdu + * @msdu: network buffer + * @ctx: LRO context + * + * This function performs the LRO related processing of the msdu + * + * Return: true: LRO enabled false: LRO is not enabled + */ +#if defined(FEATURE_LRO) +static bool dp_rx_lro(uint8_t *rx_tlv, struct dp_peer *peer, + qdf_nbuf_t msdu, qdf_lro_ctx_t ctx) +{ + qdf_assert(rx_tlv); + if (peer->vdev->lro_enable && + HAL_RX_TLV_GET_TCP_PROTO(rx_tlv)) { + QDF_NBUF_CB_RX_LRO_ELIGIBLE(msdu) = + HAL_RX_TLV_GET_LRO_ELIGIBLE(rx_tlv) && + !HAL_RX_TLV_GET_TCP_PURE_ACK(rx_tlv); + + if (QDF_NBUF_CB_RX_LRO_ELIGIBLE(msdu)) { + QDF_NBUF_CB_RX_LRO_CTX(msdu) = ctx; + QDF_NBUF_CB_RX_TCP_ACK_NUM(msdu) = + HAL_RX_TLV_GET_TCP_ACK(rx_tlv); + QDF_NBUF_CB_RX_TCP_WIN(msdu) = + HAL_RX_TLV_GET_TCP_WIN(rx_tlv); + QDF_NBUF_CB_RX_TCP_SEQ_NUM(msdu) = + HAL_RX_TLV_GET_TCP_SEQ(rx_tlv); + QDF_NBUF_CB_RX_TCP_CHKSUM(msdu) = + HAL_RX_TLV_GET_TCP_CHKSUM + (rx_tlv); + QDF_NBUF_CB_RX_FLOW_ID_TOEPLITZ(msdu) = + HAL_RX_TLV_GET_FLOW_ID_TOEPLITZ + (rx_tlv); + QDF_NBUF_CB_RX_TCP_OFFSET(msdu) = + HAL_RX_TLV_GET_TCP_OFFSET + (rx_tlv); + QDF_NBUF_CB_RX_IPV6_PROTO(msdu) = + HAL_RX_TLV_GET_IPV6(rx_tlv); + + QDF_NBUF_CB_RX_LRO_ELIGIBLE(msdu) = + qdf_lro_update_info(ctx, msdu); + } + /* LRO 'enabled' packet, it may not be LRO 'eligible' */ + return true; + } + + /* LRO not supported on this vdev or a non-TCP packet */ + return false; +} +#else +static bool dp_rx_lro(uint8_t *rx_tlv, struct dp_peer *peer, + qdf_nbuf_t msdu, qdf_lro_ctx_t ctx) +{ + return false; +} +#endif + /** * dp_rx_process() - Brain of the Rx processing functionality * Called from the bottom half (tasklet/NET_RX_SOFTIRQ) @@ -581,11 +641,11 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) * Return: uint32_t: No. of elements processed */ uint32_t -dp_rx_process(struct dp_soc *soc, void *hal_ring, uint32_t quota) +dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, uint32_t quota) { void *hal_soc; void *ring_desc; - struct dp_rx_desc *rx_desc; + struct dp_rx_desc *rx_desc = NULL; qdf_nbuf_t nbuf; union dp_rx_desc_list_elem_t *head[MAX_PDEV_CNT] = { NULL }; union dp_rx_desc_list_elem_t *tail[MAX_PDEV_CNT] = { NULL }; @@ -611,6 +671,7 @@ dp_rx_process(struct dp_soc *soc, void *hal_ring, uint32_t quota) struct dp_pdev *pdev; struct dp_srng *dp_rxdma_srng; struct rx_desc_pool *rx_desc_pool; + struct dp_soc *soc = int_ctx->soc; DP_HIST_INIT(); /* Debug -- Remove later */ @@ -915,6 +976,10 @@ done: continue; /* Get next descriptor */ rx_bufs_used++; + + if (!dp_rx_lro(rx_tlv_hdr, peer, nbuf, int_ctx->lro_ctx)) + QDF_NBUF_CB_RX_LRO_CTX(nbuf) = NULL; + DP_RX_LIST_APPEND(deliver_list_head, deliver_list_tail, nbuf); @@ -951,8 +1016,8 @@ done: dp_rx_deliver_raw(vdev, deliver_list_head); else if (qdf_likely(vdev->osif_rx) && deliver_list_head) vdev->osif_rx(vdev->osif_vdev, deliver_list_head); - } + return rx_bufs_used; /* Assume no scale factor for now */ } diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index f730e9ca63d2..88ef0e52d367 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -163,8 +163,8 @@ QDF_STATUS dp_rx_pdev_attach(struct dp_pdev *pdev); void dp_rx_pdev_detach(struct dp_pdev *pdev); -uint32_t dp_rx_process(struct dp_soc *soc, void *hal_ring, uint32_t quota); - +uint32_t +dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, uint32_t quota); uint32_t dp_rx_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota); diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 3ece8f4497e1..541cb9a07d80 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -321,6 +322,7 @@ struct dp_intr { uint8_t reo_status_ring_mask; /* REO command response ring */ struct dp_soc *soc; /* Reference to SoC structure , to get DMA ring handles */ + qdf_lro_ctx_t lro_ctx; }; #define REO_DESC_FREELIST_SIZE 64 @@ -919,6 +921,7 @@ struct dp_vdev { /* VDEV Stats */ struct cdp_vdev_stats stats; + bool lro_enable; }; diff --git a/dp/wifi3.0/hal_rx.h b/dp/wifi3.0/hal_rx.h index 23f3028c7ba0..d96507283633 100644 --- a/dp/wifi3.0/hal_rx.h +++ b/dp/wifi3.0/hal_rx.h @@ -614,6 +614,97 @@ hal_rx_mpdu_peer_meta_data_get(uint8_t *buf) RX_MSDU_END_9_L3_HEADER_PADDING_LSB)) #endif +/** +* LRO information needed from the TLVs +*/ +#define HAL_RX_TLV_GET_LRO_ELIGIBLE(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_9_LRO_ELIGIBLE_OFFSET)), \ + RX_MSDU_END_9_LRO_ELIGIBLE_MASK, \ + RX_MSDU_END_9_LRO_ELIGIBLE_LSB)) + +#define HAL_RX_TLV_GET_TCP_CHKSUM(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_1_TCP_UDP_CHKSUM_OFFSET)), \ + RX_MSDU_END_1_TCP_UDP_CHKSUM_MASK, \ + RX_MSDU_END_1_TCP_UDP_CHKSUM_LSB)) + +#define HAL_RX_TLV_GET_TCP_ACK(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_8_TCP_ACK_NUMBER_OFFSET)), \ + RX_MSDU_END_8_TCP_ACK_NUMBER_MASK, \ + RX_MSDU_END_8_TCP_ACK_NUMBER_LSB)) + +#define HAL_RX_TLV_GET_TCP_SEQ(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_7_TCP_SEQ_NUMBER_OFFSET)), \ + RX_MSDU_END_7_TCP_SEQ_NUMBER_MASK, \ + RX_MSDU_END_7_TCP_SEQ_NUMBER_LSB)) + +#define HAL_RX_TLV_GET_TCP_WIN(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_9_WINDOW_SIZE_OFFSET)), \ + RX_MSDU_END_9_WINDOW_SIZE_MASK, \ + RX_MSDU_END_9_WINDOW_SIZE_LSB)) + +#define HAL_RX_TLV_GET_TCP_PURE_ACK(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_start_tlv.rx_msdu_start), \ + RX_MSDU_START_2_TCP_ONLY_ACK_OFFSET)), \ + RX_MSDU_START_2_TCP_ONLY_ACK_MASK, \ + RX_MSDU_START_2_TCP_ONLY_ACK_LSB)) + +#define HAL_RX_TLV_GET_TCP_PROTO(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_start_tlv.rx_msdu_start), \ + RX_MSDU_START_2_TCP_PROTO_OFFSET)), \ + RX_MSDU_START_2_TCP_PROTO_MASK, \ + RX_MSDU_START_2_TCP_PROTO_LSB)) + +#define HAL_RX_TLV_GET_IPV6(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_start_tlv.rx_msdu_start), \ + RX_MSDU_START_2_IPV6_PROTO_OFFSET)), \ + RX_MSDU_START_2_IPV6_PROTO_MASK, \ + RX_MSDU_START_2_IPV6_PROTO_LSB)) + +#define HAL_RX_TLV_GET_IP_OFFSET(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_start_tlv.rx_msdu_start), \ + RX_MSDU_START_1_L3_OFFSET_OFFSET)), \ + RX_MSDU_START_1_L3_OFFSET_MASK, \ + RX_MSDU_START_1_L3_OFFSET_LSB)) + +#define HAL_RX_TLV_GET_TCP_OFFSET(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_start_tlv.rx_msdu_start), \ + RX_MSDU_START_1_L4_OFFSET_OFFSET)), \ + RX_MSDU_START_1_L4_OFFSET_MASK, \ + RX_MSDU_START_1_L4_OFFSET_LSB)) + +#define HAL_RX_TLV_GET_FLOW_ID_TOEPLITZ(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_start_tlv.rx_msdu_start), \ + RX_MSDU_START_4_FLOW_ID_TOEPLITZ_OFFSET)), \ + RX_MSDU_START_4_FLOW_ID_TOEPLITZ_MASK, \ + RX_MSDU_START_4_FLOW_ID_TOEPLITZ_LSB)) + /** * hal_rx_msdu_end_l3_hdr_padding_get(): API to get the * l3_header padding from rx_msdu_end TLV