summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManjunathappa Prakash <prakashpm@codeaurora.org>2017-02-13 00:02:16 -0800
committerqcabuildsw <qcabuildsw@localhost>2017-02-15 19:09:30 -0800
commitb7b4de2379ce1189cd250153d0c01d50ed3a42f8 (patch)
tree66061d552d36160d6742b3250bd3f6f55dee07c7
parent40bdb09f4097d7b24eb14c5d57b1a2d3005ce0f2 (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.c54
-rw-r--r--core/dp/txrx/ol_tx_desc.c13
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);
}