|
@@ -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;
|
|
|
struct dp_tx_queue *tx_q = &msdu_info->tx_queue;
|
|
|
struct cdp_tid_tx_stats *tid_stats = NULL;
|
|
|
+ uint8_t prep_desc_fail = 0, hw_enq_fail = 0;
|
|
|
|
|
|
if (qdf_unlikely(soc->cce_disable)) {
|
|
|
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 (msdu_info->frm_type == dp_tx_frm_me) {
|
|
|
+ prep_desc_fail++;
|
|
|
dp_tx_me_free_buf(pdev,
|
|
|
(void *)(msdu_info->u.sg_info
|
|
|
.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++;
|
|
|
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);
|
|
|
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++;
|
|
|
continue;
|
|
|
}
|