net: atlantic: refactoring pm logic
authorNikita Danilov <ndanilov@marvell.com>
Thu, 7 Nov 2019 22:41:52 +0000 (22:41 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 8 Nov 2019 03:54:42 +0000 (19:54 -0800)
We now implement .driver.pm callbacks, these
allows driver to work correctly in hibernate
usecases, especially when used in conjunction with
WOL feature.

Before that driver only reacted to legacy .suspend/.resume
callbacks, that was a limitation in some cases.

Signed-off-by: Nikita Danilov <ndanilov@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/aquantia/atlantic/aq_nic.c
drivers/net/ethernet/aquantia/atlantic/aq_nic.h
drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c

index 75faf288a2fcb0fe432b8eae93e5788602d6aa18..d5764228cea5515f88a6d04ac600cdf0e7bdef73 100644 (file)
@@ -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;
index 8c23ad4ddf3805457abc605b7764a30309a0d3cf..ab3176dfc2090e96cdda06fa15af679d3f3e9284 100644 (file)
@@ -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);
index e82c96b50373b370b1918ceb9922e0d5afa0889e..3169951fe6ab8755ca07ce1717bfdb59cdc358b5 100644 (file)
@@ -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)