aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tulip
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2007-08-14 14:09:02 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:50:41 -0400
commitb6aec32a7774a398c4a194ad6b6392528b5a7a5b (patch)
treee15b32f78b4a585697c5e017bf1044956967c2e4 /drivers/net/tulip
parent917270c6ed7a99d4300ce57508246813ea8613b0 (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/tulip')
-rw-r--r--drivers/net/tulip/uli526x.c108
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
1120static void uli526x_dynamic_reset(struct net_device *dev) 1118static 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
1151static 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
1171static 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
1208static 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
1694MODULE_AUTHOR("Peer Chen, peer.chen@uli.com.tw"); 1790MODULE_AUTHOR("Peer Chen, peer.chen@uli.com.tw");