diff options
author | Maxim Levitsky <maximlevitsky@gmail.com> | 2007-03-06 05:41:54 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-04-28 11:00:57 -0400 |
commit | f1069046b4c7a5750611305433646c1bff3686fd (patch) | |
tree | 0b2b419938c19b0ed325fc05c0b7860788ee0de8 /drivers/net/tulip | |
parent | bc8a8387ba57db2275e717c19838a8d5a404c270 (diff) |
dmfe: add support for Wake on lan
Add support for WOL on Magic Packet and on link change
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
Cc: Valerie Henson <val_henson@linux.intel.com>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/tulip')
-rw-r--r-- | drivers/net/tulip/dmfe.c | 66 |
1 files changed, 64 insertions, 2 deletions
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index e3a077977e4c..4ed67ff0e81e 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c | |||
@@ -122,6 +122,11 @@ | |||
122 | #define DM9801_NOISE_FLOOR 8 | 122 | #define DM9801_NOISE_FLOOR 8 |
123 | #define DM9802_NOISE_FLOOR 5 | 123 | #define DM9802_NOISE_FLOOR 5 |
124 | 124 | ||
125 | #define DMFE_WOL_LINKCHANGE 0x20000000 | ||
126 | #define DMFE_WOL_SAMPLEPACKET 0x10000000 | ||
127 | #define DMFE_WOL_MAGICPACKET 0x08000000 | ||
128 | |||
129 | |||
125 | #define DMFE_10MHF 0 | 130 | #define DMFE_10MHF 0 |
126 | #define DMFE_100MHF 1 | 131 | #define DMFE_100MHF 1 |
127 | #define DMFE_10MFD 4 | 132 | #define DMFE_10MFD 4 |
@@ -248,6 +253,7 @@ struct dmfe_board_info { | |||
248 | u8 wait_reset; /* Hardware failed, need to reset */ | 253 | u8 wait_reset; /* Hardware failed, need to reset */ |
249 | u8 dm910x_chk_mode; /* Operating mode check */ | 254 | u8 dm910x_chk_mode; /* Operating mode check */ |
250 | u8 first_in_callback; /* Flag to record state */ | 255 | u8 first_in_callback; /* Flag to record state */ |
256 | u8 wol_mode; /* user WOL settings */ | ||
251 | struct timer_list timer; | 257 | struct timer_list timer; |
252 | 258 | ||
253 | /* System defined statistic counter */ | 259 | /* System defined statistic counter */ |
@@ -428,6 +434,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, | |||
428 | db->chip_id = ent->driver_data; | 434 | db->chip_id = ent->driver_data; |
429 | db->ioaddr = pci_resource_start(pdev, 0); | 435 | db->ioaddr = pci_resource_start(pdev, 0); |
430 | db->chip_revision = dev_rev; | 436 | db->chip_revision = dev_rev; |
437 | db->wol_mode = 0; | ||
431 | 438 | ||
432 | db->pdev = pdev; | 439 | db->pdev = pdev; |
433 | 440 | ||
@@ -1062,7 +1069,11 @@ static void dmfe_set_filter_mode(struct DEVICE * dev) | |||
1062 | spin_unlock_irqrestore(&db->lock, flags); | 1069 | spin_unlock_irqrestore(&db->lock, flags); |
1063 | } | 1070 | } |
1064 | 1071 | ||
1065 | static void netdev_get_drvinfo(struct net_device *dev, | 1072 | /* |
1073 | * Ethtool interace | ||
1074 | */ | ||
1075 | |||
1076 | static void dmfe_ethtool_get_drvinfo(struct net_device *dev, | ||
1066 | struct ethtool_drvinfo *info) | 1077 | struct ethtool_drvinfo *info) |
1067 | { | 1078 | { |
1068 | struct dmfe_board_info *np = netdev_priv(dev); | 1079 | struct dmfe_board_info *np = netdev_priv(dev); |
@@ -1076,9 +1087,35 @@ static void netdev_get_drvinfo(struct net_device *dev, | |||
1076 | dev->base_addr, dev->irq); | 1087 | dev->base_addr, dev->irq); |
1077 | } | 1088 | } |
1078 | 1089 | ||
1090 | static int dmfe_ethtool_set_wol(struct net_device *dev, | ||
1091 | struct ethtool_wolinfo *wolinfo) | ||
1092 | { | ||
1093 | struct dmfe_board_info *db = netdev_priv(dev); | ||
1094 | |||
1095 | if (wolinfo->wolopts & (WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | | ||
1096 | WAKE_ARP | WAKE_MAGICSECURE)) | ||
1097 | return -EOPNOTSUPP; | ||
1098 | |||
1099 | db->wol_mode = wolinfo->wolopts; | ||
1100 | return 0; | ||
1101 | } | ||
1102 | |||
1103 | static void dmfe_ethtool_get_wol(struct net_device *dev, | ||
1104 | struct ethtool_wolinfo *wolinfo) | ||
1105 | { | ||
1106 | struct dmfe_board_info *db = netdev_priv(dev); | ||
1107 | |||
1108 | wolinfo->supported = WAKE_PHY | WAKE_MAGIC; | ||
1109 | wolinfo->wolopts = db->wol_mode; | ||
1110 | return; | ||
1111 | } | ||
1112 | |||
1113 | |||
1079 | static const struct ethtool_ops netdev_ethtool_ops = { | 1114 | static const struct ethtool_ops netdev_ethtool_ops = { |
1080 | .get_drvinfo = netdev_get_drvinfo, | 1115 | .get_drvinfo = dmfe_ethtool_get_drvinfo, |
1081 | .get_link = ethtool_op_get_link, | 1116 | .get_link = ethtool_op_get_link, |
1117 | .set_wol = dmfe_ethtool_set_wol, | ||
1118 | .get_wol = dmfe_ethtool_get_wol, | ||
1082 | }; | 1119 | }; |
1083 | 1120 | ||
1084 | /* | 1121 | /* |
@@ -2052,6 +2089,7 @@ static int dmfe_suspend(struct pci_dev *pci_dev, pm_message_t state) | |||
2052 | { | 2089 | { |
2053 | struct net_device *dev = pci_get_drvdata(pci_dev); | 2090 | struct net_device *dev = pci_get_drvdata(pci_dev); |
2054 | struct dmfe_board_info *db = netdev_priv(dev); | 2091 | struct dmfe_board_info *db = netdev_priv(dev); |
2092 | u32 tmp; | ||
2055 | 2093 | ||
2056 | /* Disable upper layer interface */ | 2094 | /* Disable upper layer interface */ |
2057 | netif_device_detach(dev); | 2095 | netif_device_detach(dev); |
@@ -2067,6 +2105,20 @@ static int dmfe_suspend(struct pci_dev *pci_dev, pm_message_t state) | |||
2067 | /* Fre RX buffers */ | 2105 | /* Fre RX buffers */ |
2068 | dmfe_free_rxbuffer(db); | 2106 | dmfe_free_rxbuffer(db); |
2069 | 2107 | ||
2108 | /* Enable WOL */ | ||
2109 | pci_read_config_dword(pci_dev, 0x40, &tmp); | ||
2110 | tmp &= ~(DMFE_WOL_LINKCHANGE|DMFE_WOL_MAGICPACKET); | ||
2111 | |||
2112 | if (db->wol_mode & WAKE_PHY) | ||
2113 | tmp |= DMFE_WOL_LINKCHANGE; | ||
2114 | if (db->wol_mode & WAKE_MAGIC) | ||
2115 | tmp |= DMFE_WOL_MAGICPACKET; | ||
2116 | |||
2117 | pci_write_config_dword(pci_dev, 0x40, tmp); | ||
2118 | |||
2119 | pci_enable_wake(pci_dev, PCI_D3hot, 1); | ||
2120 | pci_enable_wake(pci_dev, PCI_D3cold, 1); | ||
2121 | |||
2070 | /* Power down device*/ | 2122 | /* Power down device*/ |
2071 | pci_set_power_state(pci_dev, pci_choose_state (pci_dev,state)); | 2123 | pci_set_power_state(pci_dev, pci_choose_state (pci_dev,state)); |
2072 | pci_save_state(pci_dev); | 2124 | pci_save_state(pci_dev); |
@@ -2077,6 +2129,7 @@ static int dmfe_suspend(struct pci_dev *pci_dev, pm_message_t state) | |||
2077 | static int dmfe_resume(struct pci_dev *pci_dev) | 2129 | static int dmfe_resume(struct pci_dev *pci_dev) |
2078 | { | 2130 | { |
2079 | struct net_device *dev = pci_get_drvdata(pci_dev); | 2131 | struct net_device *dev = pci_get_drvdata(pci_dev); |
2132 | u32 tmp; | ||
2080 | 2133 | ||
2081 | pci_restore_state(pci_dev); | 2134 | pci_restore_state(pci_dev); |
2082 | pci_set_power_state(pci_dev, PCI_D0); | 2135 | pci_set_power_state(pci_dev, PCI_D0); |
@@ -2084,6 +2137,15 @@ static int dmfe_resume(struct pci_dev *pci_dev) | |||
2084 | /* Re-initilize DM910X board */ | 2137 | /* Re-initilize DM910X board */ |
2085 | dmfe_init_dm910x(dev); | 2138 | dmfe_init_dm910x(dev); |
2086 | 2139 | ||
2140 | /* Disable WOL */ | ||
2141 | pci_read_config_dword(pci_dev, 0x40, &tmp); | ||
2142 | |||
2143 | tmp &= ~(DMFE_WOL_LINKCHANGE | DMFE_WOL_MAGICPACKET); | ||
2144 | pci_write_config_dword(pci_dev, 0x40, tmp); | ||
2145 | |||
2146 | pci_enable_wake(pci_dev, PCI_D3hot, 0); | ||
2147 | pci_enable_wake(pci_dev, PCI_D3cold, 0); | ||
2148 | |||
2087 | /* Restart upper layer interface */ | 2149 | /* Restart upper layer interface */ |
2088 | netif_device_attach(dev); | 2150 | netif_device_attach(dev); |
2089 | 2151 | ||