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

Commit 4e43ba3d authored by Lin Bai's avatar Lin Bai Committed by Gerrit - the friendly Code Review server
Browse files

cnss2: Add synchronized force wake support



Device is still possible to enter low power state with current
unsync force wake method, and it may cause later failure when
accessing SoC register.

Introduce sync force wake API and expose it to WLAN host driver,
which will ensure device won't enter low power state after
device_wake is asserted.

Change-Id: Iaa7a7bdac910c162600bbf03ac97af83b2f68f3f
Signed-off-by: default avatarLin Bai <lbai@codeaurora.org>
parent bbc7f2d3
Loading
Loading
Loading
Loading
+37 −13
Original line number Original line Diff line number Diff line
@@ -475,27 +475,22 @@ static int cnss_pci_reg_write(struct cnss_pci_data *pci_priv, u32 offset,
static int cnss_pci_force_wake_get(struct cnss_pci_data *pci_priv)
static int cnss_pci_force_wake_get(struct cnss_pci_data *pci_priv)
{
{
	struct device *dev = &pci_priv->pci_dev->dev;
	struct device *dev = &pci_priv->pci_dev->dev;
	u32 timeout = 0;
	int ret;
	int ret;


	ret = cnss_pci_force_wake_request(dev);
	ret = cnss_pci_force_wake_request_sync(dev,
					       FORCE_WAKE_DELAY_TIMEOUT_US);
	if (ret) {
	if (ret) {
		if (ret != -EAGAIN)
		if (ret != -EAGAIN)
			cnss_pr_err("Failed to request force wake\n");
			cnss_pr_err("Failed to request force wake\n");
		return ret;
		return ret;
	}
	}


	while (!cnss_pci_is_device_awake(dev) &&
	/* If device's M1 state-change event races here, it can be ignored,
	       timeout <= FORCE_WAKE_DELAY_TIMEOUT_US) {
	 * as the device is expected to immediately move from M2 to M0
		usleep_range(FORCE_WAKE_DELAY_MIN_US, FORCE_WAKE_DELAY_MAX_US);
	 * without entering low power state.
		timeout += FORCE_WAKE_DELAY_MAX_US;
	 */
	}
	if (cnss_pci_is_device_awake(dev) != true)

		cnss_pr_warn("MHI not in M0, while reg still accessible\n");
	if (cnss_pci_is_device_awake(dev) != true) {
		cnss_pr_err("Timed out to request force wake\n");
		cnss_pci_force_wake_release(dev);
		return -ETIMEDOUT;
	}


	return 0;
	return 0;
}
}
@@ -2938,6 +2933,35 @@ int cnss_auto_resume(struct device *dev)
}
}
EXPORT_SYMBOL(cnss_auto_resume);
EXPORT_SYMBOL(cnss_auto_resume);


int cnss_pci_force_wake_request_sync(struct device *dev, int timeout_us)
{
	struct pci_dev *pci_dev = to_pci_dev(dev);
	struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
	struct cnss_plat_data *plat_priv;
	struct mhi_controller *mhi_ctrl;

	if (!pci_priv)
		return -ENODEV;

	if (pci_priv->device_id != QCA6390_DEVICE_ID &&
	    pci_priv->device_id != QCA6490_DEVICE_ID)
		return 0;

	mhi_ctrl = pci_priv->mhi_ctrl;
	if (!mhi_ctrl)
		return -EINVAL;

	plat_priv = pci_priv->plat_priv;
	if (!plat_priv)
		return -ENODEV;

	if (test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state))
		return -EAGAIN;

	return mhi_device_get_sync_atomic(mhi_ctrl->mhi_dev, timeout_us);
}
EXPORT_SYMBOL(cnss_pci_force_wake_request_sync);

int cnss_pci_force_wake_request(struct device *dev)
int cnss_pci_force_wake_request(struct device *dev)
{
{
	struct pci_dev *pci_dev = to_pci_dev(dev);
	struct pci_dev *pci_dev = to_pci_dev(dev);
+1 −0
Original line number Original line Diff line number Diff line
@@ -212,6 +212,7 @@ extern int cnss_wlan_pm_control(struct device *dev, bool vote);
extern int cnss_auto_suspend(struct device *dev);
extern int cnss_auto_suspend(struct device *dev);
extern int cnss_auto_resume(struct device *dev);
extern int cnss_auto_resume(struct device *dev);
extern int cnss_pci_is_drv_connected(struct device *dev);
extern int cnss_pci_is_drv_connected(struct device *dev);
extern int cnss_pci_force_wake_request_sync(struct device *dev, int timeout);
extern int cnss_pci_force_wake_request(struct device *dev);
extern int cnss_pci_force_wake_request(struct device *dev);
extern int cnss_pci_is_device_awake(struct device *dev);
extern int cnss_pci_is_device_awake(struct device *dev);
extern int cnss_pci_force_wake_release(struct device *dev);
extern int cnss_pci_force_wake_release(struct device *dev);