Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c9b2409 authored by Yu Tian's avatar Yu Tian Committed by snandini
Browse files

qcacmn: Perform TSO seg unmap when HW enqueue failed

TSO segment struct is not unmapped and TSO buffer is
not got freed in HW enqueue failure case handler.
Implement similar unmap and free handling as TX comp
handling.
Change-Id: I83389fcc97a2e99497011e9e878f665be88f9f04
CRs-Fixed: 2795836
parent 6071e6e1
Loading
Loading
Loading
Loading
+74 −53
Original line number Diff line number Diff line
@@ -1702,6 +1702,57 @@ dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
	return nbuf;
}

/**
 * dp_tx_comp_free_buf() - Free nbuf associated with the Tx Descriptor
 * @soc: Soc handle
 * @desc: software Tx descriptor to be processed
 *
 * Return: none
 */
static inline void dp_tx_comp_free_buf(struct dp_soc *soc,
				       struct dp_tx_desc_s *desc)
{
	struct dp_vdev *vdev = desc->vdev;
	qdf_nbuf_t nbuf = desc->nbuf;

	/* nbuf already freed in vdev detach path */
	if (!nbuf)
		return;

	/* If it is TDLS mgmt, don't unmap or free the frame */
	if (desc->flags & DP_TX_DESC_FLAG_TDLS_FRAME)
		return dp_non_std_tx_comp_free_buff(soc, desc, vdev);

	/* 0 : MSDU buffer, 1 : MLE */
	if (desc->msdu_ext_desc) {
		/* TSO free */
		if (hal_tx_ext_desc_get_tso_enable(
					desc->msdu_ext_desc->vaddr)) {
			/* unmap eash TSO seg before free the nbuf */
			dp_tx_tso_unmap_segment(soc, desc->tso_desc,
						desc->tso_num_desc);
			qdf_nbuf_free(nbuf);
			return;
		}
	}

	qdf_nbuf_unmap(soc->osdev, nbuf, QDF_DMA_TO_DEVICE);

	if (qdf_unlikely(!vdev)) {
		qdf_nbuf_free(nbuf);
		return;
	}

	if (qdf_likely(!vdev->mesh_vdev))
		qdf_nbuf_free(nbuf);
	else {
		if (desc->flags & DP_TX_DESC_FLAG_TO_FW) {
			qdf_nbuf_free(nbuf);
			DP_STATS_INC(vdev, tx_i.mesh.completion_fw, 1);
		} else
			vdev->osif_tx_free_ext((nbuf));
	}
}
/**
 * dp_tx_send_msdu_multiple() - Enqueue multiple MSDUs
 * @vdev: DP vdev handle
@@ -1777,6 +1828,22 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
				i++;
				continue;
			}

			if (msdu_info->frm_type == dp_tx_frm_tso) {
				dp_tx_tso_unmap_segment(soc,
							msdu_info->u.tso_info.
							curr_seg,
							msdu_info->u.tso_info.
							tso_num_seg_list);

				if (msdu_info->u.tso_info.curr_seg->next) {
					msdu_info->u.tso_info.curr_seg =
					msdu_info->u.tso_info.curr_seg->next;
					i++;
					continue;
				}
			}

			goto done;
		}

@@ -1847,7 +1914,13 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
			 */
			if (msdu_info->frm_type == dp_tx_frm_tso &&
			    msdu_info->u.tso_info.curr_seg) {
				qdf_nbuf_free(nbuf);
				/*
				 * unmap and free current,
				 * retransmit remaining segments
				 */
				dp_tx_comp_free_buf(soc, tx_desc);
				i++;
				continue;
			}

			goto done;
@@ -2788,58 +2861,6 @@ dp_send_completion_to_stack(struct dp_soc *soc, struct dp_pdev *pdev,
}
#endif

/**
 * dp_tx_comp_free_buf() - Free nbuf associated with the Tx Descriptor
 * @soc: Soc handle
 * @desc: software Tx descriptor to be processed
 *
 * Return: none
 */
static inline void dp_tx_comp_free_buf(struct dp_soc *soc,
				       struct dp_tx_desc_s *desc)
{
	struct dp_vdev *vdev = desc->vdev;
	qdf_nbuf_t nbuf = desc->nbuf;

	/* nbuf already freed in vdev detach path */
	if (!nbuf)
		return;

	/* If it is TDLS mgmt, don't unmap or free the frame */
	if (desc->flags & DP_TX_DESC_FLAG_TDLS_FRAME)
		return dp_non_std_tx_comp_free_buff(soc, desc, vdev);

	/* 0 : MSDU buffer, 1 : MLE */
	if (desc->msdu_ext_desc) {
		/* TSO free */
		if (hal_tx_ext_desc_get_tso_enable(
					desc->msdu_ext_desc->vaddr)) {
			/* unmap eash TSO seg before free the nbuf */
			dp_tx_tso_unmap_segment(soc, desc->tso_desc,
						desc->tso_num_desc);
			qdf_nbuf_free(nbuf);
			return;
		}
	}

	qdf_nbuf_unmap(soc->osdev, nbuf, QDF_DMA_TO_DEVICE);

	if (qdf_unlikely(!vdev)) {
		qdf_nbuf_free(nbuf);
		return;
	}

	if (qdf_likely(!vdev->mesh_vdev))
		qdf_nbuf_free(nbuf);
	else {
		if (desc->flags & DP_TX_DESC_FLAG_TO_FW) {
			qdf_nbuf_free(nbuf);
			DP_STATS_INC(vdev, tx_i.mesh.completion_fw, 1);
		} else
			vdev->osif_tx_free_ext((nbuf));
	}
}

#ifdef MESH_MODE_SUPPORT
/**
 * dp_tx_comp_fill_tx_completion_stats() - Fill per packet Tx completion stats