From 5122f8fc485ad62ec48f307099b613f358a14471 Mon Sep 17 00:00:00 2001 From: Ishank Jain Date: Wed, 15 Mar 2017 22:22:47 +0530 Subject: [PATCH] qcacmn: Enable TSO support for QCA8074/6290 DP Add TSO support for transmit datapath of QCA8074/6290 Change-Id: Id7254859372aa43e3ed16f80c0240d1b78ae63cc CRs-Fixed: 2004658 --- dp/wifi3.0/dp_tx.c | 176 ++++++++++++++++++++++++++++++++++++++-- dp/wifi3.0/dp_tx.h | 5 -- dp/wifi3.0/dp_tx_desc.c | 109 +++++++++++++++++++++++++ dp/wifi3.0/dp_tx_desc.h | 144 ++++++++++++++++++++++++++++++++ dp/wifi3.0/dp_types.h | 35 +++++--- hal/wifi3.0/hal_tx.h | 28 +++++++ 6 files changed, 475 insertions(+), 22 deletions(-) diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 13dec6bd82..36df8d0f31 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -195,6 +195,120 @@ static uint8_t dp_tx_prepare_htt_metadata(struct dp_vdev *vdev, qdf_nbuf_t nbuf, return htt_desc_size; } +/** + * dp_tx_prepare_tso_ext_desc() - Prepare MSDU extension descriptor for TSO + * @tso_seg: TSO segment to process + * @ext_desc: Pointer to MSDU extension descriptor + * + * Return: void + */ +#if defined(FEATURE_TSO) +static void dp_tx_prepare_tso_ext_desc(struct qdf_tso_seg_t *tso_seg, + void *ext_desc) +{ + uint8_t num_frag; + uint32_t *buf_ptr; + uint32_t tso_flags; + + /* + * Set tso_en, tcp_flags(NS, CWR, ECE, URG, ACK, PSH, RST, SYN, FIN), + * tcp_flag_mask + * + * Checksum enable flags are set in TCL descriptor and not in Extension + * Descriptor (H/W ignores checksum_en flags in MSDU ext descriptor) + */ + tso_flags = *(uint32_t *) &tso_seg->tso_flags; + + hal_tx_ext_desc_set_tso_flags(ext_desc, tso_flags); + + hal_tx_ext_desc_set_msdu_length(ext_desc, tso_seg->tso_flags.l2_len, + tso_seg->tso_flags.ip_len); + + hal_tx_ext_desc_set_tcp_seq(ext_desc, tso_seg->tso_flags.tcp_seq_num); + hal_tx_ext_desc_set_ip_id(ext_desc, tso_seg->tso_flags.ip_id); + + + for (num_frag = 0; num_frag < tso_seg->num_frags; num_frag++) { + uint32_t lo = 0; + uint32_t hi = 0; + + qdf_dmaaddr_to_32s( + tso_seg->tso_frags[num_frag].paddr, &lo, &hi); + hal_tx_ext_desc_set_buffer(ext_desc, num_frag, lo, hi, + tso_seg->tso_frags[num_frag].length); + } + + return; +} +#else +static void dp_tx_prepare_tso_ext_desc(struct qdf_tso_seg_t *tso_seg, + void *ext_desc) +{ + return; +} +#endif + +/** + * dp_tx_prepare_tso() - Given a jumbo msdu, prepare the TSO info + * @vdev: virtual device handle + * @msdu: network buffer + * @msdu_info: meta data associated with the msdu + * + * Return: QDF_STATUS_SUCCESS success + */ +#if defined(FEATURE_TSO) +static QDF_STATUS dp_tx_prepare_tso(struct dp_vdev *vdev, + qdf_nbuf_t msdu, struct dp_tx_msdu_info_s *msdu_info) +{ + struct qdf_tso_seg_elem_t *tso_seg; + int num_seg = qdf_nbuf_get_tso_num_seg(msdu); + struct dp_soc *soc = vdev->pdev->soc; + struct qdf_tso_info_t *tso_info; + + tso_info = &msdu_info->u.tso_info; + tso_info->curr_seg = NULL; + tso_info->tso_seg_list = NULL; + tso_info->num_segs = num_seg; + msdu_info->frm_type = dp_tx_frm_tso; + + while (num_seg) { + tso_seg = dp_tx_tso_desc_alloc( + soc, msdu_info->tx_queue.desc_pool_id); + if (tso_seg) { + tso_seg->next = tso_info->tso_seg_list; + tso_info->tso_seg_list = tso_seg; + num_seg--; + } else { + struct qdf_tso_seg_elem_t *next_seg; + struct qdf_tso_seg_elem_t *free_seg = + tso_info->tso_seg_list; + + while (free_seg) { + next_seg = free_seg->next; + dp_tx_tso_desc_free(soc, + msdu_info->tx_queue.desc_pool_id, + free_seg); + free_seg = next_seg; + } + return QDF_STATUS_E_NOMEM; + } + } + + msdu_info->num_seg = + qdf_nbuf_get_tso_info(soc->osdev, msdu, tso_info); + + tso_info->curr_seg = tso_info->tso_seg_list; + + return QDF_STATUS_SUCCESS; +} +#else +static QDF_STATUS dp_tx_prepare_tso(struct dp_vdev *vdev, + qdf_nbuf_t msdu, struct dp_tx_msdu_info_s *msdu_info) +{ + return QDF_STATUS_E_NOMEM; +} +#endif + /** * dp_tx_prepare_ext_desc() - Allocate and prepare MSDU extension descriptor * @vdev: DP Vdev handle @@ -216,6 +330,7 @@ struct dp_tx_ext_desc_elem_s *dp_tx_prepare_ext_desc(struct dp_vdev *vdev, /* Allocate an extension descriptor */ msdu_ext_desc = dp_tx_ext_desc_alloc(soc, desc_pool_id); qdf_mem_zero(&cached_ext_desc[0], HAL_TX_EXT_DESC_WITH_META_DATA); + if (!msdu_ext_desc) return NULL; @@ -239,18 +354,24 @@ struct dp_tx_ext_desc_elem_s *dp_tx_prepare_ext_desc(struct dp_vdev *vdev, seg_info->frags[i].len); } - hal_tx_ext_desc_sync(&cached_ext_desc[0], - msdu_ext_desc->vaddr); break; case dp_tx_frm_tso: - /* Todo add support for TSO */ + dp_tx_prepare_tso_ext_desc(&msdu_info->u.tso_info.curr_seg->seg, + &cached_ext_desc[0]); break; + default: break; } + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + cached_ext_desc, HAL_TX_EXT_DESC_WITH_META_DATA); + + hal_tx_ext_desc_sync(&cached_ext_desc[0], + msdu_ext_desc->vaddr); + return msdu_ext_desc; } @@ -362,7 +483,7 @@ failure: } /** - * dp_tx_desc_prepare- Allocate and prepare Tx descriptor for multisegment frame + * dp_tx_prepare_desc() - Allocate and prepare Tx descriptor for multisegment frame * @vdev: DP vdev handle * @nbuf: skb * @msdu_info: Info to be setup in MSDU descriptor and MSDU extension descriptor @@ -395,6 +516,7 @@ static struct dp_tx_desc_s *dp_tx_prepare_desc(struct dp_vdev *vdev, /* Allocate software Tx descriptor */ tx_desc = dp_tx_desc_alloc(soc, desc_pool_id); + if (!tx_desc) return NULL; @@ -564,8 +686,11 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev, hal_tx_desc_set_addr_search_flags(hal_tx_desc_cached, HAL_TX_DESC_ADDRX_EN | HAL_TX_DESC_ADDRY_EN); - if (qdf_nbuf_get_tx_cksum(tx_desc->nbuf) == QDF_NBUF_TX_CKSUM_TCP_UDP) + if ((qdf_nbuf_get_tx_cksum(tx_desc->nbuf) == QDF_NBUF_TX_CKSUM_TCP_UDP) + || qdf_nbuf_is_tso(tx_desc->nbuf)) { + hal_tx_desc_set_l3_checksum_en(hal_tx_desc_cached, 1); hal_tx_desc_set_l4_checksum_en(hal_tx_desc_cached, 1); + } if (tid != HTT_TX_EXT_TID_INVALID) hal_tx_desc_set_hlos_tid(hal_tx_desc_cached, tid); @@ -776,8 +901,17 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, if (msdu_info->u.tso_info.curr_seg->next) { msdu_info->u.tso_info.curr_seg = msdu_info->u.tso_info.curr_seg->next; + + /* + * If this is a jumbo nbuf, then increment the number of + * nbuf users for each additional segment of the msdu. + * This will ensure that the skb is freed only after + * receiving tx completion for all segments of an nbuf + */ + qdf_nbuf_inc_users(nbuf); + /* Check with MCL if this is needed */ - /* nbuf = msdu_info->u.tso_info.curr_seg->nbuf; */ + /* nbuf = msdu_info->u.tso_info.curr_seg->nbuf; */ } } @@ -1018,12 +1152,18 @@ qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf) * SW and HW descriptors. */ if (qdf_nbuf_is_tso(nbuf)) { - /* dp_tx_prepare_tso(vdev, nbuf, &seg_info, &msdu_info); */ QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, "%s TSO frame %p\n", __func__, vdev); DP_STATS_INC_PKT(vdev, tx_i.tso.tso_pkt, 1, qdf_nbuf_len(nbuf)); + if (dp_tx_prepare_tso(vdev, nbuf, &msdu_info)) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "%s tso_prepare fail vdev_id:%d\n", + __func__, vdev->vdev_id); + return nbuf; + } + goto send_multiple; } @@ -1746,6 +1886,14 @@ QDF_STATUS dp_tx_soc_detach(struct dp_soc *soc) "%s MSDU Ext Desc Pool %d Free descs = %d\n", __func__, num_pool, num_ext_desc); + for (i = 0; i < num_pool; i++) { + dp_tx_tso_desc_pool_free(soc, i); + } + + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "%s TSO Desc Pool %d Free descs = %d\n", + __func__, num_pool, num_desc); + return QDF_STATUS_SUCCESS; } @@ -1799,6 +1947,20 @@ QDF_STATUS dp_tx_soc_attach(struct dp_soc *soc) "%s MSDU Ext Desc Alloc %d, descs = %d\n", __func__, num_pool, num_ext_desc); + for (i = 0; i < num_pool; i++) { + if (dp_tx_tso_desc_pool_alloc(soc, i, num_desc)) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "TSO Desc Pool alloc %d failed %p\n", + i, soc); + + goto fail; + } + } + + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "%s TSO Desc Alloc %d, descs = %d\n", + __func__, num_pool, num_desc); + /* Initialize descriptors in TCL Rings */ if (!wlan_cfg_per_pdev_tx_ring(soc->wlan_cfg_ctx)) { for (i = 0; i < soc->num_tcl_data_rings; i++) { diff --git a/dp/wifi3.0/dp_tx.h b/dp/wifi3.0/dp_tx.h index fa1be7c7d2..5d643a66e8 100644 --- a/dp/wifi3.0/dp_tx.h +++ b/dp/wifi3.0/dp_tx.h @@ -163,11 +163,6 @@ static inline QDF_STATUS dp_tx_flow_control(struct dp_vdev *vdev) { return QDF_STATUS_SUCCESS; } -static inline QDF_STATUS dp_tx_prepare_tso(struct dp_vdev *vdev, - qdf_nbuf_t nbuf, struct dp_tx_msdu_info_s *msdu_info) -{ - return QDF_STATUS_SUCCESS; -} static inline qdf_nbuf_t dp_tx_prepare_me(struct dp_vdev *vdev, qdf_nbuf_t nbuf, struct dp_tx_msdu_info_s *msdu_info) { diff --git a/dp/wifi3.0/dp_tx_desc.c b/dp/wifi3.0/dp_tx_desc.c index 65d923c432..66ef620d61 100644 --- a/dp/wifi3.0/dp_tx_desc.c +++ b/dp/wifi3.0/dp_tx_desc.c @@ -240,6 +240,7 @@ QDF_STATUS dp_tx_ext_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, break; } + soc->tx_ext_desc[pool_id].num_free = num_elem; TX_DESC_LOCK_CREATE(&soc->tx_ext_desc[pool_id].lock); return QDF_STATUS_SUCCESS; @@ -279,3 +280,111 @@ QDF_STATUS dp_tx_ext_desc_pool_free(struct dp_soc *soc, uint8_t pool_id) return QDF_STATUS_SUCCESS; } +/** + * dp_tx_tso_desc_pool_alloc() - allocate tx tso descriptor pool + * @soc: Handle to DP SoC structure + * @pool_id: tso descriptor pool id + * @num_elem: number of element + * + * Return: QDF_STATUS_SUCCESS + */ +#if defined(FEATURE_TSO) +QDF_STATUS dp_tx_tso_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, + uint16_t num_elem) +{ + int i; + struct qdf_tso_seg_elem_t *c_element; + struct qdf_tso_seg_elem_t *temp; + + c_element = qdf_mem_malloc(sizeof(struct qdf_tso_seg_elem_t)); + + if (!c_element) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + FL("Alloc Failed %p pool_id %d"), + soc, pool_id); + return QDF_STATUS_E_NOMEM; + } + + soc->tx_tso_desc[pool_id].freelist = c_element; + for (i = 0; i < (num_elem - 1); i++) { + c_element->next = + qdf_mem_malloc(sizeof(struct qdf_tso_seg_elem_t)); + + if (!c_element->next) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + FL("Alloc Failed %p pool_id %d"), + soc, pool_id); + goto fail; + } + + c_element = c_element->next; + c_element->next = NULL; + } + + soc->tx_tso_desc[pool_id].pool_size = num_elem; + TX_DESC_LOCK_CREATE(&soc->tx_tso_desc[pool_id].lock); + + return QDF_STATUS_SUCCESS; + +fail: + c_element = soc->tx_tso_desc[pool_id].freelist; + while (c_element) { + temp = c_element->next; + qdf_mem_free(c_element); + c_element = temp; + } + + return QDF_STATUS_E_NOMEM; +} +#else +QDF_STATUS dp_tx_tso_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, + uint16_t num_elem) +{ + return QDF_STATUS_SUCCESS; +} +#endif + +/** + * dp_tx_tso_desc_pool_free() - free tx tso descriptor pool + * @soc: Handle to DP SoC structure + * @pool_id: extension descriptor pool id + * + * Return: NONE + */ +#if defined(FEATURE_TSO) +void dp_tx_tso_desc_pool_free(struct dp_soc *soc, uint8_t pool_id) +{ + int i; + struct qdf_tso_seg_elem_t *c_element; + struct qdf_tso_seg_elem_t *temp; + + TX_DESC_LOCK_LOCK(&soc->tx_tso_desc[pool_id].lock); + c_element = soc->tx_tso_desc[pool_id].freelist; + + if (!c_element) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Desc Pool Corrupt %d", pool_id); + return; + } + + for (i = 0; i < soc->tx_tso_desc[pool_id].pool_size; i++) { + temp = c_element->next; + qdf_mem_free(c_element); + c_element = temp; + if (!c_element) + break; + } + + soc->tx_tso_desc[pool_id].freelist = NULL; + soc->tx_tso_desc[pool_id].num_free = 0; + soc->tx_tso_desc[pool_id].pool_size = 0; + TX_DESC_LOCK_UNLOCK(&soc->tx_tso_desc[pool_id].lock); + TX_DESC_LOCK_DESTROY(&soc->tx_tso_desc[pool_id].lock); + return; +} +#else +void dp_tx_tso_desc_pool_free(struct dp_soc *soc, uint8_t pool_id) +{ + return; +} +#endif diff --git a/dp/wifi3.0/dp_tx_desc.h b/dp/wifi3.0/dp_tx_desc.h index 347c7e91dd..aef505ba19 100644 --- a/dp/wifi3.0/dp_tx_desc.h +++ b/dp/wifi3.0/dp_tx_desc.h @@ -48,6 +48,9 @@ QDF_STATUS dp_tx_desc_pool_free(struct dp_soc *soc, uint8_t pool_id); QDF_STATUS dp_tx_ext_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, uint16_t num_elem); QDF_STATUS dp_tx_ext_desc_pool_free(struct dp_soc *soc, uint8_t pool_id); +QDF_STATUS dp_tx_tso_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, + uint16_t num_elem); +void dp_tx_tso_desc_pool_free(struct dp_soc *soc, uint8_t pool_id); /** * dp_tx_desc_alloc() - Allocate a Software Tx Descriptor from given pool @@ -74,6 +77,7 @@ static inline struct dp_tx_desc_s *dp_tx_desc_alloc(struct dp_soc *soc, soc->tx_desc[desc_pool_id].freelist = soc->tx_desc[desc_pool_id].freelist->next; soc->tx_desc[desc_pool_id].num_allocated++; + soc->tx_desc[desc_pool_id].num_free--; } DP_STATS_INC(soc, tx.desc_in_use, 1); @@ -83,6 +87,53 @@ static inline struct dp_tx_desc_s *dp_tx_desc_alloc(struct dp_soc *soc, return tx_desc; } +/** + * dp_tx_desc_alloc_multiple() - Allocate batch of software Tx Descriptors + * from given pool + * @soc: Handle to DP SoC structure + * @pool_id: pool id should pick up + * @num_requested: number of required descriptor + * + * allocate multiple tx descriptor and make a link + * + * Return: h_desc first descriptor pointer + */ +static inline struct dp_tx_desc_s *dp_tx_desc_alloc_multiple( + struct dp_soc *soc, uint8_t desc_pool_id, uint8_t num_requested) +{ + struct dp_tx_desc_s *c_desc = NULL, *h_desc = NULL; + uint8_t count; + + TX_DESC_LOCK_LOCK(&soc->tx_desc[desc_pool_id].lock); + + if ((num_requested == 0) || + (soc->tx_desc[desc_pool_id].num_free < num_requested)) { + TX_DESC_LOCK_UNLOCK(&soc->tx_desc[desc_pool_id].lock); + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "%s, No Free Desc: Available(%d) num_requested(%d)", + __func__, soc->tx_desc[desc_pool_id].num_free, + num_requested); + return NULL; + } + + h_desc = soc->tx_desc[desc_pool_id].freelist; + + /* h_desc should never be NULL since num_free > requested */ + qdf_assert_always(h_desc); + + c_desc = h_desc; + for (count = 0; count < (num_requested - 1); count++) { + c_desc->flags = DP_TX_DESC_FLAG_ALLOCATED; + c_desc = c_desc->next; + } + soc->tx_desc[desc_pool_id].num_free -= count; + soc->tx_desc[desc_pool_id].num_allocated += count; + soc->tx_desc[desc_pool_id].freelist = c_desc->next; + c_desc->next = NULL; + + TX_DESC_LOCK_UNLOCK(&soc->tx_desc[desc_pool_id].lock); + return h_desc; +} /** * dp_tx_desc_free() - Fee a tx descriptor and attach it to free list @@ -101,6 +152,9 @@ dp_tx_desc_free(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc, tx_desc->next = soc->tx_desc[desc_pool_id].freelist; soc->tx_desc[desc_pool_id].freelist = tx_desc; DP_STATS_DEC(soc, tx.desc_in_use, 1); + soc->tx_desc[desc_pool_id].num_allocated--; + soc->tx_desc[desc_pool_id].num_free++; + TX_DESC_LOCK_UNLOCK(&soc->tx_desc[desc_pool_id].lock); } @@ -159,4 +213,94 @@ static inline void dp_tx_ext_desc_free(struct dp_soc *soc, TX_DESC_LOCK_UNLOCK(&soc->tx_ext_desc[desc_pool_id].lock); return; } + +/** + * dp_tx_ext_desc_free_multiple() - Fee multiple tx extension descriptor and + * attach it to free list + * @soc: Handle to DP SoC structure + * @desc_pool_id: pool id should pick up + * @elem: tx descriptor should be freed + * @num_free: number of descriptors should be freed + * + * Return: none + */ +static inline void dp_tx_ext_desc_free_multiple(struct dp_soc *soc, + struct dp_tx_ext_desc_elem_s *elem, uint8_t desc_pool_id, + uint8_t num_free) +{ + struct dp_tx_ext_desc_elem_s *head, *tail, *c_elem; + uint8_t freed = num_free; + + /* caller should always guarantee atleast list of num_free nodes */ + qdf_assert_always(head); + + head = elem; + c_elem = head; + tail = head; + while (c_elem && freed) { + tail = c_elem; + c_elem = c_elem->next; + freed--; + } + + /* caller should always guarantee atleast list of num_free nodes */ + qdf_assert_always(tail); + + TX_DESC_LOCK_LOCK(&soc->tx_ext_desc[desc_pool_id].lock); + tail->next = soc->tx_ext_desc[desc_pool_id].freelist; + soc->tx_ext_desc[desc_pool_id].freelist = head; + soc->tx_ext_desc[desc_pool_id].num_free += num_free; + TX_DESC_LOCK_UNLOCK(&soc->tx_ext_desc[desc_pool_id].lock); + + return; +} + +/** + * dp_tx_tso_desc_alloc() - function to allocate a TSO segment + * @soc: device soc instance + * @pool_id: pool id should pick up tso descriptor + * + * Allocates a TSO segment element from the free list held in + * the soc + * + * Return: tso_seg, tso segment memory pointer + */ +static inline struct qdf_tso_seg_elem_t *dp_tx_tso_desc_alloc( + struct dp_soc *soc, uint8_t pool_id) +{ + struct qdf_tso_seg_elem_t *tso_seg = NULL; + + TX_DESC_LOCK_LOCK(&soc->tx_tso_desc[pool_id].lock); + if (soc->tx_tso_desc[pool_id].freelist) { + soc->tx_tso_desc[pool_id].num_free--; + tso_seg = soc->tx_tso_desc[pool_id].freelist; + soc->tx_tso_desc[pool_id].freelist = + soc->tx_tso_desc[pool_id].freelist->next; + } + TX_DESC_LOCK_UNLOCK(&soc->tx_tso_desc[pool_id].lock); + + return tso_seg; +} + +/** + * dp_tx_tso_desc_free() - function to free a TSO segment + * @soc: device soc instance + * @pool_id: pool id should pick up tso descriptor + * @tso_seg: tso segment memory pointer + * + * Returns a TSO segment element to the free list held in the + * HTT pdev + * + * Return: none + */ + +static inline void dp_tx_tso_desc_free(struct dp_soc *soc, + uint8_t pool_id, struct qdf_tso_seg_elem_t *tso_seg) +{ + TX_DESC_LOCK_LOCK(&soc->tx_tso_desc[pool_id].lock); + tso_seg->next = soc->tx_tso_desc[pool_id].freelist; + soc->tx_tso_desc[pool_id].freelist = tso_seg; + soc->tx_tso_desc[pool_id].num_free++; + TX_DESC_LOCK_UNLOCK(&soc->tx_tso_desc[pool_id].lock); +} #endif /* DP_TX_DESC_H */ diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index ce317b0f6e..b79ce12235 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -115,6 +115,7 @@ struct dp_tx_ext_desc_elem_s { * struct dp_tx_ext_desc_s - Tx Extension Descriptor Pool * @elem_count: Number of descriptors in the pool * @elem_size: Size of each descriptor + * @num_free: Number of free descriptors * @msdu_ext_desc: MSDU extension descriptor * @desc_pages: multiple page allocation information for actual descriptors * @link_elem_size: size of the link descriptor in cacheable memory used for @@ -124,6 +125,7 @@ struct dp_tx_ext_desc_elem_s { struct dp_tx_ext_desc_pool_s { uint16_t elem_count; int elem_size; + uint16_t num_free; struct qdf_mem_multi_page_t desc_pages; int link_elem_size; struct qdf_mem_multi_page_t desc_link_pages; @@ -168,31 +170,41 @@ struct dp_tx_desc_s { void *me_buffer; }; +/** + * struct dp_tx_tso_seg_pool_s + * @pool_size: total number of pool elements + * @num_free: free element count + * @freelist: first free element pointer + * @lock: lock for accessing the pool + */ +struct dp_tx_tso_seg_pool_s { + uint16_t pool_size; + uint16_t num_free; + struct qdf_tso_seg_elem_t *freelist; + qdf_spinlock_t lock; +}; + /** * struct dp_tx_desc_pool_s - Tx Descriptor pool information - * @desc_reserved_size: Size to be reserved for housekeeping info - * in allocated memory for each descriptor - * @page_divider: Number of bits to shift to get page number from descriptor ID - * @offset_filter: Bit mask to get offset from descriptor ID - * @num_allocated: Number of allocated (in use) descriptors in the pool * @elem_size: Size of each descriptor in the pool * @elem_count: Total number of descriptors in the pool + * @num_allocated: Number of used descriptors + * @num_free: Number of free descriptors * @freelist: Chain of free descriptors - * @desc_pages: multiple page allocation information + * @desc_pages: multiple page allocation information for actual descriptors * @lock- Lock for descriptor allocation/free from/to the pool */ struct dp_tx_desc_pool_s { - uint16_t desc_reserved_size; - uint8_t page_divider; - uint32_t offset_filter; - uint32_t num_allocated; uint16_t elem_size; uint16_t elem_count; + uint32_t num_allocated; + uint32_t num_free; struct dp_tx_desc_s *freelist; struct qdf_mem_multi_page_t desc_pages; qdf_spinlock_t lock; }; + struct dp_srng { void *hal_srng; void *base_vaddr_unaligned; @@ -320,6 +332,9 @@ struct dp_soc { /* Tx MSDU Extension descriptor pool */ struct dp_tx_ext_desc_pool_s tx_ext_desc[MAX_TXDESC_POOLS]; + /* Tx TSO descriptor pool */ + struct dp_tx_tso_seg_pool_s tx_tso_desc[MAX_TXDESC_POOLS]; + /* Tx H/W queues lock */ qdf_spinlock_t tx_queue_lock[MAX_TX_HW_QUEUES]; diff --git a/hal/wifi3.0/hal_tx.h b/hal/wifi3.0/hal_tx.h index 641ed5ccd4..b1524f5089 100644 --- a/hal/wifi3.0/hal_tx.h +++ b/hal/wifi3.0/hal_tx.h @@ -525,6 +525,20 @@ static inline void hal_tx_ext_desc_set_tso_enable(void *desc, HAL_TX_SM(TX_MSDU_EXTENSION_0, TSO_ENABLE, tso_en); } +/** + * hal_tx_ext_desc_set_tso_flags() - Set TSO Flags + * @desc: Handle to Tx MSDU Extension Descriptor + * @falgs: 32-bit word with all TSO flags consolidated + * + * Return: none + */ +static inline void hal_tx_ext_desc_set_tso_flags(void *desc, + uint32_t tso_flags) +{ + HAL_SET_FLD_OFFSET(desc, TX_MSDU_EXTENSION_0, TSO_ENABLE, 0) = + tso_flags; +} + /** * hal_tx_ext_desc_set_checksum_en() - Enable HW Checksum offload * @desc: Handle to Tx MSDU Extension Descriptor @@ -592,6 +606,20 @@ static inline void hal_tx_ext_desc_set_tcp_seq(void *desc, ((HAL_TX_SM(TX_MSDU_EXTENSION_2, TCP_SEQ_NUMBER, seq_num))); } + +/** + * hal_tx_ext_desc_set_ip_id() - Set IP Identification field + * @desc: Handle to Tx MSDU Extension Descriptor + * @id: IP Id field for the msdu, if tso is enabled + * + * Return: none + */ +static inline void hal_tx_ext_desc_set_ip_id(void *desc, + uint16_t id) +{ + HAL_SET_FLD(desc, TX_MSDU_EXTENSION_3, IP_IDENTIFICATION) |= + ((HAL_TX_SM(TX_MSDU_EXTENSION_3, IP_IDENTIFICATION, id))); +} /** * hal_tx_ext_desc_set_buffer() - Set Buffer Pointer and Length for a fragment * @desc: Handle to Tx MSDU Extension Descriptor