qcacmn: Free cloned nbufs in error condition
While sending me packets, if failure is encountered either while preparing tx desc or while enqueuing to h/w,the cloned nbuf's must be freed.The unmap must be done only if the failure is encountered for all the me buffers. Change-Id: I08dbae1fa1820b4fb31119f65e939aead829321b
This commit is contained in:
@@ -2009,6 +2009,7 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
|
|||||||
uint16_t htt_tcl_metadata = 0;
|
uint16_t htt_tcl_metadata = 0;
|
||||||
struct dp_tx_queue *tx_q = &msdu_info->tx_queue;
|
struct dp_tx_queue *tx_q = &msdu_info->tx_queue;
|
||||||
struct cdp_tid_tx_stats *tid_stats = NULL;
|
struct cdp_tid_tx_stats *tid_stats = NULL;
|
||||||
|
uint8_t prep_desc_fail = 0, hw_enq_fail = 0;
|
||||||
|
|
||||||
if (qdf_unlikely(soc->cce_disable)) {
|
if (qdf_unlikely(soc->cce_disable)) {
|
||||||
is_cce_classified = dp_cce_classify(vdev, nbuf);
|
is_cce_classified = dp_cce_classify(vdev, nbuf);
|
||||||
@@ -2037,9 +2038,32 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
|
|||||||
|
|
||||||
if (!tx_desc) {
|
if (!tx_desc) {
|
||||||
if (msdu_info->frm_type == dp_tx_frm_me) {
|
if (msdu_info->frm_type == dp_tx_frm_me) {
|
||||||
|
prep_desc_fail++;
|
||||||
dp_tx_me_free_buf(pdev,
|
dp_tx_me_free_buf(pdev,
|
||||||
(void *)(msdu_info->u.sg_info
|
(void *)(msdu_info->u.sg_info
|
||||||
.curr_seg->frags[0].vaddr));
|
.curr_seg->frags[0].vaddr));
|
||||||
|
if (prep_desc_fail == msdu_info->num_seg) {
|
||||||
|
/*
|
||||||
|
* Unmap is needed only if descriptor
|
||||||
|
* preparation failed for all segments.
|
||||||
|
*/
|
||||||
|
qdf_nbuf_unmap(soc->osdev,
|
||||||
|
msdu_info->u.sg_info.
|
||||||
|
curr_seg->nbuf,
|
||||||
|
QDF_DMA_TO_DEVICE);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Free the nbuf for the current segment
|
||||||
|
* and make it point to the next in the list.
|
||||||
|
* For me, there are as many segments as there
|
||||||
|
* are no of clients.
|
||||||
|
*/
|
||||||
|
qdf_nbuf_free(msdu_info->u.sg_info
|
||||||
|
.curr_seg->nbuf);
|
||||||
|
if (msdu_info->u.sg_info.curr_seg->next)
|
||||||
|
msdu_info->u.sg_info.curr_seg =
|
||||||
|
msdu_info->u.sg_info
|
||||||
|
.curr_seg->next;
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2078,6 +2102,29 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
|
|||||||
|
|
||||||
dp_tx_desc_release(tx_desc, tx_q->desc_pool_id);
|
dp_tx_desc_release(tx_desc, tx_q->desc_pool_id);
|
||||||
if (msdu_info->frm_type == dp_tx_frm_me) {
|
if (msdu_info->frm_type == dp_tx_frm_me) {
|
||||||
|
hw_enq_fail++;
|
||||||
|
if (hw_enq_fail == msdu_info->num_seg) {
|
||||||
|
/*
|
||||||
|
* Unmap is needed only if enqueue
|
||||||
|
* failed for all segments.
|
||||||
|
*/
|
||||||
|
qdf_nbuf_unmap(soc->osdev,
|
||||||
|
msdu_info->u.sg_info.
|
||||||
|
curr_seg->nbuf,
|
||||||
|
QDF_DMA_TO_DEVICE);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Free the nbuf for the current segment
|
||||||
|
* and make it point to the next in the list.
|
||||||
|
* For me, there are as many segments as there
|
||||||
|
* are no of clients.
|
||||||
|
*/
|
||||||
|
qdf_nbuf_free(msdu_info->u.sg_info
|
||||||
|
.curr_seg->nbuf);
|
||||||
|
if (msdu_info->u.sg_info.curr_seg->next)
|
||||||
|
msdu_info->u.sg_info.curr_seg =
|
||||||
|
msdu_info->u.sg_info
|
||||||
|
.curr_seg->next;
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user