diff options
| -rw-r--r-- | drivers/net/sfc/efx.c | 96 | ||||
| -rw-r--r-- | drivers/net/sfc/ethtool.c | 17 | ||||
| -rw-r--r-- | drivers/net/sfc/falcon.c | 27 | ||||
| -rw-r--r-- | drivers/net/sfc/net_driver.h | 6 |
4 files changed, 146 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 | /************************************************************************** |
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index d95d0fa399ff..b4c6ea1b9c07 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c | |||
| @@ -739,6 +739,21 @@ static void efx_ethtool_get_pauseparam(struct net_device *net_dev, | |||
| 739 | } | 739 | } |
| 740 | 740 | ||
| 741 | 741 | ||
| 742 | static void efx_ethtool_get_wol(struct net_device *net_dev, | ||
| 743 | struct ethtool_wolinfo *wol) | ||
| 744 | { | ||
| 745 | struct efx_nic *efx = netdev_priv(net_dev); | ||
| 746 | return efx->type->get_wol(efx, wol); | ||
| 747 | } | ||
| 748 | |||
| 749 | |||
| 750 | static int efx_ethtool_set_wol(struct net_device *net_dev, | ||
| 751 | struct ethtool_wolinfo *wol) | ||
| 752 | { | ||
| 753 | struct efx_nic *efx = netdev_priv(net_dev); | ||
| 754 | return efx->type->set_wol(efx, wol->wolopts); | ||
| 755 | } | ||
| 756 | |||
| 742 | const struct ethtool_ops efx_ethtool_ops = { | 757 | const struct ethtool_ops efx_ethtool_ops = { |
| 743 | .get_settings = efx_ethtool_get_settings, | 758 | .get_settings = efx_ethtool_get_settings, |
| 744 | .set_settings = efx_ethtool_set_settings, | 759 | .set_settings = efx_ethtool_set_settings, |
| @@ -767,4 +782,6 @@ const struct ethtool_ops efx_ethtool_ops = { | |||
| 767 | .get_strings = efx_ethtool_get_strings, | 782 | .get_strings = efx_ethtool_get_strings, |
| 768 | .phys_id = efx_ethtool_phys_id, | 783 | .phys_id = efx_ethtool_phys_id, |
| 769 | .get_ethtool_stats = efx_ethtool_get_stats, | 784 | .get_ethtool_stats = efx_ethtool_get_stats, |
| 785 | .get_wol = efx_ethtool_get_wol, | ||
| 786 | .set_wol = efx_ethtool_set_wol, | ||
| 770 | }; | 787 | }; |
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 3466616c01c0..8f2c58305538 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c | |||
| @@ -3245,6 +3245,27 @@ void falcon_stop_nic_stats(struct efx_nic *efx) | |||
| 3245 | 3245 | ||
| 3246 | /************************************************************************** | 3246 | /************************************************************************** |
| 3247 | * | 3247 | * |
| 3248 | * Wake on LAN | ||
| 3249 | * | ||
| 3250 | ************************************************************************** | ||
| 3251 | */ | ||
| 3252 | |||
| 3253 | static void falcon_get_wol(struct efx_nic *efx, struct ethtool_wolinfo *wol) | ||
| 3254 | { | ||
| 3255 | wol->supported = 0; | ||
| 3256 | wol->wolopts = 0; | ||
| 3257 | memset(&wol->sopass, 0, sizeof(wol->sopass)); | ||
| 3258 | } | ||
| 3259 | |||
| 3260 | static int falcon_set_wol(struct efx_nic *efx, u32 type) | ||
| 3261 | { | ||
| 3262 | if (type != 0) | ||
| 3263 | return -EINVAL; | ||
| 3264 | return 0; | ||
| 3265 | } | ||
| 3266 | |||
| 3267 | /************************************************************************** | ||
| 3268 | * | ||
| 3248 | * Revision-dependent attributes used by efx.c | 3269 | * Revision-dependent attributes used by efx.c |
| 3249 | * | 3270 | * |
| 3250 | ************************************************************************** | 3271 | ************************************************************************** |
| @@ -3266,6 +3287,9 @@ struct efx_nic_type falcon_a1_nic_type = { | |||
| 3266 | .push_irq_moderation = falcon_push_irq_moderation, | 3287 | .push_irq_moderation = falcon_push_irq_moderation, |
| 3267 | .push_multicast_hash = falcon_push_multicast_hash, | 3288 | .push_multicast_hash = falcon_push_multicast_hash, |
| 3268 | .reconfigure_port = falcon_reconfigure_port, | 3289 | .reconfigure_port = falcon_reconfigure_port, |
| 3290 | .get_wol = falcon_get_wol, | ||
| 3291 | .set_wol = falcon_set_wol, | ||
| 3292 | .resume_wol = efx_port_dummy_op_void, | ||
| 3269 | .default_mac_ops = &falcon_xmac_operations, | 3293 | .default_mac_ops = &falcon_xmac_operations, |
| 3270 | 3294 | ||
| 3271 | .revision = EFX_REV_FALCON_A1, | 3295 | .revision = EFX_REV_FALCON_A1, |
| @@ -3299,6 +3323,9 @@ struct efx_nic_type falcon_b0_nic_type = { | |||
| 3299 | .push_irq_moderation = falcon_push_irq_moderation, | 3323 | .push_irq_moderation = falcon_push_irq_moderation, |
| 3300 | .push_multicast_hash = falcon_push_multicast_hash, | 3324 | .push_multicast_hash = falcon_push_multicast_hash, |
| 3301 | .reconfigure_port = falcon_reconfigure_port, | 3325 | .reconfigure_port = falcon_reconfigure_port, |
| 3326 | .get_wol = falcon_get_wol, | ||
| 3327 | .set_wol = falcon_set_wol, | ||
| 3328 | .resume_wol = efx_port_dummy_op_void, | ||
| 3302 | .default_mac_ops = &falcon_xmac_operations, | 3329 | .default_mac_ops = &falcon_xmac_operations, |
| 3303 | 3330 | ||
| 3304 | .revision = EFX_REV_FALCON_B0, | 3331 | .revision = EFX_REV_FALCON_B0, |
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index f63a05c4e38b..a9fde82aeeae 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
| @@ -861,6 +861,9 @@ static inline const char *efx_dev_name(struct efx_nic *efx) | |||
| 861 | * @push_irq_moderation: Apply interrupt moderation value | 861 | * @push_irq_moderation: Apply interrupt moderation value |
| 862 | * @push_multicast_hash: Apply multicast hash table | 862 | * @push_multicast_hash: Apply multicast hash table |
| 863 | * @reconfigure_port: Push loopback/power/txdis changes to the MAC and PHY | 863 | * @reconfigure_port: Push loopback/power/txdis changes to the MAC and PHY |
| 864 | * @get_wol: Get WoL configuration from driver state | ||
| 865 | * @set_wol: Push WoL configuration to the NIC | ||
| 866 | * @resume_wol: Synchronise WoL state between driver and MC (e.g. after resume) | ||
| 864 | * @default_mac_ops: efx_mac_operations to set at startup | 867 | * @default_mac_ops: efx_mac_operations to set at startup |
| 865 | * @revision: Hardware architecture revision | 868 | * @revision: Hardware architecture revision |
| 866 | * @mem_map_size: Memory BAR mapped size | 869 | * @mem_map_size: Memory BAR mapped size |
| @@ -894,6 +897,9 @@ struct efx_nic_type { | |||
| 894 | void (*push_irq_moderation)(struct efx_channel *channel); | 897 | void (*push_irq_moderation)(struct efx_channel *channel); |
| 895 | void (*push_multicast_hash)(struct efx_nic *efx); | 898 | void (*push_multicast_hash)(struct efx_nic *efx); |
| 896 | int (*reconfigure_port)(struct efx_nic *efx); | 899 | int (*reconfigure_port)(struct efx_nic *efx); |
| 900 | void (*get_wol)(struct efx_nic *efx, struct ethtool_wolinfo *wol); | ||
| 901 | int (*set_wol)(struct efx_nic *efx, u32 type); | ||
| 902 | void (*resume_wol)(struct efx_nic *efx); | ||
| 897 | struct efx_mac_operations *default_mac_ops; | 903 | struct efx_mac_operations *default_mac_ops; |
| 898 | 904 | ||
| 899 | int revision; | 905 | int revision; |
