diff --git a/core/dp/txrx/ol_tx_ll_fastpath.c b/core/dp/txrx/ol_tx_ll_fastpath.c index b5a5b0d8b264..3841c02742a2 100644 --- a/core/dp/txrx/ol_tx_ll_fastpath.c +++ b/core/dp/txrx/ol_tx_ll_fastpath.c @@ -382,6 +382,15 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) * pointer before the ce_send call. */ next = qdf_nbuf_next(msdu); + /* + * Increment the skb->users count here, for this SKB, to make + * sure it will be freed only after receiving Tx completion + * of the last segment. + * Decrement skb->users count before sending last segment + */ + if (qdf_nbuf_is_tso(msdu) && segments) + qdf_nbuf_inc_users(msdu); + /* init the current segment to the 1st segment in the list */ while (segments) { if (msdu_info.tso_info.curr_seg) @@ -451,6 +460,13 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) next_seg = NULL; } + /* Decrement the skb-users count if segment + * is the last segment or the only segment + */ + if (tx_desc->pkt_type == OL_TX_FRM_TSO && + segments == 0) + qdf_nbuf_tx_free(msdu, 0); + if ((ce_send_fast(pdev->ce_tx_hdl, msdu, ep_id, pkt_download_len) == 0)) { @@ -465,6 +481,10 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) tso_info->curr_seg = next_seg; ol_free_remaining_tso_segs(vdev, &msdu_info, true); + if (segments) + qdf_nbuf_tx_free( + msdu, + QDF_NBUF_PKT_ERROR); } /* @@ -491,10 +511,12 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) * If TSO packet, free associated * remaining TSO segment descriptors */ - if (qdf_nbuf_is_tso(msdu)) + if (qdf_nbuf_is_tso(msdu)) { ol_free_remaining_tso_segs(vdev, &msdu_info, true); - + qdf_nbuf_tx_free(msdu, + QDF_NBUF_PKT_ERROR); + } TXRX_STATS_MSDU_LIST_INCR( pdev, tx.dropped.host_reject, msdu); /* the list of unaccepted MSDUs */