aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorSteve Glendinning <steve.glendinning@shawell.net>2012-11-28 00:59:48 -0500
committerDavid S. Miller <davem@davemloft.net>2012-11-28 11:17:31 -0500
commiteacdd6c223d699938c56e7c991877433454d3ebc (patch)
tree8eef1e0f1350201d496b0761632a831ee1204c07 /drivers/net
parentf329ccdc6cd9ef866045af7ccc5fa7d2a9a1f6bb (diff)
smsc75xx: fix error handling in suspend failure case
This patch ensures that if we fail to suspend the LAN7500 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')
-rw-r--r--drivers/net/usb/smsc75xx.c69
1 files changed, 38 insertions, 31 deletions
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 3e3b1014141..649bf2a4262 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -1346,7 +1346,7 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
1346 int ret; 1346 int ret;
1347 1347
1348 ret = usbnet_suspend(intf, message); 1348 ret = usbnet_suspend(intf, message);
1349 check_warn_return(ret, "usbnet_suspend error\n"); 1349 check_warn_goto_done(ret, "usbnet_suspend error\n");
1350 1350
1351 /* determine if link is up using only _nopm functions */ 1351 /* determine if link is up using only _nopm functions */
1352 link_up = smsc75xx_link_ok_nopm(dev); 1352 link_up = smsc75xx_link_ok_nopm(dev);
@@ -1360,28 +1360,29 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
1360 1360
1361 /* disable energy detect (link up) & wake up events */ 1361 /* disable energy detect (link up) & wake up events */
1362 ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val); 1362 ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
1363 check_warn_return(ret, "Error reading WUCSR\n"); 1363 check_warn_goto_done(ret, "Error reading WUCSR\n");
1364 1364
1365 val &= ~(WUCSR_MPEN | WUCSR_WUEN); 1365 val &= ~(WUCSR_MPEN | WUCSR_WUEN);
1366 1366
1367 ret = smsc75xx_write_reg_nopm(dev, WUCSR, val); 1367 ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
1368 check_warn_return(ret, "Error writing WUCSR\n"); 1368 check_warn_goto_done(ret, "Error writing WUCSR\n");
1369 1369
1370 ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val); 1370 ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
1371 check_warn_return(ret, "Error reading PMT_CTL\n"); 1371 check_warn_goto_done(ret, "Error reading PMT_CTL\n");
1372 1372
1373 val &= ~(PMT_CTL_ED_EN | PMT_CTL_WOL_EN); 1373 val &= ~(PMT_CTL_ED_EN | PMT_CTL_WOL_EN);
1374 1374
1375 ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val); 1375 ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
1376 check_warn_return(ret, "Error writing PMT_CTL\n"); 1376 check_warn_goto_done(ret, "Error writing PMT_CTL\n");
1377 1377
1378 return smsc75xx_enter_suspend2(dev); 1378 ret = smsc75xx_enter_suspend2(dev);
1379 goto done;
1379 } 1380 }
1380 1381
1381 if (pdata->wolopts & WAKE_PHY) { 1382 if (pdata->wolopts & WAKE_PHY) {
1382 ret = smsc75xx_enable_phy_wakeup_interrupts(dev, 1383 ret = smsc75xx_enable_phy_wakeup_interrupts(dev,
1383 (PHY_INT_MASK_ANEG_COMP | PHY_INT_MASK_LINK_DOWN)); 1384 (PHY_INT_MASK_ANEG_COMP | PHY_INT_MASK_LINK_DOWN));
1384 check_warn_return(ret, "error enabling PHY wakeup ints\n"); 1385 check_warn_goto_done(ret, "error enabling PHY wakeup ints\n");
1385 1386
1386 /* if link is down then configure EDPD and enter SUSPEND1, 1387 /* if link is down then configure EDPD and enter SUSPEND1,
1387 * otherwise enter SUSPEND0 below 1388 * otherwise enter SUSPEND0 below
@@ -1393,7 +1394,7 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
1393 /* enable energy detect power-down mode */ 1394 /* enable energy detect power-down mode */
1394 ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, 1395 ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id,
1395 PHY_MODE_CTRL_STS); 1396 PHY_MODE_CTRL_STS);
1396 check_warn_return(ret, "Error reading PHY_MODE_CTRL_STS\n"); 1397 check_warn_goto_done(ret, "Error reading PHY_MODE_CTRL_STS\n");
1397 1398
1398 ret |= MODE_CTRL_STS_EDPWRDOWN; 1399 ret |= MODE_CTRL_STS_EDPWRDOWN;
1399 1400
@@ -1401,7 +1402,8 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
1401 PHY_MODE_CTRL_STS, ret); 1402 PHY_MODE_CTRL_STS, ret);
1402 1403
1403 /* enter SUSPEND1 mode */ 1404 /* enter SUSPEND1 mode */
1404 return smsc75xx_enter_suspend1(dev); 1405 ret = smsc75xx_enter_suspend1(dev);
1406 goto done;
1405 } 1407 }
1406 } 1408 }
1407 1409
@@ -1411,7 +1413,7 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
1411 /* disable all filters */ 1413 /* disable all filters */
1412 for (i = 0; i < WUF_NUM; i++) { 1414 for (i = 0; i < WUF_NUM; i++) {
1413 ret = smsc75xx_write_reg_nopm(dev, WUF_CFGX + i * 4, 0); 1415 ret = smsc75xx_write_reg_nopm(dev, WUF_CFGX + i * 4, 0);
1414 check_warn_return(ret, "Error writing WUF_CFGX\n"); 1416 check_warn_goto_done(ret, "Error writing WUF_CFGX\n");
1415 } 1417 }
1416 1418
1417 if (pdata->wolopts & WAKE_MCAST) { 1419 if (pdata->wolopts & WAKE_MCAST) {
@@ -1421,7 +1423,7 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
1421 val = WUF_CFGX_EN | WUF_CFGX_ATYPE_MULTICAST 1423 val = WUF_CFGX_EN | WUF_CFGX_ATYPE_MULTICAST
1422 | smsc_crc(mcast, 3); 1424 | smsc_crc(mcast, 3);
1423 ret = smsc75xx_write_wuff(dev, filter++, val, 0x0007); 1425 ret = smsc75xx_write_wuff(dev, filter++, val, 0x0007);
1424 check_warn_return(ret, "Error writing wakeup filter\n"); 1426 check_warn_goto_done(ret, "Error writing wakeup filter\n");
1425 } 1427 }
1426 1428
1427 if (pdata->wolopts & WAKE_ARP) { 1429 if (pdata->wolopts & WAKE_ARP) {
@@ -1431,106 +1433,111 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
1431 val = WUF_CFGX_EN | WUF_CFGX_ATYPE_ALL | (0x0C << 16) 1433 val = WUF_CFGX_EN | WUF_CFGX_ATYPE_ALL | (0x0C << 16)
1432 | smsc_crc(arp, 2); 1434 | smsc_crc(arp, 2);
1433 ret = smsc75xx_write_wuff(dev, filter++, val, 0x0003); 1435 ret = smsc75xx_write_wuff(dev, filter++, val, 0x0003);
1434 check_warn_return(ret, "Error writing wakeup filter\n"); 1436 check_warn_goto_done(ret, "Error writing wakeup filter\n");
1435 } 1437 }
1436 1438
1437 /* clear any pending pattern match packet status */ 1439 /* clear any pending pattern match packet status */
1438 ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val); 1440 ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
1439 check_warn_return(ret, "Error reading WUCSR\n"); 1441 check_warn_goto_done(ret, "Error reading WUCSR\n");
1440 1442
1441 val |= WUCSR_WUFR; 1443 val |= WUCSR_WUFR;
1442 1444
1443 ret = smsc75xx_write_reg_nopm(dev, WUCSR, val); 1445 ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
1444 check_warn_return(ret, "Error writing WUCSR\n"); 1446 check_warn_goto_done(ret, "Error writing WUCSR\n");
1445 1447
1446 netdev_info(dev->net, "enabling packet match detection\n"); 1448 netdev_info(dev->net, "enabling packet match detection\n");
1447 ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val); 1449 ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
1448 check_warn_return(ret, "Error reading WUCSR\n"); 1450 check_warn_goto_done(ret, "Error reading WUCSR\n");
1449 1451
1450 val |= WUCSR_WUEN; 1452 val |= WUCSR_WUEN;
1451 1453
1452 ret = smsc75xx_write_reg_nopm(dev, WUCSR, val); 1454 ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
1453 check_warn_return(ret, "Error writing WUCSR\n"); 1455 check_warn_goto_done(ret, "Error writing WUCSR\n");
1454 } else { 1456 } else {
1455 netdev_info(dev->net, "disabling packet match detection\n"); 1457 netdev_info(dev->net, "disabling packet match detection\n");
1456 ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val); 1458 ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
1457 check_warn_return(ret, "Error reading WUCSR\n"); 1459 check_warn_goto_done(ret, "Error reading WUCSR\n");
1458 1460
1459 val &= ~WUCSR_WUEN; 1461 val &= ~WUCSR_WUEN;
1460 1462
1461 ret = smsc75xx_write_reg_nopm(dev, WUCSR, val); 1463 ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
1462 check_warn_return(ret, "Error writing WUCSR\n"); 1464 check_warn_goto_done(ret, "Error writing WUCSR\n");
1463 } 1465 }
1464 1466
1465 /* disable magic, bcast & unicast wakeup sources */ 1467 /* disable magic, bcast & unicast wakeup sources */
1466 ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val); 1468 ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
1467 check_warn_return(ret, "Error reading WUCSR\n"); 1469 check_warn_goto_done(ret, "Error reading WUCSR\n");
1468 1470
1469 val &= ~(WUCSR_MPEN | WUCSR_BCST_EN | WUCSR_PFDA_EN); 1471 val &= ~(WUCSR_MPEN | WUCSR_BCST_EN | WUCSR_PFDA_EN);
1470 1472
1471 ret = smsc75xx_write_reg_nopm(dev, WUCSR, val); 1473 ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
1472 check_warn_return(ret, "Error writing WUCSR\n"); 1474 check_warn_goto_done(ret, "Error writing WUCSR\n");
1473 1475
1474 if (pdata->wolopts & WAKE_PHY) { 1476 if (pdata->wolopts & WAKE_PHY) {
1475 netdev_info(dev->net, "enabling PHY wakeup\n"); 1477 netdev_info(dev->net, "enabling PHY wakeup\n");
1476 1478
1477 ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val); 1479 ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
1478 check_warn_return(ret, "Error reading PMT_CTL\n"); 1480 check_warn_goto_done(ret, "Error reading PMT_CTL\n");
1479 1481
1480 /* clear wol status, enable energy detection */ 1482 /* clear wol status, enable energy detection */
1481 val &= ~PMT_CTL_WUPS; 1483 val &= ~PMT_CTL_WUPS;
1482 val |= (PMT_CTL_WUPS_ED | PMT_CTL_ED_EN); 1484 val |= (PMT_CTL_WUPS_ED | PMT_CTL_ED_EN);
1483 1485
1484 ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val); 1486 ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
1485 check_warn_return(ret, "Error writing PMT_CTL\n"); 1487 check_warn_goto_done(ret, "Error writing PMT_CTL\n");
1486 } 1488 }
1487 1489
1488 if (pdata->wolopts & WAKE_MAGIC) { 1490 if (pdata->wolopts & WAKE_MAGIC) {
1489 netdev_info(dev->net, "enabling magic packet wakeup\n"); 1491 netdev_info(dev->net, "enabling magic packet wakeup\n");
1490 ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val); 1492 ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
1491 check_warn_return(ret, "Error reading WUCSR\n"); 1493 check_warn_goto_done(ret, "Error reading WUCSR\n");
1492 1494
1493 /* clear any pending magic packet status */ 1495 /* clear any pending magic packet status */
1494 val |= WUCSR_MPR | WUCSR_MPEN; 1496 val |= WUCSR_MPR | WUCSR_MPEN;
1495 1497
1496 ret = smsc75xx_write_reg_nopm(dev, WUCSR, val); 1498 ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
1497 check_warn_return(ret, "Error writing WUCSR\n"); 1499 check_warn_goto_done(ret, "Error writing WUCSR\n");
1498 } 1500 }
1499 1501
1500 if (pdata->wolopts & WAKE_BCAST) { 1502 if (pdata->wolopts & WAKE_BCAST) {
1501 netdev_info(dev->net, "enabling broadcast detection\n"); 1503 netdev_info(dev->net, "enabling broadcast detection\n");
1502 ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val); 1504 ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
1503 check_warn_return(ret, "Error reading WUCSR\n"); 1505 check_warn_goto_done(ret, "Error reading WUCSR\n");
1504 1506
1505 val |= WUCSR_BCAST_FR | WUCSR_BCST_EN; 1507 val |= WUCSR_BCAST_FR | WUCSR_BCST_EN;
1506 1508
1507 ret = smsc75xx_write_reg_nopm(dev, WUCSR, val); 1509 ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
1508 check_warn_return(ret, "Error writing WUCSR\n"); 1510 check_warn_goto_done(ret, "Error writing WUCSR\n");
1509 } 1511 }
1510 1512
1511 if (pdata->wolopts & WAKE_UCAST) { 1513 if (pdata->wolopts & WAKE_UCAST) {
1512 netdev_info(dev->net, "enabling unicast detection\n"); 1514 netdev_info(dev->net, "enabling unicast detection\n");
1513 ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val); 1515 ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
1514 check_warn_return(ret, "Error reading WUCSR\n"); 1516 check_warn_goto_done(ret, "Error reading WUCSR\n");
1515 1517
1516 val |= WUCSR_WUFR | WUCSR_PFDA_EN; 1518 val |= WUCSR_WUFR | WUCSR_PFDA_EN;
1517 1519
1518 ret = smsc75xx_write_reg_nopm(dev, WUCSR, val); 1520 ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
1519 check_warn_return(ret, "Error writing WUCSR\n"); 1521 check_warn_goto_done(ret, "Error writing WUCSR\n");
1520 } 1522 }
1521 1523
1522 /* enable receiver to enable frame reception */ 1524 /* enable receiver to enable frame reception */
1523 ret = smsc75xx_read_reg_nopm(dev, MAC_RX, &val); 1525 ret = smsc75xx_read_reg_nopm(dev, MAC_RX, &val);
1524 check_warn_return(ret, "Failed to read MAC_RX: %d\n", ret); 1526 check_warn_goto_done(ret, "Failed to read MAC_RX: %d\n", ret);
1525 1527
1526 val |= MAC_RX_RXEN; 1528 val |= MAC_RX_RXEN;
1527 1529
1528 ret = smsc75xx_write_reg_nopm(dev, MAC_RX, val); 1530 ret = smsc75xx_write_reg_nopm(dev, MAC_RX, val);
1529 check_warn_return(ret, "Failed to write MAC_RX: %d\n", ret); 1531 check_warn_goto_done(ret, "Failed to write MAC_RX: %d\n", ret);
1530 1532
1531 /* some wol options are enabled, so enter SUSPEND0 */ 1533 /* some wol options are enabled, so enter SUSPEND0 */
1532 netdev_info(dev->net, "entering SUSPEND0 mode\n"); 1534 netdev_info(dev->net, "entering SUSPEND0 mode\n");
1533 return smsc75xx_enter_suspend0(dev); 1535 ret = smsc75xx_enter_suspend0(dev);
1536
1537done:
1538 if (ret)
1539 usbnet_resume(intf);
1540 return ret;
1534} 1541}
1535 1542
1536static int smsc75xx_resume(struct usb_interface *intf) 1543static int smsc75xx_resume(struct usb_interface *intf)