diff options
-rw-r--r-- | drivers/net/wimax/i2400m/usb.c | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index ca4151a9e222..17851321b7fd 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c | |||
@@ -505,27 +505,52 @@ int i2400mu_suspend(struct usb_interface *iface, pm_message_t pm_msg) | |||
505 | #ifdef CONFIG_PM | 505 | #ifdef CONFIG_PM |
506 | struct usb_device *usb_dev = i2400mu->usb_dev; | 506 | struct usb_device *usb_dev = i2400mu->usb_dev; |
507 | #endif | 507 | #endif |
508 | unsigned is_autosuspend = 0; | ||
508 | struct i2400m *i2400m = &i2400mu->i2400m; | 509 | struct i2400m *i2400m = &i2400mu->i2400m; |
509 | 510 | ||
511 | #ifdef CONFIG_PM | ||
512 | if (usb_dev->auto_pm > 0) | ||
513 | is_autosuspend = 1; | ||
514 | #endif | ||
515 | |||
510 | d_fnstart(3, dev, "(iface %p pm_msg %u)\n", iface, pm_msg.event); | 516 | d_fnstart(3, dev, "(iface %p pm_msg %u)\n", iface, pm_msg.event); |
511 | if (i2400m->updown == 0) | 517 | if (i2400m->updown == 0) |
512 | goto no_firmware; | 518 | goto no_firmware; |
513 | d_printf(1, dev, "fw up, requesting standby\n"); | 519 | if (i2400m->state == I2400M_SS_DATA_PATH_CONNECTED && is_autosuspend) { |
520 | /* ugh -- the device is connected and this suspend | ||
521 | * request is an autosuspend one (not a system standby | ||
522 | * / hibernate). | ||
523 | * | ||
524 | * The only way the device can go to standby is if the | ||
525 | * link with the base station is in IDLE mode; that | ||
526 | * were the case, we'd be in status | ||
527 | * I2400M_SS_CONNECTED_IDLE. But we are not. | ||
528 | * | ||
529 | * If we *tell* him to go power save now, it'll reset | ||
530 | * as a precautionary measure, so if this is an | ||
531 | * autosuspend thing, say no and it'll come back | ||
532 | * later, when the link is IDLE | ||
533 | */ | ||
534 | result = -EBADF; | ||
535 | d_printf(1, dev, "fw up, link up, not-idle, autosuspend: " | ||
536 | "not entering powersave\n"); | ||
537 | goto error_not_now; | ||
538 | } | ||
539 | d_printf(1, dev, "fw up: entering powersave\n"); | ||
514 | atomic_dec(&i2400mu->do_autopm); | 540 | atomic_dec(&i2400mu->do_autopm); |
515 | result = i2400m_cmd_enter_powersave(i2400m); | 541 | result = i2400m_cmd_enter_powersave(i2400m); |
516 | atomic_inc(&i2400mu->do_autopm); | 542 | atomic_inc(&i2400mu->do_autopm); |
517 | #ifdef CONFIG_PM | 543 | if (result < 0 && !is_autosuspend) { |
518 | if (result < 0 && usb_dev->auto_pm == 0) { | ||
519 | /* System suspend, can't fail */ | 544 | /* System suspend, can't fail */ |
520 | dev_err(dev, "failed to suspend, will reset on resume\n"); | 545 | dev_err(dev, "failed to suspend, will reset on resume\n"); |
521 | result = 0; | 546 | result = 0; |
522 | } | 547 | } |
523 | #endif | ||
524 | if (result < 0) | 548 | if (result < 0) |
525 | goto error_enter_powersave; | 549 | goto error_enter_powersave; |
526 | i2400mu_notification_release(i2400mu); | 550 | i2400mu_notification_release(i2400mu); |
527 | d_printf(1, dev, "fw up, got standby\n"); | 551 | d_printf(1, dev, "powersave requested\n"); |
528 | error_enter_powersave: | 552 | error_enter_powersave: |
553 | error_not_now: | ||
529 | no_firmware: | 554 | no_firmware: |
530 | d_fnend(3, dev, "(iface %p pm_msg %u) = %d\n", | 555 | d_fnend(3, dev, "(iface %p pm_msg %u) = %d\n", |
531 | iface, pm_msg.event, result); | 556 | iface, pm_msg.event, result); |