diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 353ea3d4d7..0fc2fb04a2 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -2064,6 +2064,48 @@ fail_return: return nbuf; } +/** + * dp_tx_comp_free_buf() - Free nbuf associated with the Tx Descriptor + * @soc: Soc handle + * @desc: software Tx descriptor to be processed + * + * Return: none + */ +static inline void dp_tx_comp_free_buf(struct dp_soc *soc, + struct dp_tx_desc_s *desc) +{ + qdf_nbuf_t nbuf = desc->nbuf; + + /* nbuf already freed in vdev detach path */ + if (!nbuf) + return; + + /* If it is TDLS mgmt, don't unmap or free the frame */ + if (desc->flags & DP_TX_DESC_FLAG_TDLS_FRAME) + return dp_non_std_tx_comp_free_buff(soc, desc); + + /* 0 : MSDU buffer, 1 : MLE */ + if (desc->msdu_ext_desc) { + /* TSO free */ + if (hal_tx_ext_desc_get_tso_enable( + desc->msdu_ext_desc->vaddr)) { + /* unmap eash TSO seg before free the nbuf */ + dp_tx_tso_unmap_segment(soc, desc->tso_desc, + desc->tso_num_desc); + qdf_nbuf_free(nbuf); + return; + } + } + + qdf_nbuf_unmap_nbytes_single(soc->osdev, nbuf, + QDF_DMA_TO_DEVICE, nbuf->len); + + if (desc->flags & DP_TX_DESC_FLAG_MESH_MODE) + return dp_mesh_tx_comp_free_buff(soc, desc); + + qdf_nbuf_free(nbuf); +} + /** * dp_tx_send_msdu_multiple() - Enqueue multiple MSDUs * @vdev: DP vdev handle @@ -2152,6 +2194,22 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, i++; continue; } + + if (msdu_info->frm_type == dp_tx_frm_tso) { + dp_tx_tso_unmap_segment(soc, + msdu_info->u.tso_info. + curr_seg, + msdu_info->u.tso_info. + tso_num_seg_list); + + if (msdu_info->u.tso_info.curr_seg->next) { + msdu_info->u.tso_info.curr_seg = + msdu_info->u.tso_info.curr_seg->next; + i++; + continue; + } + } + goto done; } @@ -2248,7 +2306,13 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, */ if (msdu_info->frm_type == dp_tx_frm_tso && msdu_info->u.tso_info.curr_seg) { - qdf_nbuf_free(nbuf); + /* + * unmap and free current, + * retransmit remaining segments + */ + dp_tx_comp_free_buf(soc, tx_desc); + i++; + continue; } goto done; @@ -3451,51 +3515,6 @@ dp_send_completion_to_stack(struct dp_soc *soc, struct dp_pdev *pdev, } #endif -/** - * dp_tx_comp_free_buf() - Free nbuf associated with the Tx Descriptor - * @soc: Soc handle - * @desc: software Tx descriptor to be processed - * - * Return: none - */ -static inline void dp_tx_comp_free_buf(struct dp_soc *soc, - struct dp_tx_desc_s *desc) -{ - qdf_nbuf_t nbuf = desc->nbuf; - - /* nbuf already freed in vdev detach path */ - if (!nbuf) - return; - - /* If it is TDLS mgmt, don't unmap or free the frame */ - if (desc->flags & DP_TX_DESC_FLAG_TDLS_FRAME) - return dp_non_std_tx_comp_free_buff(soc, desc); - - /* 0 : MSDU buffer, 1 : MLE */ - if (desc->msdu_ext_desc) { - /* TSO free */ - if (hal_tx_ext_desc_get_tso_enable( - desc->msdu_ext_desc->vaddr)) { - /* unmap eash TSO seg before free the nbuf */ - dp_tx_tso_unmap_segment(soc, desc->tso_desc, - desc->tso_num_desc); - qdf_nbuf_free(nbuf); - return; - } - } - /* If it's ME frame, dont unmap the cloned nbuf's */ - if ((desc->flags & DP_TX_DESC_FLAG_ME) && qdf_nbuf_is_cloned(nbuf)) - goto nbuf_free; - - qdf_nbuf_unmap_nbytes_single(soc->osdev, nbuf, - QDF_DMA_TO_DEVICE, nbuf->len); - - if (desc->flags & DP_TX_DESC_FLAG_MESH_MODE) - return dp_mesh_tx_comp_free_buff(soc, desc); -nbuf_free: - qdf_nbuf_free(nbuf); -} - #ifdef MESH_MODE_SUPPORT /** * dp_tx_comp_fill_tx_completion_stats() - Fill per packet Tx completion stats