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
This commit is contained in:
Dhanashri Atre 2017-03-23 12:30:58 -07:00 • committed by Sandeep Puligilla
commit 0da3122669
5 changed files with 179 additions and 6 deletions

View file

@ -19,6 +19,7 @@
#include <qdf_types.h>
#include <qdf_lock.h>
#include <qdf_net_types.h>
#include <qdf_lro.h>
#include <hal_api.h>
#include <hif.h>
#include <htt.h>
@ -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);

View file

@ -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 */
}

View file

@ -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);

View file

@ -25,6 +25,7 @@
#include <qdf_atomic.h>
#include <qdf_util.h>
#include <qdf_list.h>
#include <qdf_lro.h>
#include <queue.h>
#include <htt_common.h>
@ -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;
};

View file

@ -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