diff options
| author | Manjunathappa Prakash <prakashpm@codeaurora.org> | 2017-02-13 00:02:16 -0800 |
|---|---|---|
| committer | qcabuildsw <qcabuildsw@localhost> | 2017-02-15 19:09:30 -0800 |
| commit | b7b4de2379ce1189cd250153d0c01d50ed3a42f8 (patch) | |
| tree | 66061d552d36160d6742b3250bd3f6f55dee07c7 | |
| parent | 40bdb09f4097d7b24eb14c5d57b1a2d3005ce0f2 (diff) | |
qcacld-3.0: Do not free skb in OL if ce_send_fast failed
Return failure if ce_send_fast fails and let caller, HDD free the Tx msdu.
If it happens to be TSO segment then free the to be trasmited TSO segments.
Change-Id: If3a16ca841e63e7941fe732013d3b3c351a4a286
CRs-Fixed: 2004780
| -rw-r--r-- | core/dp/txrx/ol_tx.c | 54 | ||||
| -rw-r--r-- | core/dp/txrx/ol_tx_desc.c | 13 |
2 files changed, 44 insertions, 23 deletions
diff --git a/core/dp/txrx/ol_tx.c b/core/dp/txrx/ol_tx.c index ad21441a7e4b..41982e037842 100644 --- a/core/dp/txrx/ol_tx.c +++ b/core/dp/txrx/ol_tx.c @@ -83,6 +83,18 @@ int ce_send_fast(struct CE_handle *copyeng, qdf_nbuf_t msdu, } while (0) #if defined(FEATURE_TSO) +static void ol_free_remaining_tso_segs(ol_txrx_vdev_handle vdev, + struct ol_txrx_msdu_info_t *msdu_info) +{ + struct qdf_tso_seg_elem_t *next_seg; + struct qdf_tso_seg_elem_t *free_seg = msdu_info->tso_info.curr_seg; + + while (free_seg) { + next_seg = free_seg->next; + ol_tso_free_segment(vdev->pdev, free_seg); + free_seg = next_seg; + } +} /** * ol_tx_prepare_tso() - Given a jumbo msdu, prepare the TSO * related information in the msdu_info meta data @@ -113,16 +125,10 @@ static inline uint8_t ol_tx_prepare_tso(ol_txrx_vdev_handle vdev, = tso_seg; num_seg--; } else { - struct qdf_tso_seg_elem_t *next_seg; - struct qdf_tso_seg_elem_t *free_seg = + /* Free above alocated TSO segements till now */ + msdu_info->tso_info.curr_seg = msdu_info->tso_info.tso_seg_list; - qdf_print("TSO seg alloc failed!\n"); - while (free_seg) { - next_seg = free_seg->next; - ol_tso_free_segment(vdev->pdev, - free_seg); - free_seg = next_seg; - } + ol_free_remaining_tso_segs(vdev, msdu_info); return 1; } } @@ -133,16 +139,9 @@ static inline uint8_t ol_tx_prepare_tso(ol_txrx_vdev_handle vdev, msdu_info->tso_info.tso_num_seg_list = tso_num_seg; } else { /* Free the already allocated num of segments */ - struct qdf_tso_seg_elem_t *next_seg; - struct qdf_tso_seg_elem_t *free_seg = - msdu_info->tso_info.tso_seg_list; - qdf_print("TSO num of seg alloc for one jumbo skb failed!\n"); - while (free_seg) { - next_seg = free_seg->next; - ol_tso_free_segment(vdev->pdev, - free_seg); - free_seg = next_seg; - } + msdu_info->tso_info.curr_seg = + msdu_info->tso_info.tso_seg_list; + ol_free_remaining_tso_segs(vdev, msdu_info); return 1; } qdf_nbuf_get_tso_info(vdev->pdev->osdev, @@ -699,13 +698,28 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) htt_tx_desc_display(tx_desc->htt_tx_desc); if ((0 == ce_send_fast(pdev->ce_tx_hdl, msdu, ep_id, pkt_download_len))) { + struct qdf_tso_info_t *tso_info = + &msdu_info.tso_info; + /* + * If TSO packet, free associated + * remaining TSO segment descriptors + */ + if (tx_desc->pkt_type == + OL_TX_FRM_TSO) { + tso_info->curr_seg = + tso_info->curr_seg->next; + ol_free_remaining_tso_segs(vdev, + &msdu_info); + } + /* * The packet could not be sent. * Free the descriptor, return the * packet to the caller. */ ol_tx_desc_frame_free_nonstd(pdev, - tx_desc, 1); + tx_desc, + htt_tx_status_download_fail); return msdu; } if (msdu_info.tso_info.curr_seg) { diff --git a/core/dp/txrx/ol_tx_desc.c b/core/dp/txrx/ol_tx_desc.c index a1a2c3bf57f5..4194fd2d0ee8 100644 --- a/core/dp/txrx/ol_tx_desc.c +++ b/core/dp/txrx/ol_tx_desc.c @@ -685,8 +685,7 @@ void ol_tx_desc_frame_free_nonstd(struct ol_txrx_pdev_t *pdev, qdf_nbuf_set_next(tx_desc->netbuf, NULL); pdev->tx_data_callback.func(pdev->tx_data_callback.ctxt, tx_desc->netbuf, had_error); - ol_tx_desc_free(pdev, tx_desc); - return; + goto free_tx_desc; } /* let the code below unmap and free the frame */ } @@ -731,11 +730,19 @@ void ol_tx_desc_frame_free_nonstd(struct ol_txrx_pdev_t *pdev, } /* free the netbuf */ qdf_nbuf_free(tx_desc->netbuf); + } else if (had_error == htt_tx_status_download_fail) { + /* Failed to send to target */ + + /* This is to decrement skb->users count for TSO segment */ + if (tx_desc->pkt_type == OL_TX_FRM_TSO) + qdf_nbuf_tx_free(tx_desc->netbuf, had_error); + goto free_tx_desc; } else { - /* single regular frame */ + /* single regular frame, called from completion path */ qdf_nbuf_set_next(tx_desc->netbuf, NULL); qdf_nbuf_tx_free(tx_desc->netbuf, had_error); } +free_tx_desc: /* free the tx desc */ ol_tx_desc_free(pdev, tx_desc); } |
