diff options
Diffstat (limited to 'drivers/net/sfc/efx.c')
-rw-r--r-- | drivers/net/sfc/efx.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 14ef27fa8416..b016719d8f67 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -2243,11 +2243,107 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, | |||
2243 | return rc; | 2243 | return rc; |
2244 | } | 2244 | } |
2245 | 2245 | ||
2246 | static int efx_pm_freeze(struct device *dev) | ||
2247 | { | ||
2248 | struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); | ||
2249 | |||
2250 | efx->state = STATE_FINI; | ||
2251 | |||
2252 | netif_device_detach(efx->net_dev); | ||
2253 | |||
2254 | efx_stop_all(efx); | ||
2255 | efx_fini_channels(efx); | ||
2256 | |||
2257 | return 0; | ||
2258 | } | ||
2259 | |||
2260 | static int efx_pm_thaw(struct device *dev) | ||
2261 | { | ||
2262 | struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); | ||
2263 | |||
2264 | efx->state = STATE_INIT; | ||
2265 | |||
2266 | efx_init_channels(efx); | ||
2267 | |||
2268 | mutex_lock(&efx->mac_lock); | ||
2269 | efx->phy_op->reconfigure(efx); | ||
2270 | mutex_unlock(&efx->mac_lock); | ||
2271 | |||
2272 | efx_start_all(efx); | ||
2273 | |||
2274 | netif_device_attach(efx->net_dev); | ||
2275 | |||
2276 | efx->state = STATE_RUNNING; | ||
2277 | |||
2278 | efx->type->resume_wol(efx); | ||
2279 | |||
2280 | return 0; | ||
2281 | } | ||
2282 | |||
2283 | static int efx_pm_poweroff(struct device *dev) | ||
2284 | { | ||
2285 | struct pci_dev *pci_dev = to_pci_dev(dev); | ||
2286 | struct efx_nic *efx = pci_get_drvdata(pci_dev); | ||
2287 | |||
2288 | efx->type->fini(efx); | ||
2289 | |||
2290 | efx->reset_pending = RESET_TYPE_NONE; | ||
2291 | |||
2292 | pci_save_state(pci_dev); | ||
2293 | return pci_set_power_state(pci_dev, PCI_D3hot); | ||
2294 | } | ||
2295 | |||
2296 | /* Used for both resume and restore */ | ||
2297 | static int efx_pm_resume(struct device *dev) | ||
2298 | { | ||
2299 | struct pci_dev *pci_dev = to_pci_dev(dev); | ||
2300 | struct efx_nic *efx = pci_get_drvdata(pci_dev); | ||
2301 | int rc; | ||
2302 | |||
2303 | rc = pci_set_power_state(pci_dev, PCI_D0); | ||
2304 | if (rc) | ||
2305 | return rc; | ||
2306 | pci_restore_state(pci_dev); | ||
2307 | rc = pci_enable_device(pci_dev); | ||
2308 | if (rc) | ||
2309 | return rc; | ||
2310 | pci_set_master(efx->pci_dev); | ||
2311 | rc = efx->type->reset(efx, RESET_TYPE_ALL); | ||
2312 | if (rc) | ||
2313 | return rc; | ||
2314 | rc = efx->type->init(efx); | ||
2315 | if (rc) | ||
2316 | return rc; | ||
2317 | efx_pm_thaw(dev); | ||
2318 | return 0; | ||
2319 | } | ||
2320 | |||
2321 | static int efx_pm_suspend(struct device *dev) | ||
2322 | { | ||
2323 | int rc; | ||
2324 | |||
2325 | efx_pm_freeze(dev); | ||
2326 | rc = efx_pm_poweroff(dev); | ||
2327 | if (rc) | ||
2328 | efx_pm_resume(dev); | ||
2329 | return rc; | ||
2330 | } | ||
2331 | |||
2332 | static struct dev_pm_ops efx_pm_ops = { | ||
2333 | .suspend = efx_pm_suspend, | ||
2334 | .resume = efx_pm_resume, | ||
2335 | .freeze = efx_pm_freeze, | ||
2336 | .thaw = efx_pm_thaw, | ||
2337 | .poweroff = efx_pm_poweroff, | ||
2338 | .restore = efx_pm_resume, | ||
2339 | }; | ||
2340 | |||
2246 | static struct pci_driver efx_pci_driver = { | 2341 | static struct pci_driver efx_pci_driver = { |
2247 | .name = EFX_DRIVER_NAME, | 2342 | .name = EFX_DRIVER_NAME, |
2248 | .id_table = efx_pci_table, | 2343 | .id_table = efx_pci_table, |
2249 | .probe = efx_pci_probe, | 2344 | .probe = efx_pci_probe, |
2250 | .remove = efx_pci_remove, | 2345 | .remove = efx_pci_remove, |
2346 | .driver.pm = &efx_pm_ops, | ||
2251 | }; | 2347 | }; |
2252 | 2348 | ||
2253 | /************************************************************************** | 2349 | /************************************************************************** |