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.c252
1 files changed, 57 insertions, 195 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 132378b89d76..14f262e9246d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -188,6 +188,12 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
188 struct scatterlist *sg; 188 struct scatterlist *sg;
189#endif 189#endif
190 190
191 if (mrq->sbc) {
192 pr_debug("<%s: starting CMD%u arg %08x flags %08x>\n",
193 mmc_hostname(host), mrq->sbc->opcode,
194 mrq->sbc->arg, mrq->sbc->flags);
195 }
196
191 pr_debug("%s: starting CMD%u arg %08x flags %08x\n", 197 pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
192 mmc_hostname(host), mrq->cmd->opcode, 198 mmc_hostname(host), mrq->cmd->opcode,
193 mrq->cmd->arg, mrq->cmd->flags); 199 mrq->cmd->arg, mrq->cmd->flags);
@@ -243,16 +249,17 @@ static void mmc_wait_done(struct mmc_request *mrq)
243 complete(&mrq->completion); 249 complete(&mrq->completion);
244} 250}
245 251
246static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq) 252static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
247{ 253{
248 init_completion(&mrq->completion); 254 init_completion(&mrq->completion);
249 mrq->done = mmc_wait_done; 255 mrq->done = mmc_wait_done;
250 if (mmc_card_removed(host->card)) { 256 if (mmc_card_removed(host->card)) {
251 mrq->cmd->error = -ENOMEDIUM; 257 mrq->cmd->error = -ENOMEDIUM;
252 complete(&mrq->completion); 258 complete(&mrq->completion);
253 return; 259 return -ENOMEDIUM;
254 } 260 }
255 mmc_start_request(host, mrq); 261 mmc_start_request(host, mrq);
262 return 0;
256} 263}
257 264
258static void mmc_wait_for_req_done(struct mmc_host *host, 265static void mmc_wait_for_req_done(struct mmc_host *host,
@@ -336,6 +343,7 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
336 struct mmc_async_req *areq, int *error) 343 struct mmc_async_req *areq, int *error)
337{ 344{
338 int err = 0; 345 int err = 0;
346 int start_err = 0;
339 struct mmc_async_req *data = host->areq; 347 struct mmc_async_req *data = host->areq;
340 348
341 /* Prepare a new request */ 349 /* Prepare a new request */
@@ -345,30 +353,23 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
345 if (host->areq) { 353 if (host->areq) {
346 mmc_wait_for_req_done(host, host->areq->mrq); 354 mmc_wait_for_req_done(host, host->areq->mrq);
347 err = host->areq->err_check(host->card, host->areq); 355 err = host->areq->err_check(host->card, host->areq);
348 if (err) {
349 /* post process the completed failed request */
350 mmc_post_req(host, host->areq->mrq, 0);
351 if (areq)
352 /*
353 * Cancel the new prepared request, because
354 * it can't run until the failed
355 * request has been properly handled.
356 */
357 mmc_post_req(host, areq->mrq, -EINVAL);
358
359 host->areq = NULL;
360 goto out;
361 }
362 } 356 }
363 357
364 if (areq) 358 if (!err && areq)
365 __mmc_start_req(host, areq->mrq); 359 start_err = __mmc_start_req(host, areq->mrq);
366 360
367 if (host->areq) 361 if (host->areq)
368 mmc_post_req(host, host->areq->mrq, 0); 362 mmc_post_req(host, host->areq->mrq, 0);
369 363
370 host->areq = areq; 364 /* Cancel a prepared request if it was not started. */
371 out: 365 if ((err || start_err) && areq)
366 mmc_post_req(host, areq->mrq, -EINVAL);
367
368 if (err)
369 host->areq = NULL;
370 else
371 host->areq = areq;
372
372 if (error) 373 if (error)
373 *error = err; 374 *error = err;
374 return data; 375 return data;
@@ -599,105 +600,6 @@ unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz)
599EXPORT_SYMBOL(mmc_align_data_size); 600EXPORT_SYMBOL(mmc_align_data_size);
600 601
601/** 602/**
602 * mmc_host_enable - enable a host.
603 * @host: mmc host to enable
604 *
605 * Hosts that support power saving can use the 'enable' and 'disable'
606 * methods to exit and enter power saving states. For more information
607 * see comments for struct mmc_host_ops.
608 */
609int mmc_host_enable(struct mmc_host *host)
610{
611 if (!(host->caps & MMC_CAP_DISABLE))
612 return 0;
613
614 if (host->en_dis_recurs)
615 return 0;
616
617 if (host->nesting_cnt++)
618 return 0;
619
620 cancel_delayed_work_sync(&host->disable);
621
622 if (host->enabled)
623 return 0;
624
625 if (host->ops->enable) {
626 int err;
627
628 host->en_dis_recurs = 1;
629 mmc_host_clk_hold(host);
630 err = host->ops->enable(host);
631 mmc_host_clk_release(host);
632 host->en_dis_recurs = 0;
633
634 if (err) {
635 pr_debug("%s: enable error %d\n",
636 mmc_hostname(host), err);
637 return err;
638 }
639 }
640 host->enabled = 1;
641 return 0;
642}
643EXPORT_SYMBOL(mmc_host_enable);
644
645static int mmc_host_do_disable(struct mmc_host *host, int lazy)
646{
647 if (host->ops->disable) {
648 int err;
649
650 host->en_dis_recurs = 1;
651 mmc_host_clk_hold(host);
652 err = host->ops->disable(host, lazy);
653 mmc_host_clk_release(host);
654 host->en_dis_recurs = 0;
655
656 if (err < 0) {
657 pr_debug("%s: disable error %d\n",
658 mmc_hostname(host), err);
659 return err;
660 }
661 if (err > 0) {
662 unsigned long delay = msecs_to_jiffies(err);
663
664 mmc_schedule_delayed_work(&host->disable, delay);
665 }
666 }
667 host->enabled = 0;
668 return 0;
669}
670
671/**
672 * mmc_host_disable - disable a host.
673 * @host: mmc host to disable
674 *
675 * Hosts that support power saving can use the 'enable' and 'disable'
676 * methods to exit and enter power saving states. For more information
677 * see comments for struct mmc_host_ops.
678 */
679int mmc_host_disable(struct mmc_host *host)
680{
681 int err;
682
683 if (!(host->caps & MMC_CAP_DISABLE))
684 return 0;
685
686 if (host->en_dis_recurs)
687 return 0;
688
689 if (--host->nesting_cnt)
690 return 0;
691
692 if (!host->enabled)
693 return 0;
694
695 err = mmc_host_do_disable(host, 0);
696 return err;
697}
698EXPORT_SYMBOL(mmc_host_disable);
699
700/**
701 * __mmc_claim_host - exclusively claim a host 603 * __mmc_claim_host - exclusively claim a host
702 * @host: mmc host to claim 604 * @host: mmc host to claim
703 * @abort: whether or not the operation should be aborted 605 * @abort: whether or not the operation should be aborted
@@ -735,8 +637,8 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
735 wake_up(&host->wq); 637 wake_up(&host->wq);
736 spin_unlock_irqrestore(&host->lock, flags); 638 spin_unlock_irqrestore(&host->lock, flags);
737 remove_wait_queue(&host->wq, &wait); 639 remove_wait_queue(&host->wq, &wait);
738 if (!stop) 640 if (host->ops->enable && !stop && host->claim_cnt == 1)
739 mmc_host_enable(host); 641 host->ops->enable(host);
740 return stop; 642 return stop;
741} 643}
742 644
@@ -761,21 +663,28 @@ int mmc_try_claim_host(struct mmc_host *host)
761 claimed_host = 1; 663 claimed_host = 1;
762 } 664 }
763 spin_unlock_irqrestore(&host->lock, flags); 665 spin_unlock_irqrestore(&host->lock, flags);
666 if (host->ops->enable && claimed_host && host->claim_cnt == 1)
667 host->ops->enable(host);
764 return claimed_host; 668 return claimed_host;
765} 669}
766EXPORT_SYMBOL(mmc_try_claim_host); 670EXPORT_SYMBOL(mmc_try_claim_host);
767 671
768/** 672/**
769 * mmc_do_release_host - release a claimed host 673 * mmc_release_host - release a host
770 * @host: mmc host to release 674 * @host: mmc host to release
771 * 675 *
772 * If you successfully claimed a host, this function will 676 * Release a MMC host, allowing others to claim the host
773 * release it again. 677 * for their operations.
774 */ 678 */
775void mmc_do_release_host(struct mmc_host *host) 679void mmc_release_host(struct mmc_host *host)
776{ 680{
777 unsigned long flags; 681 unsigned long flags;
778 682
683 WARN_ON(!host->claimed);
684
685 if (host->ops->disable && host->claim_cnt == 1)
686 host->ops->disable(host);
687
779 spin_lock_irqsave(&host->lock, flags); 688 spin_lock_irqsave(&host->lock, flags);
780 if (--host->claim_cnt) { 689 if (--host->claim_cnt) {
781 /* Release for nested claim */ 690 /* Release for nested claim */
@@ -787,67 +696,6 @@ void mmc_do_release_host(struct mmc_host *host)
787 wake_up(&host->wq); 696 wake_up(&host->wq);
788 } 697 }
789} 698}
790EXPORT_SYMBOL(mmc_do_release_host);
791
792void mmc_host_deeper_disable(struct work_struct *work)
793{
794 struct mmc_host *host =
795 container_of(work, struct mmc_host, disable.work);
796
797 /* If the host is claimed then we do not want to disable it anymore */
798 if (!mmc_try_claim_host(host))
799 return;
800 mmc_host_do_disable(host, 1);
801 mmc_do_release_host(host);
802}
803
804/**
805 * mmc_host_lazy_disable - lazily disable a host.
806 * @host: mmc host to disable
807 *
808 * Hosts that support power saving can use the 'enable' and 'disable'
809 * methods to exit and enter power saving states. For more information
810 * see comments for struct mmc_host_ops.
811 */
812int mmc_host_lazy_disable(struct mmc_host *host)
813{
814 if (!(host->caps & MMC_CAP_DISABLE))
815 return 0;
816
817 if (host->en_dis_recurs)
818 return 0;
819
820 if (--host->nesting_cnt)
821 return 0;
822
823 if (!host->enabled)
824 return 0;
825
826 if (host->disable_delay) {
827 mmc_schedule_delayed_work(&host->disable,
828 msecs_to_jiffies(host->disable_delay));
829 return 0;
830 } else
831 return mmc_host_do_disable(host, 1);
832}
833EXPORT_SYMBOL(mmc_host_lazy_disable);
834
835/**
836 * mmc_release_host - release a host
837 * @host: mmc host to release
838 *
839 * Release a MMC host, allowing others to claim the host
840 * for their operations.
841 */
842void mmc_release_host(struct mmc_host *host)
843{
844 WARN_ON(!host->claimed);
845
846 mmc_host_lazy_disable(host);
847
848 mmc_do_release_host(host);
849}
850
851EXPORT_SYMBOL(mmc_release_host); 699EXPORT_SYMBOL(mmc_release_host);
852 700
853/* 701/*
@@ -2115,18 +1963,36 @@ int _mmc_detect_card_removed(struct mmc_host *host)
2115int mmc_detect_card_removed(struct mmc_host *host) 1963int mmc_detect_card_removed(struct mmc_host *host)
2116{ 1964{
2117 struct mmc_card *card = host->card; 1965 struct mmc_card *card = host->card;
1966 int ret;
2118 1967
2119 WARN_ON(!host->claimed); 1968 WARN_ON(!host->claimed);
1969
1970 if (!card)
1971 return 1;
1972
1973 ret = mmc_card_removed(card);
2120 /* 1974 /*
2121 * The card will be considered unchanged unless we have been asked to 1975 * The card will be considered unchanged unless we have been asked to
2122 * detect a change or host requires polling to provide card detection. 1976 * detect a change or host requires polling to provide card detection.
2123 */ 1977 */
2124 if (card && !host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL)) 1978 if (!host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL) &&
2125 return mmc_card_removed(card); 1979 !(host->caps2 & MMC_CAP2_DETECT_ON_ERR))
1980 return ret;
2126 1981
2127 host->detect_change = 0; 1982 host->detect_change = 0;
1983 if (!ret) {
1984 ret = _mmc_detect_card_removed(host);
1985 if (ret && (host->caps2 & MMC_CAP2_DETECT_ON_ERR)) {
1986 /*
1987 * Schedule a detect work as soon as possible to let a
1988 * rescan handle the card removal.
1989 */
1990 cancel_delayed_work(&host->detect);
1991 mmc_detect_change(host, 0);
1992 }
1993 }
2128 1994
2129 return _mmc_detect_card_removed(host); 1995 return ret;
2130} 1996}
2131EXPORT_SYMBOL(mmc_detect_card_removed); 1997EXPORT_SYMBOL(mmc_detect_card_removed);
2132 1998
@@ -2203,8 +2069,6 @@ void mmc_stop_host(struct mmc_host *host)
2203 spin_unlock_irqrestore(&host->lock, flags); 2069 spin_unlock_irqrestore(&host->lock, flags);
2204#endif 2070#endif
2205 2071
2206 if (host->caps & MMC_CAP_DISABLE)
2207 cancel_delayed_work(&host->disable);
2208 cancel_delayed_work_sync(&host->detect); 2072 cancel_delayed_work_sync(&host->detect);
2209 mmc_flush_scheduled_work(); 2073 mmc_flush_scheduled_work();
2210 2074
@@ -2399,13 +2263,11 @@ int mmc_suspend_host(struct mmc_host *host)
2399{ 2263{
2400 int err = 0; 2264 int err = 0;
2401 2265
2402 if (host->caps & MMC_CAP_DISABLE)
2403 cancel_delayed_work(&host->disable);
2404 cancel_delayed_work(&host->detect); 2266 cancel_delayed_work(&host->detect);
2405 mmc_flush_scheduled_work(); 2267 mmc_flush_scheduled_work();
2406 if (mmc_try_claim_host(host)) { 2268 if (mmc_try_claim_host(host)) {
2407 err = mmc_cache_ctrl(host, 0); 2269 err = mmc_cache_ctrl(host, 0);
2408 mmc_do_release_host(host); 2270 mmc_release_host(host);
2409 } else { 2271 } else {
2410 err = -EBUSY; 2272 err = -EBUSY;
2411 } 2273 }
@@ -2426,7 +2288,7 @@ int mmc_suspend_host(struct mmc_host *host)
2426 if (host->bus_ops->suspend) { 2288 if (host->bus_ops->suspend) {
2427 err = host->bus_ops->suspend(host); 2289 err = host->bus_ops->suspend(host);
2428 } 2290 }
2429 mmc_do_release_host(host); 2291 mmc_release_host(host);
2430 2292
2431 if (err == -ENOSYS || !host->bus_ops->resume) { 2293 if (err == -ENOSYS || !host->bus_ops->resume) {
2432 /* 2294 /*