aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/core/core.c')
-rw-r--r--drivers/mmc/core/core.c187
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)
605EXPORT_SYMBOL(mmc_align_data_size); 605EXPORT_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 */
615int 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}
649EXPORT_SYMBOL(mmc_host_enable);
650
651static 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 */
685int 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}
704EXPORT_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}
772EXPORT_SYMBOL(mmc_try_claim_host); 675EXPORT_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 */
781void mmc_do_release_host(struct mmc_host *host) 684void 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}
796EXPORT_SYMBOL(mmc_do_release_host);
797
798void 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 */
818int 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}
839EXPORT_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 */
848void 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
857EXPORT_SYMBOL(mmc_release_host); 704EXPORT_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 /*