From 35503cce26f0bbf033060cc62243972cc818a6e7 Mon Sep 17 00:00:00 2001 From: Venkata Sharath Chandra Manchala Date: Thu, 6 Apr 2017 15:30:54 -0700 Subject: [PATCH] qcacmn: TSO fixes 1. Unmap tso common segment only after receiving completions for all the tso segments for a given skb. 2. Keep a track of num of free tso descriptors available in the pool of tso descriptors. Change-Id: I01bdbb9e40b7259f77dbcfeec22c6d8cd0c0a6dd CRs-Fixed: 2042950 --- dp/wifi3.0/dp_tx.c | 177 ++++++++++++++++++++++++++++++++++++--- dp/wifi3.0/dp_tx_desc.c | 131 ++++++++++++++++++++++++++--- dp/wifi3.0/dp_tx_desc.h | 36 +++++++- dp/wifi3.0/dp_types.h | 23 ++++- qdf/inc/qdf_nbuf.h | 6 +- qdf/inc/qdf_trace.h | 14 ++-- qdf/linux/src/qdf_nbuf.c | 12 ++- 7 files changed, 367 insertions(+), 32 deletions(-) diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index f434b73290..47c0560bfe 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -77,6 +77,57 @@ static inline void dp_tx_get_queue(struct dp_vdev *vdev, return; } +#if defined(FEATURE_TSO) +/** + * dp_tx_tso_desc_release() - Release the tso segment + * after unmapping all the fragments + * + * @pdev - physical device handle + * @tx_desc - Tx software descriptor + */ +static void dp_tx_tso_desc_release(struct dp_soc *soc, + struct dp_tx_desc_s *tx_desc) +{ + TSO_DEBUG("%s: Free the tso descriptor", __func__); + if (qdf_unlikely(tx_desc->tso_desc == NULL)) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "%s %d TSO desc is NULL!", + __func__, __LINE__); + qdf_assert(0); + } else if (qdf_unlikely(tx_desc->tso_num_desc == NULL)) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%s %d TSO common info is NULL!", + __func__, __LINE__); + qdf_assert(0); + } else { + struct qdf_tso_num_seg_elem_t *tso_num_desc = + (struct qdf_tso_num_seg_elem_t *) tx_desc->tso_num_desc; + + if (tso_num_desc->num_seg.tso_cmn_num_seg > 1) { + tso_num_desc->num_seg.tso_cmn_num_seg--; + qdf_nbuf_unmap_tso_segment(soc->osdev, + tx_desc->tso_desc, false); + } else { + tso_num_desc->num_seg.tso_cmn_num_seg--; + qdf_assert(tso_num_desc->num_seg.tso_cmn_num_seg == 0); + qdf_nbuf_unmap_tso_segment(soc->osdev, + tx_desc->tso_desc, true); + dp_tso_num_seg_free(soc, tx_desc->pool_id, + tx_desc->tso_num_desc); + tx_desc->tso_num_desc = NULL; + } + dp_tx_tso_desc_free(soc, + tx_desc->pool_id, tx_desc->tso_desc); + tx_desc->tso_desc = NULL; + } +} +#else +static void dp_tx_tso_desc_release(struct dp_soc *soc, + struct dp_tx_desc_s *tx_desc) +{ + return; +} +#endif /** * dp_tx_desc_release() - Release Tx Descriptor * @tx_desc : Tx Descriptor @@ -98,6 +149,9 @@ dp_tx_desc_release(struct dp_tx_desc_s *tx_desc, uint8_t desc_pool_id) soc = pdev->soc; + if (tx_desc->frm_type == dp_tx_frm_tso) + dp_tx_tso_desc_release(soc, tx_desc); + if (tx_desc->flags & DP_TX_DESC_FLAG_FRAG) dp_tx_ext_desc_free(soc, tx_desc->msdu_ext_desc, desc_pool_id); @@ -223,6 +277,56 @@ static void dp_tx_prepare_tso_ext_desc(struct qdf_tso_seg_t *tso_seg, } #endif +#if defined(FEATURE_TSO) +/** + * dp_tx_free_tso_seg() - Loop through the tso segments + * allocated and free them + * + * @soc: soc handle + * @free_seg: list of tso segments + * @msdu_info: msdu descriptor + * + * Return - void + */ +static void dp_tx_free_tso_seg(struct dp_soc *soc, + struct qdf_tso_seg_elem_t *free_seg, + struct dp_tx_msdu_info_s *msdu_info) +{ + struct qdf_tso_seg_elem_t *next_seg; + + 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; + } +} + +/** + * dp_tx_free_tso_num_seg() - Loop through the tso num segments + * allocated and free them + * + * @soc: soc handle + * @free_seg: list of tso segments + * @msdu_info: msdu descriptor + * Return - void + */ +static void dp_tx_free_tso_num_seg(struct dp_soc *soc, + struct qdf_tso_num_seg_elem_t *free_seg, + struct dp_tx_msdu_info_s *msdu_info) +{ + struct qdf_tso_num_seg_elem_t *next_seg; + + while (free_seg) { + next_seg = free_seg->next; + dp_tso_num_seg_free(soc, + msdu_info->tx_queue.desc_pool_id, + free_seg); + free_seg = next_seg; + } +} + /** * dp_tx_prepare_tso() - Given a jumbo msdu, prepare the TSO info * @vdev: virtual device handle @@ -231,7 +335,6 @@ static void dp_tx_prepare_tso_ext_desc(struct qdf_tso_seg_t *tso_seg, * * 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) { @@ -239,12 +342,16 @@ static QDF_STATUS dp_tx_prepare_tso(struct dp_vdev *vdev, int num_seg = qdf_nbuf_get_tso_num_seg(msdu); struct dp_soc *soc = vdev->pdev->soc; struct qdf_tso_info_t *tso_info; + struct qdf_tso_num_seg_elem_t *tso_num_seg; 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; + tso_info->tso_num_seg_list = NULL; + + TSO_DEBUG(" %s: num_seg: %d", __func__, num_seg); while (num_seg) { tso_seg = dp_tx_tso_desc_alloc( @@ -254,24 +361,49 @@ static QDF_STATUS dp_tx_prepare_tso(struct dp_vdev *vdev, 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; - } + dp_tx_free_tso_seg(soc, free_seg, msdu_info); + return QDF_STATUS_E_NOMEM; } } + TSO_DEBUG(" %s: num_seg: %d", __func__, num_seg); + + tso_num_seg = dp_tso_num_seg_alloc(soc, + msdu_info->tx_queue.desc_pool_id); + + if (tso_num_seg) { + tso_num_seg->next = tso_info->tso_num_seg_list; + tso_info->tso_num_seg_list = tso_num_seg; + } else { + /* Bug: free tso_num_seg and tso_seg */ + /* Free the already allocated num of segments */ + struct qdf_tso_seg_elem_t *free_seg = + tso_info->tso_seg_list; + + TSO_DEBUG(" %s: Failed alloc - Number of segs for a TSO packet", + __func__); + dp_tx_free_tso_seg(soc, free_seg, msdu_info); + + return QDF_STATUS_E_NOMEM; + } + msdu_info->num_seg = qdf_nbuf_get_tso_info(soc->osdev, msdu, tso_info); + TSO_DEBUG(" %s: msdu_info->num_seg: %d", __func__, + msdu_info->num_seg); + + if (!(msdu_info->num_seg)) { + dp_tx_free_tso_seg(soc, tso_info->tso_seg_list, msdu_info); + dp_tx_free_tso_num_seg(soc, tso_info->tso_num_seg_list, + msdu_info); + return QDF_STATUS_E_INVAL; + } + tso_info->curr_seg = tso_info->tso_seg_list; return QDF_STATUS_SUCCESS; @@ -543,6 +675,8 @@ static struct dp_tx_desc_s *dp_tx_prepare_desc(struct dp_vdev *vdev, tx_desc->vdev = vdev; tx_desc->pdev = pdev; tx_desc->pkt_offset = 0; + tx_desc->tso_desc = msdu_info->u.tso_info.curr_seg; + tx_desc->tso_num_desc = msdu_info->u.tso_info.tso_num_seg_list; /* Handle scattered frames - TSO/SG/ME */ /* Allocate and prepare an extension descriptor for scattered frames */ @@ -960,7 +1094,7 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, nbuf = msdu_info->u.sg_info.curr_seg->nbuf; i = 0; - + /* Print statement to track i and num_seg */ /* * For each segment (maps to 1 MSDU) , prepare software and hardware * descriptors using information in msdu_info @@ -2159,6 +2293,15 @@ QDF_STATUS dp_tx_soc_detach(struct dp_soc *soc) "%s TSO Desc Pool %d Free descs = %d\n", __func__, num_pool, num_desc); + + for (i = 0; i < num_pool; i++) + dp_tx_tso_num_seg_pool_free(soc, i); + + + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "%s TSO Num of seg Desc Pool %d Free descs = %d\n", + __func__, num_pool, num_desc); + return QDF_STATUS_SUCCESS; } @@ -2226,6 +2369,20 @@ QDF_STATUS dp_tx_soc_attach(struct dp_soc *soc) "%s TSO Desc Alloc %d, descs = %d\n", __func__, num_pool, num_desc); + for (i = 0; i < num_pool; i++) { + if (dp_tx_tso_num_seg_pool_alloc(soc, i, num_desc)) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "TSO Num of seg Pool alloc %d failed %p\n", + i, soc); + + goto fail; + } + } + + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "%s TSO Num of seg pool 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_desc.c b/dp/wifi3.0/dp_tx_desc.c index e37c8d6653..205e463b8f 100644 --- a/dp/wifi3.0/dp_tx_desc.c +++ b/dp/wifi3.0/dp_tx_desc.c @@ -296,6 +296,7 @@ QDF_STATUS dp_tx_tso_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, struct qdf_tso_seg_elem_t *c_element; struct qdf_tso_seg_elem_t *temp; + soc->tx_tso_desc[pool_id].num_free = 0; c_element = qdf_mem_malloc(sizeof(struct qdf_tso_seg_elem_t)); if (!c_element) { @@ -306,10 +307,10 @@ QDF_STATUS dp_tx_tso_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, } soc->tx_tso_desc[pool_id].freelist = c_element; + soc->tx_tso_desc[pool_id].num_free++; 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"), @@ -317,10 +318,13 @@ QDF_STATUS dp_tx_tso_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, goto fail; } + soc->tx_tso_desc[pool_id].num_free++; c_element = c_element->next; c_element->next = NULL; - } + } + TSO_DEBUG("Number of free descriptors: %u\n", + soc->tx_tso_desc[pool_id].num_free); soc->tx_tso_desc[pool_id].pool_size = num_elem; TX_DESC_LOCK_CREATE(&soc->tx_tso_desc[pool_id].lock); @@ -336,13 +340,6 @@ fail: 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 @@ -351,7 +348,6 @@ QDF_STATUS dp_tx_tso_desc_pool_alloc(struct dp_soc *soc, uint8_t 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; @@ -382,9 +378,124 @@ void dp_tx_tso_desc_pool_free(struct dp_soc *soc, uint8_t pool_id) TX_DESC_LOCK_DESTROY(&soc->tx_tso_desc[pool_id].lock); return; } +/** + * dp_tx_tso_num_seg_pool_alloc() - Allocate descriptors that tracks the + * fragments in each tso segment + * + * @soc: handle to dp soc structure + * @pool_id: descriptor pool id + * @num_elem: total number of descriptors to be allocated + */ +QDF_STATUS dp_tx_tso_num_seg_pool_alloc(struct dp_soc *soc, uint8_t pool_id, + uint16_t num_elem) +{ + + int i; + struct qdf_tso_num_seg_elem_t *c_element; + struct qdf_tso_num_seg_elem_t *temp; + + soc->tx_tso_num_seg[pool_id].num_free = 0; + c_element = qdf_mem_malloc(sizeof(struct qdf_tso_num_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_num_seg[pool_id].freelist = c_element; + soc->tx_tso_num_seg[pool_id].num_free++; + for (i = 0; i < (num_elem - 1); i++) { + c_element->next = + qdf_mem_malloc(sizeof(struct qdf_tso_num_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; + } + soc->tx_tso_num_seg[pool_id].num_free++; + + c_element = c_element->next; + c_element->next = NULL; + } + + soc->tx_tso_num_seg[pool_id].num_seg_pool_size = num_elem; + TX_DESC_LOCK_CREATE(&soc->tx_tso_num_seg[pool_id].lock); + + return QDF_STATUS_SUCCESS; + +fail: + c_element = soc->tx_tso_num_seg[pool_id].freelist; + while (c_element) { + temp = c_element->next; + qdf_mem_free(c_element); + c_element = temp; + } + return QDF_STATUS_E_NOMEM; +} + +/** + * dp_tx_tso_num_seg_pool_free() - free pool of descriptors that tracks + * the fragments in tso segment + * + * + * @soc: handle to dp soc structure + * @pool_id: descriptor pool_id + */ +void dp_tx_tso_num_seg_pool_free(struct dp_soc *soc, uint8_t pool_id) +{ + int i; + struct qdf_tso_num_seg_elem_t *c_element; + struct qdf_tso_num_seg_elem_t *temp; + + TX_DESC_LOCK_LOCK(&soc->tx_tso_num_seg[pool_id].lock); + c_element = soc->tx_tso_num_seg[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_num_seg[pool_id].num_seg_pool_size; i++) { + temp = c_element->next; + qdf_mem_free(c_element); + c_element = temp; + if (!c_element) + break; + } + + soc->tx_tso_num_seg[pool_id].freelist = NULL; + soc->tx_tso_num_seg[pool_id].num_free = 0; + soc->tx_tso_num_seg[pool_id].num_seg_pool_size = 0; + TX_DESC_LOCK_UNLOCK(&soc->tx_tso_num_seg[pool_id].lock); + TX_DESC_LOCK_DESTROY(&soc->tx_tso_num_seg[pool_id].lock); + return; +} + #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; +} + void dp_tx_tso_desc_pool_free(struct dp_soc *soc, uint8_t pool_id) { return; } + +QDF_STATUS dp_tx_tso_num_seg_pool_alloc(struct dp_soc *soc, uint8_t pool_id, + uint16_t num_elem) +{ + return QDF_STATUS_SUCCESS; +} + +void dp_tx_tso_num_seg_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 bb623baea1..cb8694f64d 100644 --- a/dp/wifi3.0/dp_tx_desc.h +++ b/dp/wifi3.0/dp_tx_desc.h @@ -52,7 +52,9 @@ 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); - +QDF_STATUS dp_tx_tso_num_seg_pool_alloc(struct dp_soc *soc, uint8_t pool_id, + uint16_t num_elem); +void dp_tx_tso_num_seg_pool_free(struct dp_soc *soc, uint8_t pool_id); /** * dp_tx_desc_alloc() - Allocate a Software Tx Descriptor from given pool * @@ -256,6 +258,7 @@ static inline void dp_tx_ext_desc_free_multiple(struct dp_soc *soc, return; } +#if defined(FEATURE_TSO) /** * dp_tx_tso_desc_alloc() - function to allocate a TSO segment * @soc: device soc instance @@ -294,7 +297,6 @@ static inline struct qdf_tso_seg_elem_t *dp_tx_tso_desc_alloc( * * 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) { @@ -304,6 +306,36 @@ static inline void dp_tx_tso_desc_free(struct dp_soc *soc, soc->tx_tso_desc[pool_id].num_free++; TX_DESC_LOCK_UNLOCK(&soc->tx_tso_desc[pool_id].lock); } + +static inline +struct qdf_tso_num_seg_elem_t *dp_tso_num_seg_alloc(struct dp_soc *soc, + uint8_t pool_id) +{ + struct qdf_tso_num_seg_elem_t *tso_num_seg = NULL; + + TX_DESC_LOCK_LOCK(&soc->tx_tso_num_seg[pool_id].lock); + if (soc->tx_tso_num_seg[pool_id].freelist) { + soc->tx_tso_num_seg[pool_id].num_free--; + tso_num_seg = soc->tx_tso_num_seg[pool_id].freelist; + soc->tx_tso_num_seg[pool_id].freelist = + soc->tx_tso_num_seg[pool_id].freelist->next; + } + TX_DESC_LOCK_UNLOCK(&soc->tx_tso_num_seg[pool_id].lock); + + return tso_num_seg; +} + +static inline +void dp_tso_num_seg_free(struct dp_soc *soc, + uint8_t pool_id, struct qdf_tso_num_seg_elem_t *tso_num_seg) +{ + TX_DESC_LOCK_LOCK(&soc->tx_tso_num_seg[pool_id].lock); + tso_num_seg->next = soc->tx_tso_num_seg[pool_id].freelist; + soc->tx_tso_num_seg[pool_id].freelist = tso_num_seg; + soc->tx_tso_num_seg[pool_id].num_free++; + TX_DESC_LOCK_UNLOCK(&soc->tx_tso_num_seg[pool_id].lock); +} +#endif /* * dp_tx_me_alloc_buf() Alloc descriptor from me pool * @pdev DP_PDEV handle for datapath diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 30b62d6907..890101a7c5 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -202,7 +202,7 @@ struct dp_tx_ext_desc_pool_s { * @id: Descriptor ID * @vdev: vdev over which the packet was transmitted * @pdev: Handle to pdev - * @pool_id: Pool ID - used when releasing the descripto + * @pool_id: Pool ID - used when releasing the descriptor * @flags: Flags to track the state of descriptor and special frame handling * @comp: Pool ID - used when releasing the descriptor * @tx_encap_type: Transmit encap type (i.e. Raw, Native Wi-Fi, Ethernet). @@ -228,6 +228,8 @@ struct dp_tx_desc_s { uint8_t frm_type; uint8_t pkt_offset; void *me_buffer; + void *tso_desc; + void *tso_num_desc; }; /** @@ -244,6 +246,22 @@ struct dp_tx_tso_seg_pool_s { qdf_spinlock_t lock; }; +/** + * struct dp_tx_tso_num_seg_pool_s { + * @num_seg_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_num_seg_pool_s { + uint16_t num_seg_pool_size; + uint16_t num_free; + struct qdf_tso_num_seg_elem_t *freelist; + /*tso mutex */ + qdf_spinlock_t lock; +}; + /** * struct dp_tx_desc_pool_s - Tx Descriptor pool information * @elem_size: Size of each descriptor in the pool @@ -416,6 +434,9 @@ struct dp_soc { /* Tx TSO descriptor pool */ struct dp_tx_tso_seg_pool_s tx_tso_desc[MAX_TXDESC_POOLS]; + /* Tx TSO Num of segments pool */ + struct dp_tx_tso_num_seg_pool_s tx_tso_num_seg[MAX_TXDESC_POOLS]; + /* Tx H/W queues lock */ qdf_spinlock_t tx_queue_lock[MAX_TX_HW_QUEUES]; diff --git a/qdf/inc/qdf_nbuf.h b/qdf/inc/qdf_nbuf.h index be767686e2..3eab871bbe 100644 --- a/qdf/inc/qdf_nbuf.h +++ b/qdf/inc/qdf_nbuf.h @@ -103,9 +103,11 @@ /* Enable flag to print TSO specific prints in datapath */ #ifdef TSO_DEBUG_LOG_ENABLE -#define TSO_DEBUG(args ...) printk(args) +#define TSO_DEBUG(fmt, args ...) \ + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE, \ + fmt, ## args) #else -#define TSO_DEBUG(args ...) +#define TSO_DEBUG(fmt, args ...) #endif /** diff --git a/qdf/inc/qdf_trace.h b/qdf/inc/qdf_trace.h index 53880327f9..81d2d64c58 100644 --- a/qdf/inc/qdf_trace.h +++ b/qdf/inc/qdf_trace.h @@ -467,6 +467,14 @@ void __printf(3, 4) qdf_snprintf(char *str_buffer, unsigned int size, #define QDF_SNPRINTF qdf_snprintf +#else + +#define DPTRACE(x) +#define qdf_trace_hex_dump(x, y, z, q) + +#endif /* CONFIG_MCL */ + + #ifdef TSOSEG_DEBUG static inline int qdf_tso_seg_dbg_record(struct qdf_tso_seg_elem_t *tsoseg, @@ -522,12 +530,6 @@ qdf_tso_seg_dbg_zero(struct qdf_tso_seg_elem_t *tsoseg) }; #endif /* TSOSEG_DEBUG */ -#else - -#define DPTRACE(x) -#define qdf_trace_hex_dump(x, y, z, q) - -#endif /* CONFIG_MCL */ #define ERROR_CODE -1 #define QDF_MAX_NAME_SIZE 32 diff --git a/qdf/linux/src/qdf_nbuf.c b/qdf/linux/src/qdf_nbuf.c index 719e82c3ae..92b3e9b001 100644 --- a/qdf/linux/src/qdf_nbuf.c +++ b/qdf/linux/src/qdf_nbuf.c @@ -1740,7 +1740,6 @@ static uint8_t __qdf_nbuf_get_tso_cmn_seg_info(qdf_device_t osdev, tso_info->ethproto); return 1; } - tso_info->l2_len = (skb_network_header(skb) - skb_mac_header(skb)); tso_info->tcphdr = tcp_hdr(skb); tso_info->tcp_seq_num = ntohl(tcp_hdr(skb)->seq); @@ -1886,6 +1885,7 @@ uint32_t __qdf_nbuf_get_tso_info(qdf_device_t osdev, struct sk_buff *skb, qdf_print("TSO: error getting common segment info\n"); return 0; } + total_num_seg = tso_info->tso_num_seg_list; curr_seg = tso_info->tso_seg_list; @@ -1921,6 +1921,7 @@ uint32_t __qdf_nbuf_get_tso_info(qdf_device_t osdev, struct sk_buff *skb, int i = 1; /* tso fragment index */ uint8_t more_tso_frags = 1; + curr_seg->seg.num_frags = 0; tso_info->num_segs++; total_num_seg->num_seg.tso_cmn_num_seg++; @@ -1943,6 +1944,7 @@ uint32_t __qdf_nbuf_get_tso_info(qdf_device_t osdev, struct sk_buff *skb, skb_proc = skb_proc - tso_frag_len; /* increment the TCP sequence number */ + tso_cmn_info.tcp_seq_num += tso_frag_len; curr_seg->seg.tso_frags[i].paddr = tso_frag_paddr; TSO_DEBUG("%s[%d] frag %d frag len %d total_len %u vaddr %p\n", @@ -1997,6 +1999,12 @@ uint32_t __qdf_nbuf_get_tso_info(qdf_device_t osdev, struct sk_buff *skb, __func__, __LINE__, skb_frag_len, tso_frag_len, tso_seg_size); + if (!(tso_frag_vaddr)) { + TSO_DEBUG("%s: Fragment virtual addr is NULL", + __func__); + return 0; + } + tso_frag_paddr = dma_map_single(osdev->dev, tso_frag_vaddr, @@ -2009,6 +2017,8 @@ uint32_t __qdf_nbuf_get_tso_info(qdf_device_t osdev, struct sk_buff *skb, return 0; } } + TSO_DEBUG("%s tcp_seq_num: %u", __func__, + curr_seg->seg.tso_flags.tcp_seq_num); num_seg--; /* if TCP FIN flag was set, set it in the last segment */ if (!num_seg)