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

Commit 955be850 authored by Sujeev Dias's avatar Sujeev Dias
Browse files

mhi: cntrl: qcom: add usage of system pm state notifications



ESOC power off notifications can be received during any stage
of system suspend/resume. Avoid these race conditions by
aborting system suspend and waiting for system resume to complete
to process ESOC power off.

CRs-Fixed: 2429838
Change-Id: Ie79b0e007b628f8740e581e9a6776b1e581259f5
Acked-by: default avatarBhaumik Vasav Bhatt <bbhatt@qti.qualcomm.com>
Signed-off-by: default avatarSujeev Dias <sdias@codeaurora.org>
parent c5aa0a59
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/msm_pcie.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/suspend.h>
#include <linux/mhi.h>
#include "mhi_qcom.h"

@@ -32,6 +33,8 @@ struct arch_info {
	struct mhi_link_info current_link_info;
	struct work_struct bw_scale_work;
	bool drv_connected;
	struct notifier_block pm_notifier;
	struct completion pm_completion;
};

/* ipc log markings */
@@ -50,6 +53,25 @@ enum MHI_DEBUG_LEVEL mhi_ipc_log_lvl = MHI_MSG_LVL_ERROR;

#endif

static int mhi_arch_pm_notifier(struct notifier_block *nb,
				unsigned long event, void *unused)
{
	struct arch_info *arch_info =
		container_of(nb, struct arch_info, pm_notifier);

	switch (event) {
	case PM_SUSPEND_PREPARE:
		reinit_completion(&arch_info->pm_completion);
		break;

	case PM_POST_SUSPEND:
		complete_all(&arch_info->pm_completion);
		break;
	}

	return NOTIFY_DONE;
}

static int mhi_arch_set_bus_request(struct mhi_controller *mhi_cntrl, int index)
{
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
@@ -192,6 +214,15 @@ void mhi_arch_esoc_ops_power_off(void *priv, bool mdm_state)
	mhi_dev->powered_on = false;
	mutex_unlock(&mhi_cntrl->pm_mutex);

	/*
	 * Abort system suspend if system is preparing to go to suspend
	 * by grabbing wake source.
	 * If system is suspended, wait for pm notifier callback to notify
	 * that resume has occurred with PM_POST_SUSPEND event.
	 */
	pm_stay_awake(&mhi_cntrl->mhi_dev->dev);
	wait_for_completion(&arch_info->pm_completion);

	MHI_LOG("Triggering shutdown process\n");
	mhi_power_down(mhi_cntrl, !mdm_state);

@@ -204,6 +235,8 @@ void mhi_arch_esoc_ops_power_off(void *priv, bool mdm_state)

	mhi_arch_pcie_deinit(mhi_cntrl);
	mhi_cntrl->dev = NULL;

	pm_relax(&mhi_cntrl->mhi_dev->dev);
}

static void mhi_bl_dl_cb(struct mhi_device *mhi_device,
@@ -450,6 +483,18 @@ int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl)
		if (ret)
			MHI_LOG("Failed to reg. for link up notification\n");

		init_completion(&arch_info->pm_completion);

		/* register PM notifier to get post resume events */
		arch_info->pm_notifier.notifier_call = mhi_arch_pm_notifier;
		register_pm_notifier(&arch_info->pm_notifier);

		/*
		 * Mark as completed at initial boot-up to allow ESOC power on
		 * callback to proceed if system has not gone to suspend
		 */
		complete_all(&arch_info->pm_completion);

		arch_info->esoc_client = devm_register_esoc_client(
						&mhi_dev->pci_dev->dev, "mdm");
		if (IS_ERR_OR_NULL(arch_info->esoc_client)) {