Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mmc: core: Validate suspend prerequisites for SDIO at SUSPEND_PREPARE

This patch moves the validation for all the suspend prerequisites to be
done at SUSPEND_PREPARE notification. Previously in the SDIO case parts
of the validation was done from mmc_suspend_host.

This patch invents a new pre_suspend bus_ops callback and implements it
for SDIO. Returning an error code from it, will mean at SUSPEND_PREPARE
notification, the card will be removed before proceeding with the
suspend sequence.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Tested-by: Jaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: Chris Ball <cjb@laptop.org>

authored by

Ulf Hansson and committed by
Chris Ball
810caddb 58a8a4a1

+32 -21
+8 -17
drivers/mmc/core/core.c
··· 2628 2628 if (host->bus_ops && !host->bus_dead) { 2629 2629 if (host->bus_ops->suspend) 2630 2630 err = host->bus_ops->suspend(host); 2631 - 2632 - if (err == -ENOSYS || !host->bus_ops->resume) { 2633 - /* 2634 - * We simply "remove" the card in this case. 2635 - * It will be redetected on resume. (Calling 2636 - * bus_ops->remove() with a claimed host can 2637 - * deadlock.) 2638 - */ 2639 - host->bus_ops->remove(host); 2640 - mmc_claim_host(host); 2641 - mmc_detach_bus(host); 2642 - mmc_power_off(host); 2643 - mmc_release_host(host); 2644 - host->pm_flags = 0; 2645 - err = 0; 2646 - } 2647 2631 } 2648 2632 mmc_bus_put(host); 2649 2633 ··· 2690 2706 struct mmc_host *host = container_of( 2691 2707 notify_block, struct mmc_host, pm_notify); 2692 2708 unsigned long flags; 2709 + int err = 0; 2693 2710 2694 2711 switch (mode) { 2695 2712 case PM_HIBERNATION_PREPARE: ··· 2700 2715 spin_unlock_irqrestore(&host->lock, flags); 2701 2716 cancel_delayed_work_sync(&host->detect); 2702 2717 2703 - if (!host->bus_ops || host->bus_ops->suspend) 2718 + if (!host->bus_ops) 2719 + break; 2720 + 2721 + /* Validate prerequisites for suspend */ 2722 + if (host->bus_ops->pre_suspend) 2723 + err = host->bus_ops->pre_suspend(host); 2724 + if (!err && host->bus_ops->suspend) 2704 2725 break; 2705 2726 2706 2727 /* Calling bus_ops->remove() with a claimed host can deadlock */
+1
drivers/mmc/core/core.h
··· 18 18 struct mmc_bus_ops { 19 19 void (*remove)(struct mmc_host *); 20 20 void (*detect)(struct mmc_host *); 21 + int (*pre_suspend)(struct mmc_host *); 21 22 int (*suspend)(struct mmc_host *); 22 23 int (*resume)(struct mmc_host *); 23 24 int (*runtime_suspend)(struct mmc_host *);
+23 -4
drivers/mmc/core/sdio.c
··· 910 910 } 911 911 912 912 /* 913 - * SDIO suspend. We need to suspend all functions separately. 913 + * SDIO pre_suspend. We need to suspend all functions separately. 914 914 * Therefore all registered functions must have drivers with suspend 915 915 * and resume methods. Failing that we simply remove the whole card. 916 916 */ 917 - static int mmc_sdio_suspend(struct mmc_host *host) 917 + static int mmc_sdio_pre_suspend(struct mmc_host *host) 918 918 { 919 919 int i, err = 0; 920 920 ··· 925 925 if (!pmops || !pmops->suspend || !pmops->resume) { 926 926 /* force removal of entire card in that case */ 927 927 err = -ENOSYS; 928 - } else 929 - err = pmops->suspend(&func->dev); 928 + break; 929 + } 930 + } 931 + } 932 + 933 + return err; 934 + } 935 + 936 + /* 937 + * SDIO suspend. Suspend all functions separately. 938 + */ 939 + static int mmc_sdio_suspend(struct mmc_host *host) 940 + { 941 + int i, err = 0; 942 + 943 + for (i = 0; i < host->card->sdio_funcs; i++) { 944 + struct sdio_func *func = host->card->sdio_func[i]; 945 + if (func && sdio_func_present(func) && func->dev.driver) { 946 + const struct dev_pm_ops *pmops = func->dev.driver->pm; 947 + err = pmops->suspend(&func->dev); 930 948 if (err) 931 949 break; 932 950 } ··· 1094 1076 static const struct mmc_bus_ops mmc_sdio_ops = { 1095 1077 .remove = mmc_sdio_remove, 1096 1078 .detect = mmc_sdio_detect, 1079 + .pre_suspend = mmc_sdio_pre_suspend, 1097 1080 .suspend = mmc_sdio_suspend, 1098 1081 .resume = mmc_sdio_resume, 1099 1082 .runtime_suspend = mmc_sdio_runtime_suspend,