aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/smsc95xx.c
diff options
context:
space:
mode:
authorSteve Glendinning <steve.glendinning@shawell.net>2012-11-30 00:55:49 -0500
committerDavid S. Miller <davem@davemloft.net>2012-11-30 12:27:20 -0500
commit3b9f7d8cdb6db2b6ba78c149dacec3d72591c544 (patch)
tree8ca72360b184ba56f9d65de6caaef005735eb999 /drivers/net/usb/smsc95xx.c
parenteed9a72914a2b2737a0d91b80579f878999574ef (diff)
smsc95xx: fix error handling in suspend failure case
This patch ensures that if we fail to suspend the LAN9500 device we call usbnet_resume before returning failure, instead of leaving the usbnet driver in an unusable state. Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/usb/smsc95xx.c')
-rw-r--r--drivers/net/usb/smsc95xx.c50
1 files changed, 29 insertions, 21 deletions
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index c397b3a04f10..ffeaf131baa7 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1248,35 +1248,37 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
1248 1248
1249 /* disable energy detect (link up) & wake up events */ 1249 /* disable energy detect (link up) & wake up events */
1250 ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val); 1250 ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
1251 check_warn_return(ret, "Error reading WUCSR\n"); 1251 check_warn_goto_done(ret, "Error reading WUCSR\n");
1252 1252
1253 val &= ~(WUCSR_MPEN_ | WUCSR_WAKE_EN_); 1253 val &= ~(WUCSR_MPEN_ | WUCSR_WAKE_EN_);
1254 1254
1255 ret = smsc95xx_write_reg_nopm(dev, WUCSR, val); 1255 ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
1256 check_warn_return(ret, "Error writing WUCSR\n"); 1256 check_warn_goto_done(ret, "Error writing WUCSR\n");
1257 1257
1258 ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val); 1258 ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
1259 check_warn_return(ret, "Error reading PM_CTRL\n"); 1259 check_warn_goto_done(ret, "Error reading PM_CTRL\n");
1260 1260
1261 val &= ~(PM_CTL_ED_EN_ | PM_CTL_WOL_EN_); 1261 val &= ~(PM_CTL_ED_EN_ | PM_CTL_WOL_EN_);
1262 1262
1263 ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val); 1263 ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
1264 check_warn_return(ret, "Error writing PM_CTRL\n"); 1264 check_warn_goto_done(ret, "Error writing PM_CTRL\n");
1265 1265
1266 return smsc95xx_enter_suspend2(dev); 1266 ret = smsc95xx_enter_suspend2(dev);
1267 goto done;
1267 } 1268 }
1268 1269
1269 if (pdata->wolopts & WAKE_PHY) { 1270 if (pdata->wolopts & WAKE_PHY) {
1270 ret = smsc95xx_enable_phy_wakeup_interrupts(dev, 1271 ret = smsc95xx_enable_phy_wakeup_interrupts(dev,
1271 (PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_LINK_DOWN_)); 1272 (PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_LINK_DOWN_));
1272 check_warn_return(ret, "error enabling PHY wakeup ints\n"); 1273 check_warn_goto_done(ret, "error enabling PHY wakeup ints\n");
1273 1274
1274 /* if link is down then configure EDPD and enter SUSPEND1, 1275 /* if link is down then configure EDPD and enter SUSPEND1,
1275 * otherwise enter SUSPEND0 below 1276 * otherwise enter SUSPEND0 below
1276 */ 1277 */
1277 if (!link_up) { 1278 if (!link_up) {
1278 netdev_info(dev->net, "entering SUSPEND1 mode\n"); 1279 netdev_info(dev->net, "entering SUSPEND1 mode\n");
1279 return smsc95xx_enter_suspend1(dev); 1280 ret = smsc95xx_enter_suspend1(dev);
1281 goto done;
1280 } 1282 }
1281 } 1283 }
1282 1284
@@ -1292,7 +1294,8 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
1292 1294
1293 if (!filter_mask) { 1295 if (!filter_mask) {
1294 netdev_warn(dev->net, "Unable to allocate filter_mask\n"); 1296 netdev_warn(dev->net, "Unable to allocate filter_mask\n");
1295 return -ENOMEM; 1297 ret = -ENOMEM;
1298 goto done;
1296 } 1299 }
1297 1300
1298 memset(command, 0, sizeof(command)); 1301 memset(command, 0, sizeof(command));
@@ -1354,49 +1357,49 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
1354 ret = smsc95xx_write_reg_nopm(dev, WUFF, filter_mask[i]); 1357 ret = smsc95xx_write_reg_nopm(dev, WUFF, filter_mask[i]);
1355 if (ret < 0) 1358 if (ret < 0)
1356 kfree(filter_mask); 1359 kfree(filter_mask);
1357 check_warn_return(ret, "Error writing WUFF\n"); 1360 check_warn_goto_done(ret, "Error writing WUFF\n");
1358 } 1361 }
1359 kfree(filter_mask); 1362 kfree(filter_mask);
1360 1363
1361 for (i = 0; i < (wuff_filter_count / 4); i++) { 1364 for (i = 0; i < (wuff_filter_count / 4); i++) {
1362 ret = smsc95xx_write_reg_nopm(dev, WUFF, command[i]); 1365 ret = smsc95xx_write_reg_nopm(dev, WUFF, command[i]);
1363 check_warn_return(ret, "Error writing WUFF\n"); 1366 check_warn_goto_done(ret, "Error writing WUFF\n");
1364 } 1367 }
1365 1368
1366 for (i = 0; i < (wuff_filter_count / 4); i++) { 1369 for (i = 0; i < (wuff_filter_count / 4); i++) {
1367 ret = smsc95xx_write_reg_nopm(dev, WUFF, offset[i]); 1370 ret = smsc95xx_write_reg_nopm(dev, WUFF, offset[i]);
1368 check_warn_return(ret, "Error writing WUFF\n"); 1371 check_warn_goto_done(ret, "Error writing WUFF\n");
1369 } 1372 }
1370 1373
1371 for (i = 0; i < (wuff_filter_count / 2); i++) { 1374 for (i = 0; i < (wuff_filter_count / 2); i++) {
1372 ret = smsc95xx_write_reg_nopm(dev, WUFF, crc[i]); 1375 ret = smsc95xx_write_reg_nopm(dev, WUFF, crc[i]);
1373 check_warn_return(ret, "Error writing WUFF\n"); 1376 check_warn_goto_done(ret, "Error writing WUFF\n");
1374 } 1377 }
1375 1378
1376 /* clear any pending pattern match packet status */ 1379 /* clear any pending pattern match packet status */
1377 ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val); 1380 ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
1378 check_warn_return(ret, "Error reading WUCSR\n"); 1381 check_warn_goto_done(ret, "Error reading WUCSR\n");
1379 1382
1380 val |= WUCSR_WUFR_; 1383 val |= WUCSR_WUFR_;
1381 1384
1382 ret = smsc95xx_write_reg_nopm(dev, WUCSR, val); 1385 ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
1383 check_warn_return(ret, "Error writing WUCSR\n"); 1386 check_warn_goto_done(ret, "Error writing WUCSR\n");
1384 } 1387 }
1385 1388
1386 if (pdata->wolopts & WAKE_MAGIC) { 1389 if (pdata->wolopts & WAKE_MAGIC) {
1387 /* clear any pending magic packet status */ 1390 /* clear any pending magic packet status */
1388 ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val); 1391 ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
1389 check_warn_return(ret, "Error reading WUCSR\n"); 1392 check_warn_goto_done(ret, "Error reading WUCSR\n");
1390 1393
1391 val |= WUCSR_MPR_; 1394 val |= WUCSR_MPR_;
1392 1395
1393 ret = smsc95xx_write_reg_nopm(dev, WUCSR, val); 1396 ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
1394 check_warn_return(ret, "Error writing WUCSR\n"); 1397 check_warn_goto_done(ret, "Error writing WUCSR\n");
1395 } 1398 }
1396 1399
1397 /* enable/disable wakeup sources */ 1400 /* enable/disable wakeup sources */
1398 ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val); 1401 ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
1399 check_warn_return(ret, "Error reading WUCSR\n"); 1402 check_warn_goto_done(ret, "Error reading WUCSR\n");
1400 1403
1401 if (pdata->wolopts & (WAKE_BCAST | WAKE_MCAST | WAKE_ARP | WAKE_UCAST)) { 1404 if (pdata->wolopts & (WAKE_BCAST | WAKE_MCAST | WAKE_ARP | WAKE_UCAST)) {
1402 netdev_info(dev->net, "enabling pattern match wakeup\n"); 1405 netdev_info(dev->net, "enabling pattern match wakeup\n");
@@ -1415,11 +1418,11 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
1415 } 1418 }
1416 1419
1417 ret = smsc95xx_write_reg_nopm(dev, WUCSR, val); 1420 ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
1418 check_warn_return(ret, "Error writing WUCSR\n"); 1421 check_warn_goto_done(ret, "Error writing WUCSR\n");
1419 1422
1420 /* enable wol wakeup source */ 1423 /* enable wol wakeup source */
1421 ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val); 1424 ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
1422 check_warn_return(ret, "Error reading PM_CTRL\n"); 1425 check_warn_goto_done(ret, "Error reading PM_CTRL\n");
1423 1426
1424 val |= PM_CTL_WOL_EN_; 1427 val |= PM_CTL_WOL_EN_;
1425 1428
@@ -1428,14 +1431,19 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
1428 val |= PM_CTL_ED_EN_; 1431 val |= PM_CTL_ED_EN_;
1429 1432
1430 ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val); 1433 ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
1431 check_warn_return(ret, "Error writing PM_CTRL\n"); 1434 check_warn_goto_done(ret, "Error writing PM_CTRL\n");
1432 1435
1433 /* enable receiver to enable frame reception */ 1436 /* enable receiver to enable frame reception */
1434 smsc95xx_start_rx_path(dev, 1); 1437 smsc95xx_start_rx_path(dev, 1);
1435 1438
1436 /* some wol options are enabled, so enter SUSPEND0 */ 1439 /* some wol options are enabled, so enter SUSPEND0 */
1437 netdev_info(dev->net, "entering SUSPEND0 mode\n"); 1440 netdev_info(dev->net, "entering SUSPEND0 mode\n");
1438 return smsc95xx_enter_suspend0(dev); 1441 ret = smsc95xx_enter_suspend0(dev);
1442
1443done:
1444 if (ret)
1445 usbnet_resume(intf);
1446 return ret;
1439} 1447}
1440 1448
1441static int smsc95xx_resume(struct usb_interface *intf) 1449static int smsc95xx_resume(struct usb_interface *intf)