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 | /* |