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

Commit f1a3f544 authored by Sujeev Dias's avatar Sujeev Dias
Browse files

mhi: cntrl: qcom: device requested bandwidth scaling support



Device can request scaling for the PCIe link speeds and width
through MHI. Added support for handling the same.

CRs-Fixed: 2479785
Change-Id: I448d79fe5aa6b8e2e7696938f0085ca5a2b4f358
Acked-by: default avatarBhaumik Vasav Bhatt <bbhatt@qti.qualcomm.com>
Signed-off-by: default avatarSujeev Dias <sdias@codeaurora.org>
parent 5497a9f6
Loading
Loading
Loading
Loading
+7 −59
Original line number Diff line number Diff line
@@ -41,8 +41,6 @@ struct arch_info {
	void *boot_ipc_log;
	void *tsync_ipc_log;
	struct mhi_device *boot_dev;
	struct mhi_link_info current_link_info;
	struct work_struct bw_scale_work;
	struct notifier_block pm_notifier;
	struct completion pm_completion;
};
@@ -349,49 +347,13 @@ static int mhi_arch_pcie_scale_bw(struct mhi_controller *mhi_cntrl,
	return 0;
}

static void mhi_arch_pcie_bw_scale_work(struct work_struct *work)
static int mhi_arch_bw_scale(struct mhi_controller *mhi_cntrl,
			     struct mhi_link_info *link_info)
{
	struct arch_info *arch_info = container_of(work,
						   struct arch_info,
						   bw_scale_work);
	struct mhi_dev *mhi_dev = arch_info->mhi_dev;
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
	struct pci_dev *pci_dev = mhi_dev->pci_dev;
	struct device *dev = &pci_dev->dev;
	struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev);
	struct mhi_link_info mhi_link_info;
	struct mhi_link_info *cur_info = &arch_info->current_link_info;
	int ret;

	mutex_lock(&mhi_cntrl->pm_mutex);
	if (!mhi_dev->powered_on || MHI_IS_SUSPENDED(mhi_dev->suspend_mode))
		goto exit_work;

	/* copy the latest speed change */
	write_lock_irq(&mhi_cntrl->pm_lock);
	mhi_link_info = mhi_cntrl->mhi_link_info;
	write_unlock_irq(&mhi_cntrl->pm_lock);

	/* link is already set to current settings */
	if (cur_info->target_link_speed == mhi_link_info.target_link_speed &&
	    cur_info->target_link_width == mhi_link_info.target_link_width)
		goto exit_work;

	ret = mhi_arch_pcie_scale_bw(mhi_cntrl, pci_dev, &mhi_link_info);
	if (ret)
		goto exit_work;

	*cur_info = mhi_link_info;

exit_work:
	mutex_unlock(&mhi_cntrl->pm_mutex);
}

static void mhi_arch_pcie_bw_scale_cb(struct mhi_controller *mhi_cntrl,
				      struct mhi_dev *mhi_dev)
{
	struct arch_info *arch_info = mhi_dev->arch_info;

	schedule_work(&arch_info->bw_scale_work);
	return mhi_arch_pcie_scale_bw(mhi_cntrl, pci_dev, link_info);
}

static int mhi_bl_probe(struct mhi_device *mhi_device,
@@ -534,9 +496,7 @@ int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl)
				    mhi_dev->pci_dev, NULL, 0);
		mhi_dev->pci_dev->no_d3hot = true;

		INIT_WORK(&arch_info->bw_scale_work,
			  mhi_arch_pcie_bw_scale_work);
		mhi_dev->bw_scale = mhi_arch_pcie_bw_scale_cb;
		mhi_cntrl->bw_scale = mhi_arch_bw_scale;

		/* store the current bw info */
		ret = pcie_capability_read_word(mhi_dev->pci_dev,
@@ -544,13 +504,12 @@ int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl)
		if (ret)
			return ret;

		cur_link_info = &arch_info->current_link_info;
		cur_link_info = &mhi_cntrl->mhi_link_info;
		cur_link_info->target_link_speed =
			linkstat & PCI_EXP_LNKSTA_CLS;
		cur_link_info->target_link_width =
			(linkstat & PCI_EXP_LNKSTA_NLW) >>
			PCI_EXP_LNKSTA_NLW_SHIFT;
		mhi_cntrl->mhi_link_info = *cur_link_info;

		mhi_driver_register(&mhi_bl_driver);
	}
@@ -743,7 +702,7 @@ static int __mhi_arch_link_resume(struct mhi_controller *mhi_cntrl)
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
	struct arch_info *arch_info = mhi_dev->arch_info;
	struct pci_dev *pci_dev = mhi_dev->pci_dev;
	struct mhi_link_info *cur_info = &arch_info->current_link_info;
	struct mhi_link_info *cur_info = &mhi_cntrl->mhi_link_info;
	int ret;

	MHI_LOG("Entered\n");
@@ -787,10 +746,7 @@ static int __mhi_arch_link_resume(struct mhi_controller *mhi_cntrl)
int mhi_arch_link_resume(struct mhi_controller *mhi_cntrl)
{
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
	struct arch_info *arch_info = mhi_dev->arch_info;
	struct pci_dev *pci_dev = mhi_dev->pci_dev;
	struct mhi_link_info *cur_info = &arch_info->current_link_info;
	struct mhi_link_info *updated_info = &mhi_cntrl->mhi_link_info;
	int ret = 0;

	MHI_LOG("Entered\n");
@@ -810,14 +766,6 @@ int mhi_arch_link_resume(struct mhi_controller *mhi_cntrl)
		return ret;
	}

	/* BW request from device doesn't match current link speed */
	if (cur_info->target_link_speed != updated_info->target_link_speed ||
	    cur_info->target_link_width != updated_info->target_link_width) {
		ret = mhi_arch_pcie_scale_bw(mhi_cntrl, pci_dev, updated_info);
		if (!ret)
			*cur_info = *updated_info;
	}

	msm_pcie_l1ss_timeout_enable(pci_dev);

	MHI_LOG("Exited\n");
+0 −4
Original line number Diff line number Diff line
@@ -594,10 +594,6 @@ static void mhi_status_cb(struct mhi_controller *mhi_cntrl,
		pm_runtime_mark_last_busy(dev);
		pm_request_autosuspend(dev);
		break;
	case MHI_CB_BW_REQ:
		if (mhi_dev->bw_scale)
			mhi_dev->bw_scale(mhi_cntrl, mhi_dev);
		break;
	case MHI_CB_EE_MISSION_MODE:
		/*
		 * we need to force a suspend so device can switch to
+0 −3
Original line number Diff line number Diff line
@@ -57,9 +57,6 @@ struct mhi_dev {
	dma_addr_t iova_stop;
	enum mhi_suspend_mode suspend_mode;

	/* if set, soc support dynamic bw scaling */
	void (*bw_scale)(struct mhi_controller *mhi_cntrl,
			 struct mhi_dev *mhi_dev);
	unsigned int lpm_disable_depth;
	/* lock to toggle low power modes */
	spinlock_t lpm_lock;