net: wwan: t7xx: Ensure init is completed before system sleep
[ Upstream commit ab87603b251134441a67385ecc9d3371be17b7a7 ] When the system attempts to sleep while mtk_t7xx is not ready, the driver cannot put the device to sleep: [ 12.472918] mtk_t7xx 0000:57:00.0: [PM] Exiting suspend, modem in invalid state [ 12.472936] mtk_t7xx 0000:57:00.0: PM: pci_pm_suspend(): t7xx_pci_pm_suspend+0x0/0x20 [mtk_t7xx] returns -14 [ 12.473678] mtk_t7xx 0000:57:00.0: PM: dpm_run_callback(): pci_pm_suspend+0x0/0x1b0 returns -14 [ 12.473711] mtk_t7xx 0000:57:00.0: PM: failed to suspend async: error -14 [ 12.764776] PM: Some devices failed to suspend, or early wake event detected Mediatek confirmed the device can take a rather long time to complete its initialization, so wait for up to 20 seconds until init is done. Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
ae72bd1a4b
commit
def67e27f2
2 changed files with 19 additions and 0 deletions
|
|
@ -45,6 +45,7 @@
|
||||||
#define T7XX_PCI_IREG_BASE 0
|
#define T7XX_PCI_IREG_BASE 0
|
||||||
#define T7XX_PCI_EREG_BASE 2
|
#define T7XX_PCI_EREG_BASE 2
|
||||||
|
|
||||||
|
#define T7XX_INIT_TIMEOUT 20
|
||||||
#define PM_SLEEP_DIS_TIMEOUT_MS 20
|
#define PM_SLEEP_DIS_TIMEOUT_MS 20
|
||||||
#define PM_ACK_TIMEOUT_MS 1500
|
#define PM_ACK_TIMEOUT_MS 1500
|
||||||
#define PM_AUTOSUSPEND_MS 20000
|
#define PM_AUTOSUSPEND_MS 20000
|
||||||
|
|
@ -96,6 +97,7 @@ static int t7xx_pci_pm_init(struct t7xx_pci_dev *t7xx_dev)
|
||||||
spin_lock_init(&t7xx_dev->md_pm_lock);
|
spin_lock_init(&t7xx_dev->md_pm_lock);
|
||||||
init_completion(&t7xx_dev->sleep_lock_acquire);
|
init_completion(&t7xx_dev->sleep_lock_acquire);
|
||||||
init_completion(&t7xx_dev->pm_sr_ack);
|
init_completion(&t7xx_dev->pm_sr_ack);
|
||||||
|
init_completion(&t7xx_dev->init_done);
|
||||||
atomic_set(&t7xx_dev->md_pm_state, MTK_PM_INIT);
|
atomic_set(&t7xx_dev->md_pm_state, MTK_PM_INIT);
|
||||||
|
|
||||||
device_init_wakeup(&pdev->dev, true);
|
device_init_wakeup(&pdev->dev, true);
|
||||||
|
|
@ -124,6 +126,7 @@ void t7xx_pci_pm_init_late(struct t7xx_pci_dev *t7xx_dev)
|
||||||
pm_runtime_mark_last_busy(&t7xx_dev->pdev->dev);
|
pm_runtime_mark_last_busy(&t7xx_dev->pdev->dev);
|
||||||
pm_runtime_allow(&t7xx_dev->pdev->dev);
|
pm_runtime_allow(&t7xx_dev->pdev->dev);
|
||||||
pm_runtime_put_noidle(&t7xx_dev->pdev->dev);
|
pm_runtime_put_noidle(&t7xx_dev->pdev->dev);
|
||||||
|
complete_all(&t7xx_dev->init_done);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int t7xx_pci_pm_reinit(struct t7xx_pci_dev *t7xx_dev)
|
static int t7xx_pci_pm_reinit(struct t7xx_pci_dev *t7xx_dev)
|
||||||
|
|
@ -529,6 +532,20 @@ static void t7xx_pci_shutdown(struct pci_dev *pdev)
|
||||||
__t7xx_pci_pm_suspend(pdev);
|
__t7xx_pci_pm_suspend(pdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int t7xx_pci_pm_prepare(struct device *dev)
|
||||||
|
{
|
||||||
|
struct pci_dev *pdev = to_pci_dev(dev);
|
||||||
|
struct t7xx_pci_dev *t7xx_dev;
|
||||||
|
|
||||||
|
t7xx_dev = pci_get_drvdata(pdev);
|
||||||
|
if (!wait_for_completion_timeout(&t7xx_dev->init_done, T7XX_INIT_TIMEOUT * HZ)) {
|
||||||
|
dev_warn(dev, "Not ready for system sleep.\n");
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int t7xx_pci_pm_suspend(struct device *dev)
|
static int t7xx_pci_pm_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
return __t7xx_pci_pm_suspend(to_pci_dev(dev));
|
return __t7xx_pci_pm_suspend(to_pci_dev(dev));
|
||||||
|
|
@ -555,6 +572,7 @@ static int t7xx_pci_pm_runtime_resume(struct device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct dev_pm_ops t7xx_pci_pm_ops = {
|
static const struct dev_pm_ops t7xx_pci_pm_ops = {
|
||||||
|
.prepare = t7xx_pci_pm_prepare,
|
||||||
.suspend = t7xx_pci_pm_suspend,
|
.suspend = t7xx_pci_pm_suspend,
|
||||||
.resume = t7xx_pci_pm_resume,
|
.resume = t7xx_pci_pm_resume,
|
||||||
.resume_noirq = t7xx_pci_pm_resume_noirq,
|
.resume_noirq = t7xx_pci_pm_resume_noirq,
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ struct t7xx_pci_dev {
|
||||||
struct t7xx_modem *md;
|
struct t7xx_modem *md;
|
||||||
struct t7xx_ccmni_ctrl *ccmni_ctlb;
|
struct t7xx_ccmni_ctrl *ccmni_ctlb;
|
||||||
bool rgu_pci_irq_en;
|
bool rgu_pci_irq_en;
|
||||||
|
struct completion init_done;
|
||||||
|
|
||||||
/* Low Power Items */
|
/* Low Power Items */
|
||||||
struct list_head md_pm_entities;
|
struct list_head md_pm_entities;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue