sfc: Add power-management and wake-on-LAN support

Wake-on-LAN is a stub for Falcon, but will be implemented fully for
new NICs.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Ben Hutchings
2009-11-29 03:43:07 +00:00
committed by David S. Miller
parent 78c1f0a065
commit 89c758fa47
4 changed files with 146 additions and 0 deletions

View File

@@ -2243,11 +2243,107 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
return rc;
}
static int efx_pm_freeze(struct device *dev)
{
struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
efx->state = STATE_FINI;
netif_device_detach(efx->net_dev);
efx_stop_all(efx);
efx_fini_channels(efx);
return 0;
}
static int efx_pm_thaw(struct device *dev)
{
struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
efx->state = STATE_INIT;
efx_init_channels(efx);
mutex_lock(&efx->mac_lock);
efx->phy_op->reconfigure(efx);
mutex_unlock(&efx->mac_lock);
efx_start_all(efx);
netif_device_attach(efx->net_dev);
efx->state = STATE_RUNNING;
efx->type->resume_wol(efx);
return 0;
}
static int efx_pm_poweroff(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct efx_nic *efx = pci_get_drvdata(pci_dev);
efx->type->fini(efx);
efx->reset_pending = RESET_TYPE_NONE;
pci_save_state(pci_dev);
return pci_set_power_state(pci_dev, PCI_D3hot);
}
/* Used for both resume and restore */
static int efx_pm_resume(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct efx_nic *efx = pci_get_drvdata(pci_dev);
int rc;
rc = pci_set_power_state(pci_dev, PCI_D0);
if (rc)
return rc;
pci_restore_state(pci_dev);
rc = pci_enable_device(pci_dev);
if (rc)
return rc;
pci_set_master(efx->pci_dev);
rc = efx->type->reset(efx, RESET_TYPE_ALL);
if (rc)
return rc;
rc = efx->type->init(efx);
if (rc)
return rc;
efx_pm_thaw(dev);
return 0;
}
static int efx_pm_suspend(struct device *dev)
{
int rc;
efx_pm_freeze(dev);
rc = efx_pm_poweroff(dev);
if (rc)
efx_pm_resume(dev);
return rc;
}
static struct dev_pm_ops efx_pm_ops = {
.suspend = efx_pm_suspend,
.resume = efx_pm_resume,
.freeze = efx_pm_freeze,
.thaw = efx_pm_thaw,
.poweroff = efx_pm_poweroff,
.restore = efx_pm_resume,
};
static struct pci_driver efx_pci_driver = {
.name = EFX_DRIVER_NAME,
.id_table = efx_pci_table,
.probe = efx_pci_probe,
.remove = efx_pci_remove,
.driver.pm = &efx_pm_ops,
};
/**************************************************************************