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 | ||
