diff options
Diffstat (limited to 'drivers/mmc/core/core.c')
| -rw-r--r-- | drivers/mmc/core/core.c | 187 |
1 files changed, 15 insertions, 172 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 436409f7f7bd..9b56674ddc2a 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
| @@ -605,105 +605,6 @@ unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz) | |||
| 605 | EXPORT_SYMBOL(mmc_align_data_size); | 605 | EXPORT_SYMBOL(mmc_align_data_size); |
| 606 | 606 | ||
| 607 | /** | 607 | /** |
| 608 | * mmc_host_enable - enable a host. | ||
| 609 | * @host: mmc host to enable | ||
| 610 | * | ||
| 611 | * Hosts that support power saving can use the 'enable' and 'disable' | ||
| 612 | * methods to exit and enter power saving states. For more information | ||
| 613 | * see comments for struct mmc_host_ops. | ||
| 614 | */ | ||
| 615 | int mmc_host_enable(struct mmc_host *host) | ||
| 616 | { | ||
| 617 | if (!(host->caps & MMC_CAP_DISABLE)) | ||
| 618 | return 0; | ||
| 619 | |||
| 620 | if (host->en_dis_recurs) | ||
| 621 | return 0; | ||
| 622 | |||
| 623 | if (host->nesting_cnt++) | ||
| 624 | return 0; | ||
| 625 | |||
| 626 | cancel_delayed_work_sync(&host->disable); | ||
| 627 | |||
| 628 | if (host->enabled) | ||
| 629 | return 0; | ||
| 630 | |||
| 631 | if (host->ops->enable) { | ||
| 632 | int err; | ||
| 633 | |||
| 634 | host->en_dis_recurs = 1; | ||
| 635 | mmc_host_clk_hold(host); | ||
| 636 | err = host->ops->enable(host); | ||
| 637 | mmc_host_clk_release(host); | ||
| 638 | host->en_dis_recurs = 0; | ||
| 639 | |||
| 640 | if (err) { | ||
| 641 | pr_debug("%s: enable error %d\n", | ||
| 642 | mmc_hostname(host), err); | ||
| 643 | return err; | ||
| 644 | } | ||
| 645 | } | ||
| 646 | host->enabled = 1; | ||
| 647 | return 0; | ||
| 648 | } | ||
| 649 | EXPORT_SYMBOL(mmc_host_enable); | ||
| 650 | |||
| 651 | static int mmc_host_do_disable(struct mmc_host *host, int lazy) | ||
| 652 | { | ||
| 653 | if (host->ops->disable) { | ||
| 654 | int err; | ||
| 655 | |||
| 656 | host->en_dis_recurs = 1; | ||
| 657 | mmc_host_clk_hold(host); | ||
| 658 | err = host->ops->disable(host, lazy); | ||
| 659 | mmc_host_clk_release(host); | ||
| 660 | host->en_dis_recurs = 0; | ||
| 661 | |||
| 662 | if (err < 0) { | ||
| 663 | pr_debug("%s: disable error %d\n", | ||
| 664 | mmc_hostname(host), err); | ||
| 665 | return err; | ||
| 666 | } | ||
| 667 | if (err > 0) { | ||
| 668 | unsigned long delay = msecs_to_jiffies(err); | ||
| 669 | |||
| 670 | mmc_schedule_delayed_work(&host->disable, delay); | ||
| 671 | } | ||
| 672 | } | ||
| 673 | host->enabled = 0; | ||
| 674 | return 0; | ||
| 675 | } | ||
| 676 | |||
| 677 | /** | ||
| 678 | * mmc_host_disable - disable a host. | ||
| 679 | * @host: mmc host to disable | ||
| 680 | * | ||
| 681 | * Hosts that support power saving can use the 'enable' and 'disable' | ||
| 682 | * methods to exit and enter power saving states. For more information | ||
| 683 | * see comments for struct mmc_host_ops. | ||
| 684 | */ | ||
| 685 | int mmc_host_disable(struct mmc_host *host) | ||
| 686 | { | ||
| 687 | int err; | ||
| 688 | |||
| 689 | if (!(host->caps & MMC_CAP_DISABLE)) | ||
| 690 | return 0; | ||
| 691 | |||
| 692 | if (host->en_dis_recurs) | ||
| 693 | return 0; | ||
| 694 | |||
| 695 | if (--host->nesting_cnt) | ||
| 696 | return 0; | ||
| 697 | |||
| 698 | if (!host->enabled) | ||
| 699 | return 0; | ||
| 700 | |||
| 701 | err = mmc_host_do_disable(host, 0); | ||
| 702 | return err; | ||
| 703 | } | ||
| 704 | EXPORT_SYMBOL(mmc_host_disable); | ||
| 705 | |||
| 706 | /** | ||
| 707 | * __mmc_claim_host - exclusively claim a host | 608 | * __mmc_claim_host - exclusively claim a host |
| 708 | * @host: mmc host to claim | 609 | * @host: mmc host to claim |
| 709 | * @abort: whether or not the operation should be aborted | 610 | * @abort: whether or not the operation should be aborted |
| @@ -741,8 +642,8 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort) | |||
| 741 | wake_up(&host->wq); | 642 | wake_up(&host->wq); |
| 742 | spin_unlock_irqrestore(&host->lock, flags); | 643 | spin_unlock_irqrestore(&host->lock, flags); |
| 743 | remove_wait_queue(&host->wq, &wait); | 644 | remove_wait_queue(&host->wq, &wait); |
| 744 | if (!stop) | 645 | if (host->ops->enable && !stop && host->claim_cnt == 1) |
| 745 | mmc_host_enable(host); | 646 | host->ops->enable(host); |
| 746 | return stop; | 647 | return stop; |
| 747 | } | 648 | } |
| 748 | 649 | ||
| @@ -767,21 +668,28 @@ int mmc_try_claim_host(struct mmc_host *host) | |||
| 767 | claimed_host = 1; | 668 | claimed_host = 1; |
| 768 | } | 669 | } |
| 769 | spin_unlock_irqrestore(&host->lock, flags); | 670 | spin_unlock_irqrestore(&host->lock, flags); |
| 671 | if (host->ops->enable && claimed_host && host->claim_cnt == 1) | ||
| 672 | host->ops->enable(host); | ||
| 770 | return claimed_host; | 673 | return claimed_host; |
| 771 | } | 674 | } |
| 772 | EXPORT_SYMBOL(mmc_try_claim_host); | 675 | EXPORT_SYMBOL(mmc_try_claim_host); |
| 773 | 676 | ||
| 774 | /** | 677 | /** |
| 775 | * mmc_do_release_host - release a claimed host | 678 | * mmc_release_host - release a host |
| 776 | * @host: mmc host to release | 679 | * @host: mmc host to release |
| 777 | * | 680 | * |
| 778 | * If you successfully claimed a host, this function will | 681 | * Release a MMC host, allowing others to claim the host |
| 779 | * release it again. | 682 | * for their operations. |
| 780 | */ | 683 | */ |
| 781 | void mmc_do_release_host(struct mmc_host *host) | 684 | void mmc_release_host(struct mmc_host *host) |
| 782 | { | 685 | { |
| 783 | unsigned long flags; | 686 | unsigned long flags; |
| 784 | 687 | ||
| 688 | WARN_ON(!host->claimed); | ||
| 689 | |||
| 690 | if (host->ops->disable && host->claim_cnt == 1) | ||
| 691 | host->ops->disable(host); | ||
| 692 | |||
| 785 | spin_lock_irqsave(&host->lock, flags); | 693 | spin_lock_irqsave(&host->lock, flags); |
| 786 | if (--host->claim_cnt) { | 694 | if (--host->claim_cnt) { |
| 787 | /* Release for nested claim */ | 695 | /* Release for nested claim */ |
| @@ -793,67 +701,6 @@ void mmc_do_release_host(struct mmc_host *host) | |||
| 793 | wake_up(&host->wq); | 701 | wake_up(&host->wq); |
| 794 | } | 702 | } |
| 795 | } | 703 | } |
| 796 | EXPORT_SYMBOL(mmc_do_release_host); | ||
| 797 | |||
| 798 | void mmc_host_deeper_disable(struct work_struct *work) | ||
| 799 | { | ||
| 800 | struct mmc_host *host = | ||
| 801 | container_of(work, struct mmc_host, disable.work); | ||
| 802 | |||
| 803 | /* If the host is claimed then we do not want to disable it anymore */ | ||
| 804 | if (!mmc_try_claim_host(host)) | ||
| 805 | return; | ||
| 806 | mmc_host_do_disable(host, 1); | ||
| 807 | mmc_do_release_host(host); | ||
| 808 | } | ||
| 809 | |||
| 810 | /** | ||
| 811 | * mmc_host_lazy_disable - lazily disable a host. | ||
| 812 | * @host: mmc host to disable | ||
| 813 | * | ||
| 814 | * Hosts that support power saving can use the 'enable' and 'disable' | ||
| 815 | * methods to exit and enter power saving states. For more information | ||
| 816 | * see comments for struct mmc_host_ops. | ||
| 817 | */ | ||
| 818 | int mmc_host_lazy_disable(struct mmc_host *host) | ||
| 819 | { | ||
| 820 | if (!(host->caps & MMC_CAP_DISABLE)) | ||
| 821 | return 0; | ||
| 822 | |||
| 823 | if (host->en_dis_recurs) | ||
| 824 | return 0; | ||
| 825 | |||
| 826 | if (--host->nesting_cnt) | ||
| 827 | return 0; | ||
| 828 | |||
| 829 | if (!host->enabled) | ||
| 830 | return 0; | ||
| 831 | |||
| 832 | if (host->disable_delay) { | ||
| 833 | mmc_schedule_delayed_work(&host->disable, | ||
| 834 | msecs_to_jiffies(host->disable_delay)); | ||
| 835 | return 0; | ||
| 836 | } else | ||
| 837 | return mmc_host_do_disable(host, 1); | ||
| 838 | } | ||
| 839 | EXPORT_SYMBOL(mmc_host_lazy_disable); | ||
| 840 | |||
| 841 | /** | ||
| 842 | * mmc_release_host - release a host | ||
| 843 | * @host: mmc host to release | ||
| 844 | * | ||
| 845 | * Release a MMC host, allowing others to claim the host | ||
| 846 | * for their operations. | ||
| 847 | */ | ||
| 848 | void mmc_release_host(struct mmc_host *host) | ||
| 849 | { | ||
| 850 | WARN_ON(!host->claimed); | ||
| 851 | |||
| 852 | mmc_host_lazy_disable(host); | ||
| 853 | |||
| 854 | mmc_do_release_host(host); | ||
| 855 | } | ||
| 856 | |||
| 857 | EXPORT_SYMBOL(mmc_release_host); | 704 | EXPORT_SYMBOL(mmc_release_host); |
| 858 | 705 | ||
| 859 | /* | 706 | /* |
| @@ -2227,8 +2074,6 @@ void mmc_stop_host(struct mmc_host *host) | |||
| 2227 | spin_unlock_irqrestore(&host->lock, flags); | 2074 | spin_unlock_irqrestore(&host->lock, flags); |
| 2228 | #endif | 2075 | #endif |
| 2229 | 2076 | ||
| 2230 | if (host->caps & MMC_CAP_DISABLE) | ||
| 2231 | cancel_delayed_work(&host->disable); | ||
| 2232 | cancel_delayed_work_sync(&host->detect); | 2077 | cancel_delayed_work_sync(&host->detect); |
| 2233 | mmc_flush_scheduled_work(); | 2078 | mmc_flush_scheduled_work(); |
| 2234 | 2079 | ||
| @@ -2423,13 +2268,11 @@ int mmc_suspend_host(struct mmc_host *host) | |||
| 2423 | { | 2268 | { |
| 2424 | int err = 0; | 2269 | int err = 0; |
| 2425 | 2270 | ||
| 2426 | if (host->caps & MMC_CAP_DISABLE) | ||
| 2427 | cancel_delayed_work(&host->disable); | ||
| 2428 | cancel_delayed_work(&host->detect); | 2271 | cancel_delayed_work(&host->detect); |
| 2429 | mmc_flush_scheduled_work(); | 2272 | mmc_flush_scheduled_work(); |
| 2430 | if (mmc_try_claim_host(host)) { | 2273 | if (mmc_try_claim_host(host)) { |
| 2431 | err = mmc_cache_ctrl(host, 0); | 2274 | err = mmc_cache_ctrl(host, 0); |
| 2432 | mmc_do_release_host(host); | 2275 | mmc_release_host(host); |
| 2433 | } else { | 2276 | } else { |
| 2434 | err = -EBUSY; | 2277 | err = -EBUSY; |
| 2435 | } | 2278 | } |
| @@ -2450,7 +2293,7 @@ int mmc_suspend_host(struct mmc_host *host) | |||
| 2450 | if (host->bus_ops->suspend) { | 2293 | if (host->bus_ops->suspend) { |
| 2451 | err = host->bus_ops->suspend(host); | 2294 | err = host->bus_ops->suspend(host); |
| 2452 | } | 2295 | } |
| 2453 | mmc_do_release_host(host); | 2296 | mmc_release_host(host); |
| 2454 | 2297 | ||
| 2455 | if (err == -ENOSYS || !host->bus_ops->resume) { | 2298 | if (err == -ENOSYS || !host->bus_ops->resume) { |
| 2456 | /* | 2299 | /* |
