aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/smsc75xx.c
diff options
context:
space:
mode:
authorSteve Glendinning <steve.glendinning@shawell.net>2012-09-27 20:57:52 -0400
committerDavid S. Miller <davem@davemloft.net>2012-09-28 18:35:47 -0400
commit16c79a04e262e51c790af4b074963dd592c617f2 (patch)
treee137efbead23c429a6f9d7db220e502272345c8e /drivers/net/usb/smsc75xx.c
parent8762cec8d9d06eddc9a80293a230d6e073568815 (diff)
smsc75xx: enable power saving mode during system suspend
This patch instructs the device to enter its lowest power SUSPEND2 state during system suspend. This patch also explicitly wakes the device after resume, which should address reports of the device not automatically coming back after system suspend: Patch updated to change BUG_ON to WARN_ON_ONCE. http://code.google.com/p/chromium-os/issues/detail?id=31871 Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/usb/smsc75xx.c')
-rw-r--r--drivers/net/usb/smsc75xx.c57
1 files changed, 54 insertions, 3 deletions
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 1f45f7b2fe63..759e577008b0 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -1106,6 +1106,57 @@ static void smsc75xx_unbind(struct usbnet *dev, struct usb_interface *intf)
1106 } 1106 }
1107} 1107}
1108 1108
1109static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
1110{
1111 struct usbnet *dev = usb_get_intfdata(intf);
1112 int ret;
1113 u32 val;
1114
1115 if (WARN_ON_ONCE(!dev))
1116 return -EINVAL;
1117
1118 ret = usbnet_suspend(intf, message);
1119 check_warn_return(ret, "usbnet_suspend error");
1120
1121 netdev_info(dev->net, "entering SUSPEND2 mode");
1122
1123 ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
1124 check_warn_return(ret, "Error reading PMT_CTL");
1125
1126 val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
1127 val |= PMT_CTL_SUS_MODE_2;
1128
1129 ret = smsc75xx_write_reg(dev, PMT_CTL, val);
1130 check_warn_return(ret, "Error writing PMT_CTL");
1131
1132 return 0;
1133}
1134
1135static int smsc75xx_resume(struct usb_interface *intf)
1136{
1137 struct usbnet *dev = usb_get_intfdata(intf);
1138 int ret;
1139 u32 val;
1140
1141 if (WARN_ON_ONCE(!dev))
1142 return -EINVAL;
1143
1144 netdev_info(dev->net, "resuming from SUSPEND2");
1145
1146 ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
1147 check_warn_return(ret, "Error reading PMT_CTL");
1148
1149 val |= PMT_CTL_PHY_PWRUP;
1150
1151 ret = smsc75xx_write_reg(dev, PMT_CTL, val);
1152 check_warn_return(ret, "Error writing PMT_CTL");
1153
1154 ret = smsc75xx_wait_ready(dev);
1155 check_warn_return(ret, "device not ready in smsc75xx_resume");
1156
1157 return usbnet_resume(intf);
1158}
1159
1109static void smsc75xx_rx_csum_offload(struct usbnet *dev, struct sk_buff *skb, 1160static void smsc75xx_rx_csum_offload(struct usbnet *dev, struct sk_buff *skb,
1110 u32 rx_cmd_a, u32 rx_cmd_b) 1161 u32 rx_cmd_a, u32 rx_cmd_b)
1111{ 1162{
@@ -1274,9 +1325,9 @@ static struct usb_driver smsc75xx_driver = {
1274 .name = SMSC_CHIPNAME, 1325 .name = SMSC_CHIPNAME,
1275 .id_table = products, 1326 .id_table = products,
1276 .probe = usbnet_probe, 1327 .probe = usbnet_probe,
1277 .suspend = usbnet_suspend, 1328 .suspend = smsc75xx_suspend,
1278 .resume = usbnet_resume, 1329 .resume = smsc75xx_resume,
1279 .reset_resume = usbnet_resume, 1330 .reset_resume = smsc75xx_resume,
1280 .disconnect = usbnet_disconnect, 1331 .disconnect = usbnet_disconnect,
1281 .disable_hub_initiated_lpm = 1, 1332 .disable_hub_initiated_lpm = 1,
1282}; 1333};