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

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

msm: mhi_dev: Allocate ring element during M0



Device allocates ring memory during mmio initialization, this
causes 128 event ring elements to be created as MHICFG
register may not be updated by the host. This causes memory
to get exhausted leading to an MMIO init failure.

The Change is to allocate ring memory during M0, during which
MHICFG register is bound to be updated by the host.

Change-Id: I04a0e0ed79a46f16f96e2be4c5c68cba9ee2c99d
Signed-off-by: default avatarSubramanian Ananthanarayanan <skananth@codeaurora.org>
Signed-off-by: default avatarGauri Joshi <gaurjosh@codeaurora.org>
parent d9d62284
Loading
Loading
Loading
Loading
+52 −18
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ static void mhi_dev_cmd_event_msi_cb(void *req);

static int mhi_dev_alloc_cmd_ack_buf_req(struct mhi_dev *mhi);

static int mhi_dev_ring_init(struct mhi_dev *dev);

static struct mhi_dev_uevent_info channel_state_info[MHI_MAX_CHANNELS];
static DECLARE_COMPLETION(read_from_host);
@@ -2685,6 +2686,25 @@ static int mhi_dev_cache_host_cfg(struct mhi_dev *mhi)
					mhi->cfg.event_rings;
	mhi->ch_ctx_shadow.size = sizeof(struct mhi_dev_ch_ctx) *
					mhi->cfg.channels;

	/* Allocate ring elements, during M0 when host
	 * would have updated MHICFG register
	 */

	if (!mhi->ring) {
		mhi->ring = devm_kcalloc(&pdev->dev,
				(mhi->cfg.channels + mhi->cfg.event_rings+1),
				sizeof(struct mhi_dev_ring),
				GFP_KERNEL);
		if (!mhi->ring) {
			rc = -ENOMEM;
			goto exit;
		}
		mhi_log(MHI_MSG_INFO,
			"MEM_ALLOC: size:%d RING_ALLOC\n",
			(sizeof(struct mhi_dev_ring) *
			(mhi->cfg.channels + mhi->cfg.event_rings + 1)));
	}
	/*
	 * This func mhi_dev_cache_host_cfg will be called when
	 * processing mhi device reset as well, do not allocate
@@ -2731,6 +2751,13 @@ static int mhi_dev_cache_host_cfg(struct mhi_dev *mhi)
	}
	memset(mhi->ch_ctx_cache, 0, sizeof(struct mhi_dev_ch_ctx) *
						mhi->cfg.channels);

	rc = mhi_dev_ring_init(mhi);
	if (rc) {
		mhi_log(MHI_MSG_VERBOSE, "MHI dev ring init failed\n");
		goto exit;
	}

	if (MHI_USE_DMA(mhi)) {
		data_transfer.phy_addr = mhi->cmd_ctx_cache_dma_handle;
		data_transfer.host_pa = mhi->cmd_ctx_shadow.host_pa;
@@ -2761,21 +2788,43 @@ static int mhi_dev_cache_host_cfg(struct mhi_dev *mhi)
					mhi->ev_ctx_cache->rp,
					mhi->ev_ctx_cache->wp);

	return mhi_ring_start(&mhi->ring[0],
	rc = mhi_ring_start(&mhi->ring[0],
			(union mhi_dev_ring_ctx *)mhi->cmd_ctx_cache, mhi);
	if (rc) {
		pr_err("MHI ring start failed:%d\n", rc);
		goto exit;
	}

	return 0;
exit:
	if (mhi->cmd_ctx_cache)
	if (mhi->ring) {
		devm_kfree(&pdev->dev, mhi->ring);
		mhi->ring = NULL;
		mhi_log(MHI_MSG_INFO,
			"MEM_DEALLOC: size:%d RING_ALLOC\n",
			(sizeof(struct mhi_dev_ring) *
			(mhi->cfg.channels + mhi->cfg.event_rings + 1)));
	}
	if (mhi->cmd_ctx_cache) {
		dma_free_coherent(&pdev->dev,
			sizeof(struct mhi_dev_cmd_ctx),
			mhi->cmd_ctx_cache,
			mhi->cmd_ctx_cache_dma_handle);
	if (mhi->ev_ctx_cache)
		mhi_log(MHI_MSG_INFO,
			"MEM_DEALLOC: size:%d CMD_CTX_CACHE\n",
			sizeof(struct mhi_dev_cmd_ctx));
	}
	if (mhi->ev_ctx_cache) {
		dma_free_coherent(&pdev->dev,
			sizeof(struct mhi_dev_ev_ctx) *
			mhi->cfg.event_rings,
			mhi->ev_ctx_cache,
			mhi->ev_ctx_cache_dma_handle);
		mhi_log(MHI_MSG_INFO,
			"MEM_DEALLOC: size:%d EV_CTX_CACHE\n",
			sizeof(struct mhi_dev_ev_ctx) *
			mhi->cfg.event_rings);
	}
	return rc;
}

@@ -3675,13 +3724,6 @@ static void mhi_dev_enable(struct work_struct *work)
		}
	}

	rc = mhi_dev_ring_init(mhi);
	if (rc) {
		pr_err("MHI dev ring init failed\n");
		return;
	}


	rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset);
	if (rc) {
		pr_err("%s: get mhi state failed\n", __func__);
@@ -3995,14 +4037,6 @@ 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)),
				GFP_KERNEL);
	if (!mhi->ring)
		return -ENOMEM;

	/*
	 * mhi_init is also called during device reset, in
	 * which case channel mem will already be allocated.