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

Commit 57661131 authored by Jinwei Chen's avatar Jinwei Chen Committed by nshrivas
Browse files

qcacmn: fix TX TDLS discover frame nbuf leak issue

crash scenario:
(1) during dp_vdev_detach_wifi3(), it will reset related outstanding
TX desc vdev pointer to NULL.
(2) In the meantime, if this vdev TX completion is received from HW,
dp_non_std_tx_comp_free_buff() do nothing for nbuf due to null vdev,
leak will happen.

add error handling in dp_non_std_tx_comp_free_buff() to fix it.

Change-Id: I942a3d690711c60e8299d86562f08f0fb77f0b32
CRs-Fixed: 2670186
parent 9ab69862
Loading
Loading
Loading
Loading
+15 −6
Original line number Diff line number Diff line
@@ -1497,37 +1497,46 @@ static void dp_tx_update_tdls_flags(struct dp_tx_desc_s *tx_desc)

/**
 * dp_non_std_tx_comp_free_buff() - Free the non std tx packet buffer
 * @soc: DP soc handdle
 * @tx_desc: TX descriptor
 * @vdev: datapath vdev handle
 *
 * Return: None
 */
static void dp_non_std_tx_comp_free_buff(struct dp_tx_desc_s *tx_desc,
static void dp_non_std_tx_comp_free_buff(struct dp_soc *soc,
					 struct dp_tx_desc_s *tx_desc,
					 struct dp_vdev *vdev)
{
	struct hal_tx_completion_status ts = {0};
	qdf_nbuf_t nbuf = tx_desc->nbuf;

	if (qdf_unlikely(!vdev)) {
		dp_err("vdev is null!");
		return;
		dp_err_rl("vdev is null!");
		goto error;
	}

	hal_tx_comp_get_status(&tx_desc->comp, &ts, vdev->pdev->soc->hal_soc);
	if (vdev->tx_non_std_data_callback.func) {
		qdf_nbuf_set_next(tx_desc->nbuf, NULL);
		qdf_nbuf_set_next(nbuf, NULL);
		vdev->tx_non_std_data_callback.func(
				vdev->tx_non_std_data_callback.ctxt,
				nbuf, ts.status);
		return;
	} else {
		dp_err_rl("callback func is null");
	}

error:
	qdf_nbuf_unmap(soc->osdev, nbuf, QDF_DMA_TO_DEVICE);
	qdf_nbuf_free(nbuf);
}
#else
static inline void dp_tx_update_tdls_flags(struct dp_tx_desc_s *tx_desc)
{
}

static inline void dp_non_std_tx_comp_free_buff(struct dp_tx_desc_s *tx_desc,
static inline void dp_non_std_tx_comp_free_buff(struct dp_soc *soc,
						struct dp_tx_desc_s *tx_desc,
						struct dp_vdev *vdev)
{
}
@@ -2768,7 +2777,7 @@ static inline void dp_tx_comp_free_buf(struct dp_soc *soc,

	/* 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(desc, vdev);
		return dp_non_std_tx_comp_free_buff(soc, desc, vdev);

	/* 0 : MSDU buffer, 1 : MLE */
	if (desc->msdu_ext_desc) {