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

Commit 14666a96 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: mhi_dev: Do not free channel memory in mhi_deinit"

parents 0488369d 56aa07bd
Loading
Loading
Loading
Loading
+87 −18
Original line number Original line Diff line number Diff line
@@ -46,7 +46,7 @@
#define MHI_RING_PRIMARY_EVT_ID		1
#define MHI_RING_PRIMARY_EVT_ID		1
#define MHI_1K_SIZE			0x1000
#define MHI_1K_SIZE			0x1000
/* Updated Specification for event start is NER - 2 and end - NER -1 */
/* Updated Specification for event start is NER - 2 and end - NER -1 */
#define MHI_HW_ACC_EVT_RING_START	2
#define MHI_HW_ACC_EVT_RING_START	3
#define MHI_HW_ACC_EVT_RING_END		1
#define MHI_HW_ACC_EVT_RING_END		1


#define MHI_HOST_REGION_NUM             2
#define MHI_HOST_REGION_NUM             2
@@ -843,7 +843,9 @@ static int mhi_hwc_chcmd(struct mhi_dev *mhi, uint chid,
	case MHI_DEV_RING_EL_START:
	case MHI_DEV_RING_EL_START:
		connect_params.channel_id = chid;
		connect_params.channel_id = chid;
		connect_params.sys.skip_ep_cfg = true;
		connect_params.sys.skip_ep_cfg = true;
		if ((chid % 2) == 0x0)
		if (chid == MHI_CLIENT_ADPL_IN)
			connect_params.sys.client = IPA_CLIENT_MHI_DPL_CONS;
		else if ((chid % 2) == 0x0)
			connect_params.sys.client = IPA_CLIENT_MHI_PROD;
			connect_params.sys.client = IPA_CLIENT_MHI_PROD;
		else
		else
			connect_params.sys.client = IPA_CLIENT_MHI_CONS;
			connect_params.sys.client = IPA_CLIENT_MHI_CONS;
@@ -2290,6 +2292,8 @@ int mhi_dev_channel_isempty(struct mhi_dev_client *handle)
	int rc;
	int rc;


	ch = handle->channel;
	ch = handle->channel;
	if (!ch)
		return -EINVAL;


	rc = ch->ring->rd_offset == ch->ring->wr_offset;
	rc = ch->ring->rd_offset == ch->ring->wr_offset;


@@ -2669,6 +2673,64 @@ int mhi_dev_write_channel(struct mhi_req *wreq)
}
}
EXPORT_SYMBOL(mhi_dev_write_channel);
EXPORT_SYMBOL(mhi_dev_write_channel);


static int mhi_dev_recover(struct mhi_dev *mhi)
{
	int rc = 0;
	uint32_t syserr, max_cnt = 0, bhi_intvec = 0;
	bool mhi_reset;
	enum mhi_dev_state state;

	/* Check if MHI is in syserr */
	mhi_dev_mmio_masked_read(mhi, MHISTATUS,
				MHISTATUS_SYSERR_MASK,
				MHISTATUS_SYSERR_SHIFT, &syserr);

	mhi_log(MHI_MSG_VERBOSE, "mhi_syserr = 0x%X\n", syserr);
	if (syserr) {
		rc = mhi_dev_mmio_read(mhi, BHI_INTVEC, &bhi_intvec);
		if (rc)
			return rc;

		if (bhi_intvec != 0xffffffff) {
			/* Indicate the host that the device is ready */
			rc = ep_pcie_trigger_msi(mhi->phandle, bhi_intvec);
			if (rc) {
				pr_err("%s: error sending msi\n", __func__);
				return rc;
			}
		}

		/* Poll for the host to set the reset bit */
		rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset);
		if (rc) {
			pr_err("%s: get mhi state failed\n", __func__);
			return rc;
		}
		while (mhi_reset != true && max_cnt < MHI_SUSPEND_TIMEOUT) {
			/* Wait for Host to set the reset */
			msleep(MHI_SUSPEND_MIN);
			rc = mhi_dev_mmio_get_mhi_state(mhi, &state,
								&mhi_reset);
			if (rc) {
				pr_err("%s: get mhi state failed\n", __func__);
				return rc;
			}
			max_cnt++;
		}

		if (!mhi_reset) {
			mhi_log(MHI_MSG_VERBOSE, "Host failed to set reset\n");
			return -EINVAL;
		}
	}
	/*
	 * Now mask the interrupts so that the state machine moves
	 * only after IPA is ready
	 */
	mhi_dev_mmio_mask_interrupts(mhi);
	return 0;
}

static void mhi_dev_enable(struct work_struct *work)
static void mhi_dev_enable(struct work_struct *work)
{
{
	int rc = 0;
	int rc = 0;
@@ -3000,11 +3062,7 @@ static int mhi_deinit(struct mhi_dev *mhi)
			ring->ring_cache_dma_handle);
			ring->ring_cache_dma_handle);
	}
	}


	for (i = 0; i < mhi->cfg.channels; i++)
		mutex_destroy(&mhi->ch[i].ch_lock);

	devm_kfree(&pdev->dev, mhi->mmio_backup);
	devm_kfree(&pdev->dev, mhi->mmio_backup);
	devm_kfree(&pdev->dev, mhi->ch);
	devm_kfree(&pdev->dev, mhi->ring);
	devm_kfree(&pdev->dev, mhi->ring);


	mhi_dev_sm_exit(mhi);
	mhi_dev_sm_exit(mhi);
@@ -3032,6 +3090,11 @@ static int mhi_init(struct mhi_dev *mhi)
	if (!mhi->ring)
	if (!mhi->ring)
		return -ENOMEM;
		return -ENOMEM;


	/*
	 * mhi_init is also called during device reset, in
	 * which case channel mem will already be allocated.
	 */
	if (!mhi->ch) {
		mhi->ch = devm_kzalloc(&pdev->dev,
		mhi->ch = devm_kzalloc(&pdev->dev,
			(sizeof(struct mhi_dev_channel) *
			(sizeof(struct mhi_dev_channel) *
			(mhi->cfg.channels)), GFP_KERNEL);
			(mhi->cfg.channels)), GFP_KERNEL);
@@ -3040,6 +3103,7 @@ static int mhi_init(struct mhi_dev *mhi)


		for (i = 0; i < mhi->cfg.channels; i++)
		for (i = 0; i < mhi->cfg.channels; i++)
			mutex_init(&mhi->ch[i].ch_lock);
			mutex_init(&mhi->ch[i].ch_lock);
	}


	spin_lock_init(&mhi->lock);
	spin_lock_init(&mhi->lock);
	mhi->mmio_backup = devm_kzalloc(&pdev->dev,
	mhi->mmio_backup = devm_kzalloc(&pdev->dev,
@@ -3180,6 +3244,18 @@ static int mhi_dev_resume_mmio_mhi_init(struct mhi_dev *mhi_ctx)
	mutex_init(&mhi_ctx->mhi_event_lock);
	mutex_init(&mhi_ctx->mhi_event_lock);
	mutex_init(&mhi_ctx->mhi_write_test);
	mutex_init(&mhi_ctx->mhi_write_test);


	mhi_ctx->phandle = ep_pcie_get_phandle(mhi_ctx->ifc_id);
	if (!mhi_ctx->phandle) {
		pr_err("PCIe driver get handle failed.\n");
		return -EINVAL;
	}

	rc = mhi_dev_recover(mhi_ctx);
	if (rc) {
		pr_err("%s: get mhi state failed\n", __func__);
		return rc;
	}

	rc = mhi_init(mhi_ctx);
	rc = mhi_init(mhi_ctx);
	if (rc)
	if (rc)
		return rc;
		return rc;
@@ -3209,13 +3285,6 @@ static int mhi_dev_resume_mmio_mhi_init(struct mhi_dev *mhi_ctx)
		pr_err("Failed to update the MHI version\n");
		pr_err("Failed to update the MHI version\n");
		return rc;
		return rc;
	}
	}

	mhi_ctx->phandle = ep_pcie_get_phandle(mhi_ctx->ifc_id);
	if (!mhi_ctx->phandle) {
		pr_err("PCIe driver get handle failed.\n");
		return -EINVAL;
	}

	mhi_ctx->event_reg.events = EP_PCIE_EVENT_PM_D3_HOT |
	mhi_ctx->event_reg.events = EP_PCIE_EVENT_PM_D3_HOT |
		EP_PCIE_EVENT_PM_D3_COLD |
		EP_PCIE_EVENT_PM_D3_COLD |
		EP_PCIE_EVENT_PM_D0 |
		EP_PCIE_EVENT_PM_D0 |
+6 −0
Original line number Original line Diff line number Diff line
@@ -882,6 +882,12 @@ int mhi_dev_mmio_mask_erdb_interrupts(struct mhi_dev *dev);
 */
 */
int mhi_dev_mmio_read_erdb_status_interrupts(struct mhi_dev *dev);
int mhi_dev_mmio_read_erdb_status_interrupts(struct mhi_dev *dev);


/**
 * mhi_dev_mmio_mask_interrupts() - Mask all MHI interrupts.
 * @dev:	MHI device structure.
 */
void mhi_dev_mmio_mask_interrupts(struct mhi_dev *dev);

/**
/**
 * mhi_dev_mmio_clear_interrupts() - Clear all doorbell interrupts.
 * mhi_dev_mmio_clear_interrupts() - Clear all doorbell interrupts.
 * @dev:	MHI device structure.
 * @dev:	MHI device structure.
+2 −1
Original line number Original line Diff line number Diff line
@@ -389,7 +389,7 @@ int mhi_dev_mmio_disable_cmdb_interrupt(struct mhi_dev *dev)
}
}
EXPORT_SYMBOL(mhi_dev_mmio_disable_cmdb_interrupt);
EXPORT_SYMBOL(mhi_dev_mmio_disable_cmdb_interrupt);


static void mhi_dev_mmio_mask_interrupts(struct mhi_dev *dev)
void mhi_dev_mmio_mask_interrupts(struct mhi_dev *dev)
{
{
	mhi_dev_mmio_disable_ctrl_interrupt(dev);
	mhi_dev_mmio_disable_ctrl_interrupt(dev);


@@ -399,6 +399,7 @@ static void mhi_dev_mmio_mask_interrupts(struct mhi_dev *dev)


	mhi_dev_mmio_mask_erdb_interrupts(dev);
	mhi_dev_mmio_mask_erdb_interrupts(dev);
}
}
EXPORT_SYMBOL(mhi_dev_mmio_mask_interrupts);


int mhi_dev_mmio_clear_interrupts(struct mhi_dev *dev)
int mhi_dev_mmio_clear_interrupts(struct mhi_dev *dev)
{
{
Loading