提交 c2a43a6b 编写于 作者: H Hante Meuleman 提交者: Kalle Valo

brcmfmac: Use new methods for pcie Power Management.

Currently the legacy methods suspend and resume are used for pcie
devices. This is not the preferable method and is also causing
issues with some setups when doing hibernate. Changing this to
use the new PM methods.
Reviewed-by: NArend Van Spriel <arend@broadcom.com>
Reviewed-by: NFranky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: NPieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: NHante Meuleman <meuleman@broadcom.com>
Signed-off-by: NArend van Spriel <arend@broadcom.com>
Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
上级 37a869ec
无相关合并请求
......@@ -1388,10 +1388,6 @@ static void brcmf_pcie_wowl_config(struct device *dev, bool enabled)
brcmf_dbg(PCIE, "Configuring WOWL, enabled=%d\n", enabled);
devinfo->wowl_enabled = enabled;
if (enabled)
device_set_wakeup_enable(&devinfo->pdev->dev, true);
else
device_set_wakeup_enable(&devinfo->pdev->dev, false);
}
......@@ -1961,15 +1957,14 @@ brcmf_pcie_remove(struct pci_dev *pdev)
#ifdef CONFIG_PM
static int brcmf_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
static int brcmf_pcie_pm_enter_D3(struct device *dev)
{
struct brcmf_pciedev_info *devinfo;
struct brcmf_bus *bus;
int err;
brcmf_dbg(PCIE, "Enter, state=%d, pdev=%p\n", state.event, pdev);
brcmf_err("Enter\n");
bus = dev_get_drvdata(&pdev->dev);
bus = dev_get_drvdata(dev);
devinfo = bus->bus_priv.pcie->devinfo;
brcmf_bus_change_state(bus, BRCMF_BUS_DOWN);
......@@ -1984,62 +1979,45 @@ static int brcmf_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
brcmf_err("Timeout on response for entering D3 substate\n");
return -EIO;
}
brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM_IN_USE);
err = pci_save_state(pdev);
if (err)
brcmf_err("pci_save_state failed, err=%d\n", err);
if ((err) || (!devinfo->wowl_enabled)) {
brcmf_chip_detach(devinfo->ci);
devinfo->ci = NULL;
brcmf_pcie_remove(pdev);
return 0;
}
devinfo->state = BRCMFMAC_PCIE_STATE_DOWN;
return pci_prepare_to_sleep(pdev);
return 0;
}
static int brcmf_pcie_resume(struct pci_dev *pdev)
static int brcmf_pcie_pm_leave_D3(struct device *dev)
{
struct brcmf_pciedev_info *devinfo;
struct brcmf_bus *bus;
struct pci_dev *pdev;
int err;
bus = dev_get_drvdata(&pdev->dev);
brcmf_dbg(PCIE, "Enter, pdev=%p, bus=%p\n", pdev, bus);
brcmf_err("Enter\n");
err = pci_set_power_state(pdev, PCI_D0);
if (err) {
brcmf_err("pci_set_power_state failed, err=%d\n", err);
goto cleanup;
}
pci_restore_state(pdev);
pci_enable_wake(pdev, PCI_D3hot, false);
pci_enable_wake(pdev, PCI_D3cold, false);
bus = dev_get_drvdata(dev);
devinfo = bus->bus_priv.pcie->devinfo;
brcmf_dbg(PCIE, "Enter, dev=%p, bus=%p\n", dev, bus);
/* Check if device is still up and running, if so we are ready */
if (bus) {
devinfo = bus->bus_priv.pcie->devinfo;
if (brcmf_pcie_read_reg32(devinfo,
BRCMF_PCIE_PCIE2REG_INTMASK) != 0) {
if (brcmf_pcie_send_mb_data(devinfo,
BRCMF_H2D_HOST_D0_INFORM))
goto cleanup;
brcmf_dbg(PCIE, "Hot resume, continue....\n");
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
brcmf_bus_change_state(bus, BRCMF_BUS_UP);
brcmf_pcie_intr_enable(devinfo);
return 0;
}
if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0) {
brcmf_dbg(PCIE, "Try to wakeup device....\n");
if (brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM))
goto cleanup;
brcmf_dbg(PCIE, "Hot resume, continue....\n");
devinfo->state = BRCMFMAC_PCIE_STATE_UP;
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
brcmf_bus_change_state(bus, BRCMF_BUS_UP);
brcmf_pcie_intr_enable(devinfo);
return 0;
}
cleanup:
if (bus) {
devinfo = bus->bus_priv.pcie->devinfo;
brcmf_chip_detach(devinfo->ci);
devinfo->ci = NULL;
brcmf_pcie_remove(pdev);
}
brcmf_chip_detach(devinfo->ci);
devinfo->ci = NULL;
pdev = devinfo->pdev;
brcmf_pcie_remove(pdev);
err = brcmf_pcie_probe(pdev, NULL);
if (err)
brcmf_err("probe after resume failed, err=%d\n", err);
......@@ -2048,6 +2026,14 @@ static int brcmf_pcie_resume(struct pci_dev *pdev)
}
static const struct dev_pm_ops brcmf_pciedrvr_pm = {
.suspend = brcmf_pcie_pm_enter_D3,
.resume = brcmf_pcie_pm_leave_D3,
.freeze = brcmf_pcie_pm_enter_D3,
.restore = brcmf_pcie_pm_leave_D3,
};
#endif /* CONFIG_PM */
......@@ -2086,9 +2072,8 @@ static struct pci_driver brcmf_pciedrvr = {
.probe = brcmf_pcie_probe,
.remove = brcmf_pcie_remove,
#ifdef CONFIG_PM
.suspend = brcmf_pcie_suspend,
.resume = brcmf_pcie_resume
#endif /* CONFIG_PM */
.driver.pm = &brcmf_pciedrvr_pm,
#endif
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部