diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2007-08-14 14:09:02 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:50:41 -0400 |
commit | b6aec32a7774a398c4a194ad6b6392528b5a7a5b (patch) | |
tree | e15b32f78b4a585697c5e017bf1044956967c2e4 /drivers/net | |
parent | 917270c6ed7a99d4300ce57508246813ea8613b0 (diff) |
uli526x: Add suspend and resume routines (updated)
Add suspend/resume support to the uli526x network driver (tested on x86_64,
with 'Ethernet controller: ALi Corporation M5263 Ethernet Controller, rev 40').
This patch is based on the suspend/resume code in the tg3 driver.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/tulip/uli526x.c | 108 |
1 files changed, 102 insertions, 6 deletions
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index ca2548eb7d63..e26ce44561c4 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c | |||
@@ -1110,19 +1110,15 @@ static void uli526x_timer(unsigned long data) | |||
1110 | 1110 | ||
1111 | 1111 | ||
1112 | /* | 1112 | /* |
1113 | * Dynamic reset the ULI526X board | ||
1114 | * Stop ULI526X board | 1113 | * Stop ULI526X board |
1115 | * Free Tx/Rx allocated memory | 1114 | * Free Tx/Rx allocated memory |
1116 | * Reset ULI526X board | 1115 | * Init system variable |
1117 | * Re-initialize ULI526X board | ||
1118 | */ | 1116 | */ |
1119 | 1117 | ||
1120 | static void uli526x_dynamic_reset(struct net_device *dev) | 1118 | static void uli526x_reset_prepare(struct net_device *dev) |
1121 | { | 1119 | { |
1122 | struct uli526x_board_info *db = netdev_priv(dev); | 1120 | struct uli526x_board_info *db = netdev_priv(dev); |
1123 | 1121 | ||
1124 | ULI526X_DBUG(0, "uli526x_dynamic_reset()", 0); | ||
1125 | |||
1126 | /* Sopt MAC controller */ | 1122 | /* Sopt MAC controller */ |
1127 | db->cr6_data &= ~(CR6_RXSC | CR6_TXSC); /* Disable Tx/Rx */ | 1123 | db->cr6_data &= ~(CR6_RXSC | CR6_TXSC); /* Disable Tx/Rx */ |
1128 | update_cr6(db->cr6_data, dev->base_addr); | 1124 | update_cr6(db->cr6_data, dev->base_addr); |
@@ -1141,6 +1137,22 @@ static void uli526x_dynamic_reset(struct net_device *dev) | |||
1141 | db->link_failed = 1; | 1137 | db->link_failed = 1; |
1142 | db->init=1; | 1138 | db->init=1; |
1143 | db->wait_reset = 0; | 1139 | db->wait_reset = 0; |
1140 | } | ||
1141 | |||
1142 | |||
1143 | /* | ||
1144 | * Dynamic reset the ULI526X board | ||
1145 | * Stop ULI526X board | ||
1146 | * Free Tx/Rx allocated memory | ||
1147 | * Reset ULI526X board | ||
1148 | * Re-initialize ULI526X board | ||
1149 | */ | ||
1150 | |||
1151 | static void uli526x_dynamic_reset(struct net_device *dev) | ||
1152 | { | ||
1153 | ULI526X_DBUG(0, "uli526x_dynamic_reset()", 0); | ||
1154 | |||
1155 | uli526x_reset_prepare(dev); | ||
1144 | 1156 | ||
1145 | /* Re-initialize ULI526X board */ | 1157 | /* Re-initialize ULI526X board */ |
1146 | uli526x_init(dev); | 1158 | uli526x_init(dev); |
@@ -1150,6 +1162,88 @@ static void uli526x_dynamic_reset(struct net_device *dev) | |||
1150 | } | 1162 | } |
1151 | 1163 | ||
1152 | 1164 | ||
1165 | #ifdef CONFIG_PM | ||
1166 | |||
1167 | /* | ||
1168 | * Suspend the interface. | ||
1169 | */ | ||
1170 | |||
1171 | static int uli526x_suspend(struct pci_dev *pdev, pm_message_t state) | ||
1172 | { | ||
1173 | struct net_device *dev = pci_get_drvdata(pdev); | ||
1174 | pci_power_t power_state; | ||
1175 | int err; | ||
1176 | |||
1177 | ULI526X_DBUG(0, "uli526x_suspend", 0); | ||
1178 | |||
1179 | if (!netdev_priv(dev)) | ||
1180 | return 0; | ||
1181 | |||
1182 | pci_save_state(pdev); | ||
1183 | |||
1184 | if (!netif_running(dev)) | ||
1185 | return 0; | ||
1186 | |||
1187 | netif_device_detach(dev); | ||
1188 | uli526x_reset_prepare(dev); | ||
1189 | |||
1190 | power_state = pci_choose_state(pdev, state); | ||
1191 | pci_enable_wake(pdev, power_state, 0); | ||
1192 | err = pci_set_power_state(pdev, power_state); | ||
1193 | if (err) { | ||
1194 | netif_device_attach(dev); | ||
1195 | /* Re-initialize ULI526X board */ | ||
1196 | uli526x_init(dev); | ||
1197 | /* Restart upper layer interface */ | ||
1198 | netif_wake_queue(dev); | ||
1199 | } | ||
1200 | |||
1201 | return err; | ||
1202 | } | ||
1203 | |||
1204 | /* | ||
1205 | * Resume the interface. | ||
1206 | */ | ||
1207 | |||
1208 | static int uli526x_resume(struct pci_dev *pdev) | ||
1209 | { | ||
1210 | struct net_device *dev = pci_get_drvdata(pdev); | ||
1211 | int err; | ||
1212 | |||
1213 | ULI526X_DBUG(0, "uli526x_resume", 0); | ||
1214 | |||
1215 | if (!netdev_priv(dev)) | ||
1216 | return 0; | ||
1217 | |||
1218 | pci_restore_state(pdev); | ||
1219 | |||
1220 | if (!netif_running(dev)) | ||
1221 | return 0; | ||
1222 | |||
1223 | err = pci_set_power_state(pdev, PCI_D0); | ||
1224 | if (err) { | ||
1225 | printk(KERN_WARNING "%s: Could not put device into D0\n", | ||
1226 | dev->name); | ||
1227 | return err; | ||
1228 | } | ||
1229 | |||
1230 | netif_device_attach(dev); | ||
1231 | /* Re-initialize ULI526X board */ | ||
1232 | uli526x_init(dev); | ||
1233 | /* Restart upper layer interface */ | ||
1234 | netif_wake_queue(dev); | ||
1235 | |||
1236 | return 0; | ||
1237 | } | ||
1238 | |||
1239 | #else /* !CONFIG_PM */ | ||
1240 | |||
1241 | #define uli526x_suspend NULL | ||
1242 | #define uli526x_resume NULL | ||
1243 | |||
1244 | #endif /* !CONFIG_PM */ | ||
1245 | |||
1246 | |||
1153 | /* | 1247 | /* |
1154 | * free all allocated rx buffer | 1248 | * free all allocated rx buffer |
1155 | */ | 1249 | */ |
@@ -1689,6 +1783,8 @@ static struct pci_driver uli526x_driver = { | |||
1689 | .id_table = uli526x_pci_tbl, | 1783 | .id_table = uli526x_pci_tbl, |
1690 | .probe = uli526x_init_one, | 1784 | .probe = uli526x_init_one, |
1691 | .remove = __devexit_p(uli526x_remove_one), | 1785 | .remove = __devexit_p(uli526x_remove_one), |
1786 | .suspend = uli526x_suspend, | ||
1787 | .resume = uli526x_resume, | ||
1692 | }; | 1788 | }; |
1693 | 1789 | ||
1694 | MODULE_AUTHOR("Peer Chen, peer.chen@uli.com.tw"); | 1790 | MODULE_AUTHOR("Peer Chen, peer.chen@uli.com.tw"); |