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: Subramanian Ananthanarayanan <skananth@codeaurora.org>
Signed-off-by: Gauri Joshi <gaurjosh@codeaurora.org>
This commit is contained in:
Subramanian Ananthanarayanan 2020-06-19 13:42:24 +05:30 • committed by Gauri Joshi
commit 296ddd7554
2 changed files with 43 additions and 59 deletions

View file

@ -3688,36 +3688,6 @@ err:
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,10 +3707,11 @@ static int mhi_init(struct mhi_dev *mhi)
return rc;
}
mhi->ring = devm_kzalloc(&pdev->dev,
(sizeof(struct mhi_dev_ring) *
(mhi->cfg.channels + mhi->cfg.event_rings + 1)),
GFP_KERNEL);
if (!mhi->ring)
mhi->ring = devm_kzalloc(&pdev->dev,
(sizeof(struct mhi_dev_ring) *
(mhi->cfg.channels + mhi->cfg.event_rings + 1)),
GFP_KERNEL);
if (!mhi->ring)
return -ENOMEM;
@ -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;

View file

@ -443,33 +443,43 @@ 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);
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)
return -ENOMEM;
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) {
mhi_log(MHI_MSG_ERROR,
"Failed to allocate ring cache\n");
return -ENOMEM;
}
}
if (ring->type == RING_TYPE_ER) {
ring->evt_rp_cache = dma_alloc_coherent(mhi->dev,
sizeof(uint64_t) * ring->ring_size,
&ring->evt_rp_cache_dma_handle,
GFP_KERNEL);
if (!ring->evt_rp_cache) {
mhi_log(MHI_MSG_ERROR,
"Failed to allocate evt rp cache\n");
rc = -ENOMEM;
goto cleanup;
ring->evt_rp_cache = dma_alloc_coherent(mhi->dev,
sizeof(uint64_t) * ring->ring_size,
&ring->evt_rp_cache_dma_handle,
GFP_KERNEL);
if (!ring->evt_rp_cache) {
mhi_log(MHI_MSG_ERROR,
"Failed to allocate evt rp cache\n");
rc = -ENOMEM;
goto cleanup;
}
}
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");
rc = -ENOMEM;
goto cleanup;
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");
rc = -ENOMEM;
goto cleanup;
}
}
}
@ -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 @@ cleanup:
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;
}