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

Commit 296ddd75 authored by Subramanian Ananthanarayanan's avatar Subramanian Ananthanarayanan Committed by Gauri Joshi
Browse files

msm: mhi_dev: Fix memory leak during channel reset/stop



mhi_ring_start() does not check whether we once ever allocated DMA buffer
or not , causing it to leak memory if channel reset/stop happens.
Also removing the free logic in mhi_deinit() as the check would suffice
to prevent reallocation.

Change-Id: I569560f9de9facc690131c56f657eadb77a12811
Signed-off-by: default avatarSubramanian Ananthanarayanan <skananth@codeaurora.org>
Signed-off-by: default avatarGauri Joshi <gaurjosh@codeaurora.org>
parent cc0c11d5
Loading
Loading
Loading
Loading
+9 −36
Original line number Diff line number Diff line
@@ -3688,36 +3688,6 @@ static int get_device_tree_data(struct platform_device *pdev)

static int mhi_deinit(struct mhi_dev *mhi)
{
	int i = 0, ring_id = 0;
	struct mhi_dev_ring *ring;

	ring_id = mhi->cfg.channels + mhi->cfg.event_rings + 1;

	for (i = 0; i < ring_id; i++) {
		ring = &mhi->ring[i];
		if (ring->state == RING_STATE_UINT)
			continue;

		dma_free_coherent(mhi->dev, ring->ring_size *
			sizeof(union mhi_dev_ring_element_type),
			ring->ring_cache,
			ring->ring_cache_dma_handle);

		if (mhi->use_edma)
			dma_free_coherent(mhi->dev, sizeof(u32),
				ring->msi_buffer.buf,
				ring->msi_buffer.dma_addr);
		if (ring->type == RING_TYPE_ER) {
			dma_free_coherent(mhi->dev, ring->ring_size *
				sizeof(uint64_t),
				ring->evt_rp_cache,
				ring->evt_rp_cache_dma_handle);
			dma_free_coherent(mhi->dev,
				sizeof(uint32_t),
				ring->msi_buf,
				ring->msi_buf_dma_handle);
		}
	}

	mhi_dev_sm_exit(mhi);

@@ -3737,6 +3707,7 @@ static int mhi_init(struct mhi_dev *mhi)
		return rc;
	}

	if (!mhi->ring)
		mhi->ring = devm_kzalloc(&pdev->dev,
				(sizeof(struct mhi_dev_ring) *
				(mhi->cfg.channels + mhi->cfg.event_rings + 1)),
@@ -3763,8 +3734,10 @@ static int mhi_init(struct mhi_dev *mhi)

	spin_lock_init(&mhi->lock);
	spin_lock_init(&mhi->msi_lock);
	mhi->mmio_backup = devm_kzalloc(&pdev->dev,
			MHI_DEV_MMIO_RANGE, GFP_KERNEL);

	if (!mhi->mmio_backup)
		mhi->mmio_backup = devm_kzalloc(&pdev->dev, MHI_DEV_MMIO_RANGE, GFP_KERNEL);

	if (!mhi->mmio_backup)
		return -ENOMEM;

+34 −23
Original line number Diff line number Diff line
@@ -443,15 +443,21 @@ int mhi_ring_start(struct mhi_dev_ring *ring, union mhi_dev_ring_ctx *ctx,
	wr_offset = mhi_dev_ring_addr2ofst(ring,
					ring->ring_ctx->generic.wp);

	if (!ring->ring_cache) {
		ring->ring_cache = dma_alloc_coherent(mhi->dev,
				ring->ring_size *
				sizeof(union mhi_dev_ring_element_type),
				&ring->ring_cache_dma_handle,
				GFP_KERNEL);
	if (!ring->ring_cache)
		if (!ring->ring_cache) {
			mhi_log(MHI_MSG_ERROR,
				"Failed to allocate ring cache\n");
			return -ENOMEM;
		}
	}

	if (ring->type == RING_TYPE_ER) {
		if (!ring->evt_rp_cache) {
			ring->evt_rp_cache = dma_alloc_coherent(mhi->dev,
				sizeof(uint64_t) * ring->ring_size,
				&ring->evt_rp_cache_dma_handle,
@@ -462,16 +468,20 @@ int mhi_ring_start(struct mhi_dev_ring *ring, union mhi_dev_ring_ctx *ctx,
				rc = -ENOMEM;
				goto cleanup;
			}
		}
		if (!ring->msi_buf) {
			ring->msi_buf = dma_alloc_coherent(mhi->dev,
				sizeof(uint32_t),
				&ring->msi_buf_dma_handle,
				GFP_KERNEL);
			if (!ring->msi_buf) {
			mhi_log(MHI_MSG_ERROR, "Failed to allocate msi buf\n");
				mhi_log(MHI_MSG_ERROR,
					"Failed to allocate msi buf\n");
				rc = -ENOMEM;
				goto cleanup;
			}
		}
	}

	offset = (size_t)(ring->ring_ctx->generic.rbase -
					mhi->ctrl_base.host_pa);
@@ -512,7 +522,6 @@ int mhi_ring_start(struct mhi_dev_ring *ring, union mhi_dev_ring_ctx *ctx,
		if (rc)
			return rc;
	}

	return rc;

cleanup:
@@ -521,11 +530,13 @@ int mhi_ring_start(struct mhi_dev_ring *ring, union mhi_dev_ring_ctx *ctx,
		sizeof(union mhi_dev_ring_element_type),
		ring->ring_cache,
		ring->ring_cache_dma_handle);
	ring->ring_cache = NULL;
	if (ring->evt_rp_cache) {
		dma_free_coherent(mhi->dev,
			sizeof(uint64_t) * ring->ring_size,
			ring->evt_rp_cache,
			ring->evt_rp_cache_dma_handle);
		ring->evt_rp_cache = NULL;
	}
	return rc;
}