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

Commit b1903627 authored by Sujeev Dias's avatar Sujeev Dias Committed by Gerrit - the friendly Code Review server
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 b4183bf4
Loading
Loading
Loading
Loading
+22 −64
Original line number Original line Diff line number Diff line
@@ -31,8 +31,6 @@ struct arch_info {
	void *boot_ipc_log;
	void *boot_ipc_log;
	void *tsync_ipc_log;
	void *tsync_ipc_log;
	struct mhi_device *boot_dev;
	struct mhi_device *boot_dev;
	struct mhi_link_info current_link_info;
	struct work_struct bw_scale_work;
	bool drv_connected;
	bool drv_connected;
	struct notifier_block pm_notifier;
	struct notifier_block pm_notifier;
	struct completion pm_completion;
	struct completion pm_completion;
@@ -367,49 +365,13 @@ static int mhi_arch_pcie_scale_bw(struct mhi_controller *mhi_cntrl,
	return 0;
	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 mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
						   struct arch_info,
						   bw_scale_work);
	struct mhi_dev *mhi_dev = arch_info->mhi_dev;
	struct pci_dev *pci_dev = mhi_dev->pci_dev;
	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);
	return mhi_arch_pcie_scale_bw(mhi_cntrl, pci_dev, 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);
}
}


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


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


		/* store the current bw info */
		/* store the current bw info */
		ret = pcie_capability_read_word(mhi_dev->pci_dev,
		ret = pcie_capability_read_word(mhi_dev->pci_dev,
@@ -576,13 +536,12 @@ int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl)
		if (ret)
		if (ret)
			return 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 =
		cur_link_info->target_link_speed =
			linkstat & PCI_EXP_LNKSTA_CLS;
			linkstat & PCI_EXP_LNKSTA_CLS;
		cur_link_info->target_link_width =
		cur_link_info->target_link_width =
			(linkstat & PCI_EXP_LNKSTA_NLW) >>
			(linkstat & PCI_EXP_LNKSTA_NLW) >>
			PCI_EXP_LNKSTA_NLW_SHIFT;
			PCI_EXP_LNKSTA_NLW_SHIFT;
		mhi_cntrl->mhi_link_info = *cur_link_info;


		mhi_driver_register(&mhi_bl_driver);
		mhi_driver_register(&mhi_bl_driver);
	}
	}
@@ -598,13 +557,12 @@ void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl)
static int mhi_arch_drv_suspend(struct mhi_controller *mhi_cntrl)
static int mhi_arch_drv_suspend(struct mhi_controller *mhi_cntrl)
{
{
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(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 pci_dev *pci_dev = mhi_dev->pci_dev;
	struct mhi_link_info link_info, *cur_link_info;
	struct mhi_link_info link_info, *cur_link_info;
	bool bw_switched = false;
	bool bw_switched = false;
	int ret;
	int ret;


	cur_link_info = &arch_info->current_link_info;
	cur_link_info = &mhi_cntrl->mhi_link_info;
	/* if link is not in gen 1 we need to switch to gen 1 */
	/* if link is not in gen 1 we need to switch to gen 1 */
	if (cur_link_info->target_link_speed != PCI_EXP_LNKSTA_CLS_2_5GB) {
	if (cur_link_info->target_link_speed != PCI_EXP_LNKSTA_CLS_2_5GB) {
		link_info.target_link_speed = PCI_EXP_LNKSTA_CLS_2_5GB;
		link_info.target_link_speed = PCI_EXP_LNKSTA_CLS_2_5GB;
@@ -630,9 +588,6 @@ static int mhi_arch_drv_suspend(struct mhi_controller *mhi_cntrl)
		return ret;
		return ret;
	}
	}


	if (bw_switched)
		*cur_link_info = link_info;

	return ret;
	return ret;
}
}


@@ -689,7 +644,7 @@ static int __mhi_arch_link_resume(struct mhi_controller *mhi_cntrl)
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
	struct arch_info *arch_info = mhi_dev->arch_info;
	struct arch_info *arch_info = mhi_dev->arch_info;
	struct pci_dev *pci_dev = mhi_dev->pci_dev;
	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;
	int ret;


	MHI_LOG("Entered\n");
	MHI_LOG("Entered\n");
@@ -733,10 +688,8 @@ static int __mhi_arch_link_resume(struct mhi_controller *mhi_cntrl)
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 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 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;
	struct mhi_link_info *updated_info = &mhi_cntrl->mhi_link_info;
	int ret = 0;
	int ret = 0;


	MHI_LOG("Entered\n");
	MHI_LOG("Entered\n");
@@ -748,6 +701,19 @@ int mhi_arch_link_resume(struct mhi_controller *mhi_cntrl)
	case MHI_FAST_LINK_OFF:
	case MHI_FAST_LINK_OFF:
		ret = msm_pcie_pm_control(MSM_PCIE_RESUME, mhi_cntrl->bus,
		ret = msm_pcie_pm_control(MSM_PCIE_RESUME, mhi_cntrl->bus,
					  pci_dev, NULL, 0);
					  pci_dev, NULL, 0);
		if (ret ||
		    cur_info->target_link_speed == PCI_EXP_LNKSTA_CLS_2_5GB)
			break;

		/*
		 * BW request from device isn't for gen 1 link speed, we can
		 * only print an error here.
		 */
		if (mhi_arch_pcie_scale_bw(mhi_cntrl, pci_dev, cur_info))
			MHI_ERR(
			"Failed to honor bw request: speed:0x%x width:0x%x\n",
			cur_info->target_link_speed,
			cur_info->target_link_width);
		break;
		break;
	case MHI_ACTIVE_STATE:
	case MHI_ACTIVE_STATE:
	case MHI_FAST_LINK_ON:
	case MHI_FAST_LINK_ON:
@@ -759,14 +725,6 @@ int mhi_arch_link_resume(struct mhi_controller *mhi_cntrl)
		return ret;
		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);
	msm_pcie_l1ss_timeout_enable(pci_dev);


	MHI_LOG("Exited\n");
	MHI_LOG("Exited\n");
+0 −4
Original line number Original line Diff line number Diff line
@@ -609,10 +609,6 @@ static void mhi_status_cb(struct mhi_controller *mhi_cntrl,
		pm_runtime_mark_last_busy(dev);
		pm_runtime_mark_last_busy(dev);
		pm_request_autosuspend(dev);
		pm_request_autosuspend(dev);
		break;
		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:
	case MHI_CB_EE_MISSION_MODE:
		/*
		/*
		 * we need to force a suspend so device can switch to
		 * we need to force a suspend so device can switch to
+0 −3
Original line number Original line Diff line number Diff line
@@ -48,9 +48,6 @@ struct mhi_dev {
	dma_addr_t iova_stop;
	dma_addr_t iova_stop;
	enum mhi_suspend_mode suspend_mode;
	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;
	unsigned int lpm_disable_depth;
	/* lock to toggle low power modes */
	/* lock to toggle low power modes */
	spinlock_t lpm_lock;
	spinlock_t lpm_lock;