diff options
-rw-r--r-- | drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 38 | ||||
-rw-r--r-- | drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c | 87 |
3 files changed, 78 insertions, 48 deletions
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c index 75faf288a2fc..d5764228cea5 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c @@ -1057,44 +1057,6 @@ void aq_nic_free_vectors(struct aq_nic_s *self) err_exit:; } -int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg) -{ - int err = 0; - - if (!netif_running(self->ndev)) { - err = 0; - goto out; - } - rtnl_lock(); - if (pm_msg->event & PM_EVENT_SLEEP || pm_msg->event & PM_EVENT_FREEZE) { - self->power_state = AQ_HW_POWER_STATE_D3; - netif_device_detach(self->ndev); - netif_tx_stop_all_queues(self->ndev); - - err = aq_nic_stop(self); - if (err < 0) - goto err_exit; - - aq_nic_deinit(self, !self->aq_hw->aq_nic_cfg->wol); - } else { - err = aq_nic_init(self); - if (err < 0) - goto err_exit; - - err = aq_nic_start(self); - if (err < 0) - goto err_exit; - - netif_device_attach(self->ndev); - netif_tx_start_all_queues(self->ndev); - } - -err_exit: - rtnl_unlock(); -out: - return err; -} - void aq_nic_shutdown(struct aq_nic_s *self) { int err = 0; diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h index 8c23ad4ddf38..ab3176dfc209 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h @@ -157,7 +157,6 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self, const struct ethtool_link_ksettings *cmd); struct aq_nic_cfg_s *aq_nic_get_cfg(struct aq_nic_s *self); u32 aq_nic_get_fw_version(struct aq_nic_s *self); -int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg); int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self); void aq_nic_shutdown(struct aq_nic_s *self); u8 aq_nic_reserve_filter(struct aq_nic_s *self, enum aq_rx_filter_type type); diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c index e82c96b50373..3169951fe6ab 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c @@ -347,29 +347,98 @@ static void aq_pci_shutdown(struct pci_dev *pdev) } } -static int aq_pci_suspend(struct pci_dev *pdev, pm_message_t pm_msg) +static int aq_suspend_common(struct device *dev, bool deep) { - struct aq_nic_s *self = pci_get_drvdata(pdev); + struct aq_nic_s *nic = pci_get_drvdata(to_pci_dev(dev)); + + rtnl_lock(); + + nic->power_state = AQ_HW_POWER_STATE_D3; + netif_device_detach(nic->ndev); + netif_tx_stop_all_queues(nic->ndev); - return aq_nic_change_pm_state(self, &pm_msg); + aq_nic_stop(nic); + + if (deep) { + aq_nic_deinit(nic, !nic->aq_hw->aq_nic_cfg->wol); + aq_nic_set_power(nic); + } + + rtnl_unlock(); + + return 0; } -static int aq_pci_resume(struct pci_dev *pdev) +static int atl_resume_common(struct device *dev, bool deep) { - struct aq_nic_s *self = pci_get_drvdata(pdev); - pm_message_t pm_msg = PMSG_RESTORE; + struct pci_dev *pdev = to_pci_dev(dev); + struct aq_nic_s *nic; + int ret; + + nic = pci_get_drvdata(pdev); + + rtnl_lock(); + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + if (deep) { + ret = aq_nic_init(nic); + if (ret) + goto err_exit; + } + + ret = aq_nic_start(nic); + if (ret) + goto err_exit; + + netif_device_attach(nic->ndev); + netif_tx_start_all_queues(nic->ndev); - return aq_nic_change_pm_state(self, &pm_msg); +err_exit: + rtnl_unlock(); + + return ret; +} + +static int aq_pm_freeze(struct device *dev) +{ + return aq_suspend_common(dev, false); } +static int aq_pm_suspend_poweroff(struct device *dev) +{ + return aq_suspend_common(dev, true); +} + +static int aq_pm_thaw(struct device *dev) +{ + return atl_resume_common(dev, false); +} + +static int aq_pm_resume_restore(struct device *dev) +{ + return atl_resume_common(dev, true); +} + +const struct dev_pm_ops aq_pm_ops = { + .suspend = aq_pm_suspend_poweroff, + .poweroff = aq_pm_suspend_poweroff, + .freeze = aq_pm_freeze, + .resume = aq_pm_resume_restore, + .restore = aq_pm_resume_restore, + .thaw = aq_pm_thaw, +}; + static struct pci_driver aq_pci_ops = { .name = AQ_CFG_DRV_NAME, .id_table = aq_pci_tbl, .probe = aq_pci_probe, .remove = aq_pci_remove, - .suspend = aq_pci_suspend, - .resume = aq_pci_resume, .shutdown = aq_pci_shutdown, +#ifdef CONFIG_PM + .driver.pm = &aq_pm_ops, +#endif }; int aq_pci_func_register_driver(void) |