diff options
| author | Robert Foss <robert.foss@collabora.com> | 2016-08-29 09:32:16 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2016-09-01 00:07:05 -0400 |
| commit | 8a46f665833a2085e402bd0827be380f161f09ef (patch) | |
| tree | d15ae39e7a98704fad123b6be04674114fc41592 /drivers/net/usb | |
| parent | d9fe64e511144c1ee7d7555b4111f09dde9692ef (diff) | |
net: asix: Avoid looping when the device is disconnected
From: Vincent Palatin <vpalatin@chromium.org>
Check the answers from the USB stack and avoid re-sending multiple times
the request if the device has disappeared.
Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
Signed-off-by: Robert Foss <robert.foss@collabora.com>
Tested-by: Robert Foss <robert.foss@collabora.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/usb')
| -rw-r--r-- | drivers/net/usb/asix_common.c | 56 | ||||
| -rw-r--r-- | drivers/net/usb/asix_devices.c | 2 |
2 files changed, 46 insertions, 12 deletions
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c index 25609eefc762..f79eb12c326a 100644 --- a/drivers/net/usb/asix_common.c +++ b/drivers/net/usb/asix_common.c | |||
| @@ -428,13 +428,21 @@ int asix_mdio_read(struct net_device *netdev, int phy_id, int loc) | |||
| 428 | __le16 res; | 428 | __le16 res; |
| 429 | u8 smsr; | 429 | u8 smsr; |
| 430 | int i = 0; | 430 | int i = 0; |
| 431 | int ret; | ||
| 431 | 432 | ||
| 432 | mutex_lock(&dev->phy_mutex); | 433 | mutex_lock(&dev->phy_mutex); |
| 433 | do { | 434 | do { |
| 434 | asix_set_sw_mii(dev, 0); | 435 | ret = asix_set_sw_mii(dev, 0); |
| 436 | if (ret == -ENODEV) | ||
| 437 | break; | ||
| 435 | usleep_range(1000, 1100); | 438 | usleep_range(1000, 1100); |
| 436 | asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &smsr, 0); | 439 | ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, |
| 437 | } while (!(smsr & AX_HOST_EN) && (i++ < 30)); | 440 | 0, 0, 1, &smsr, 0); |
| 441 | } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV)); | ||
| 442 | if (ret == -ENODEV) { | ||
| 443 | mutex_unlock(&dev->phy_mutex); | ||
| 444 | return ret; | ||
| 445 | } | ||
| 438 | 446 | ||
| 439 | asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, | 447 | asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, |
| 440 | (__u16)loc, 2, &res, 0); | 448 | (__u16)loc, 2, &res, 0); |
| @@ -453,16 +461,24 @@ void asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val) | |||
| 453 | __le16 res = cpu_to_le16(val); | 461 | __le16 res = cpu_to_le16(val); |
| 454 | u8 smsr; | 462 | u8 smsr; |
| 455 | int i = 0; | 463 | int i = 0; |
| 464 | int ret; | ||
| 456 | 465 | ||
| 457 | netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", | 466 | netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", |
| 458 | phy_id, loc, val); | 467 | phy_id, loc, val); |
| 459 | 468 | ||
| 460 | mutex_lock(&dev->phy_mutex); | 469 | mutex_lock(&dev->phy_mutex); |
| 461 | do { | 470 | do { |
| 462 | asix_set_sw_mii(dev, 0); | 471 | ret = asix_set_sw_mii(dev, 0); |
| 472 | if (ret == -ENODEV) | ||
| 473 | break; | ||
| 463 | usleep_range(1000, 1100); | 474 | usleep_range(1000, 1100); |
| 464 | asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &smsr, 0); | 475 | ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, |
| 465 | } while (!(smsr & AX_HOST_EN) && (i++ < 30)); | 476 | 0, 0, 1, &smsr, 0); |
| 477 | } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV)); | ||
| 478 | if (ret == -ENODEV) { | ||
| 479 | mutex_unlock(&dev->phy_mutex); | ||
| 480 | return; | ||
| 481 | } | ||
| 466 | 482 | ||
| 467 | asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, | 483 | asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, |
| 468 | (__u16)loc, 2, &res, 0); | 484 | (__u16)loc, 2, &res, 0); |
| @@ -476,13 +492,21 @@ int asix_mdio_read_nopm(struct net_device *netdev, int phy_id, int loc) | |||
| 476 | __le16 res; | 492 | __le16 res; |
| 477 | u8 smsr; | 493 | u8 smsr; |
| 478 | int i = 0; | 494 | int i = 0; |
| 495 | int ret; | ||
| 479 | 496 | ||
| 480 | mutex_lock(&dev->phy_mutex); | 497 | mutex_lock(&dev->phy_mutex); |
| 481 | do { | 498 | do { |
| 482 | asix_set_sw_mii(dev, 1); | 499 | ret = asix_set_sw_mii(dev, 1); |
| 500 | if (ret == -ENODEV) | ||
| 501 | break; | ||
| 483 | usleep_range(1000, 1100); | 502 | usleep_range(1000, 1100); |
| 484 | asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &smsr, 1); | 503 | ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, |
| 485 | } while (!(smsr & AX_HOST_EN) && (i++ < 30)); | 504 | 0, 0, 1, &smsr, 1); |
| 505 | } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV)); | ||
| 506 | if (ret == -ENODEV) { | ||
| 507 | mutex_unlock(&dev->phy_mutex); | ||
| 508 | return ret; | ||
| 509 | } | ||
| 486 | 510 | ||
| 487 | asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, | 511 | asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, |
| 488 | (__u16)loc, 2, &res, 1); | 512 | (__u16)loc, 2, &res, 1); |
| @@ -502,16 +526,24 @@ asix_mdio_write_nopm(struct net_device *netdev, int phy_id, int loc, int val) | |||
| 502 | __le16 res = cpu_to_le16(val); | 526 | __le16 res = cpu_to_le16(val); |
| 503 | u8 smsr; | 527 | u8 smsr; |
| 504 | int i = 0; | 528 | int i = 0; |
| 529 | int ret; | ||
| 505 | 530 | ||
| 506 | netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", | 531 | netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", |
| 507 | phy_id, loc, val); | 532 | phy_id, loc, val); |
| 508 | 533 | ||
| 509 | mutex_lock(&dev->phy_mutex); | 534 | mutex_lock(&dev->phy_mutex); |
| 510 | do { | 535 | do { |
| 511 | asix_set_sw_mii(dev, 1); | 536 | ret = asix_set_sw_mii(dev, 1); |
| 537 | if (ret == -ENODEV) | ||
| 538 | break; | ||
| 512 | usleep_range(1000, 1100); | 539 | usleep_range(1000, 1100); |
| 513 | asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &smsr, 1); | 540 | ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, |
| 514 | } while (!(smsr & AX_HOST_EN) && (i++ < 30)); | 541 | 0, 0, 1, &smsr, 1); |
| 542 | } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV)); | ||
| 543 | if (ret == -ENODEV) { | ||
| 544 | mutex_unlock(&dev->phy_mutex); | ||
| 545 | return; | ||
| 546 | } | ||
| 515 | 547 | ||
| 516 | asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, | 548 | asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, |
| 517 | (__u16)loc, 2, &res, 1); | 549 | (__u16)loc, 2, &res, 1); |
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index aaa42909d932..ebeb73014fdf 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c | |||
| @@ -79,6 +79,8 @@ static u32 asix_get_phyid(struct usbnet *dev) | |||
| 79 | /* Poll for the rare case the FW or phy isn't ready yet. */ | 79 | /* Poll for the rare case the FW or phy isn't ready yet. */ |
| 80 | for (i = 0; i < 100; i++) { | 80 | for (i = 0; i < 100; i++) { |
| 81 | phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1); | 81 | phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1); |
| 82 | if (phy_reg < 0) | ||
| 83 | return 0; | ||
| 82 | if (phy_reg != 0 && phy_reg != 0xFFFF) | 84 | if (phy_reg != 0 && phy_reg != 0xFFFF) |
| 83 | break; | 85 | break; |
| 84 | mdelay(1); | 86 | mdelay(1); |
