Skip to content

Commit

Permalink
net: atlantic: refactoring pm logic
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Nikita Danilov authored and davem330 committed Nov 8, 2019
1 parent 837c637 commit 8aaa112
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 48 deletions.
38 changes: 0 additions & 38 deletions drivers/net/ethernet/aquantia/atlantic/aq_nic.c
Expand Up @@ -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;
Expand Down
1 change: 0 additions & 1 deletion drivers/net/ethernet/aquantia/atlantic/aq_nic.h
Expand Up @@ -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);
Expand Down
87 changes: 78 additions & 9 deletions drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
Expand Up @@ -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)
Expand Down

0 comments on commit 8aaa112

Please sign in to comment.