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

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

msm: mhi_dev: Avoid MSI trigger during device cold boot scenario



In hibernate scenario, due to recent changes on host side the
BHI register value is updated before M0 is issued. This causes a
mismatch with the reset value 0xfffffff expectations. As a result
device ends up sending an MSI to indicate ready status.

This is not expected from host side, and causes race conditions
where it leads the host to process MHI initialization and MHI reset
concurrently in two thread contexts. This manifest into two different
signatures primarily:
a) M0 is acknowledged in Thread 1 context, host keep waiting for device to
Acknowledged M0 sent as part of Thread 2. Device ignores the 2nd request
as its already in M0.
b) MMIO event ring is initialized with a primary value x, because of
Thread 2 doing a re-installation the event ring base is updated by the
host to another value y. The device which is only aware of the primary
value send completion event with RP value corresponding to x. This is
treated as a junk RP and ends up resulting in a host crash with
BSOD 0xdeaddead.

Change-Id: Iae0ee996ad086ff5e6430c198f29e56d994c1ef7
Signed-off-by: default avatarSubramanian Ananthanarayanan <skananth@codeaurora.org>
Signed-off-by: default avatarGauri Joshi <gaurjosh@codeaurora.org>
parent 36455696
Loading
Loading
Loading
Loading
+1 −19
Original line number Diff line number Diff line
@@ -3265,12 +3265,11 @@ static int mhi_dev_recover(struct mhi_dev *mhi)
static void mhi_dev_enable(struct work_struct *work)
{
	int rc = 0;
	struct ep_pcie_msi_config msi_cfg;
	struct mhi_dev *mhi = container_of(work,
				struct mhi_dev, ring_init_cb_work);
	u32 mhi_reset;
	enum mhi_dev_state state;
	uint32_t max_cnt = 0, bhi_intvec = 0;
	uint32_t max_cnt = 0;

	if (mhi->use_ipa) {
		rc = ipa_dma_init();
@@ -3292,23 +3291,6 @@ static void mhi_dev_enable(struct work_struct *work)
		return;
	}

	rc = mhi_dev_mmio_read(mhi, BHI_INTVEC, &bhi_intvec);
	if (rc)
		return;

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

	rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset);
	if (rc) {