|
@@ -23,6 +23,7 @@
|
|
|
#include <linux/log2.h>
|
|
|
#include <linux/regulator/consumer.h>
|
|
|
#include <linux/pm_runtime.h>
|
|
|
+#include <linux/pm_wakeup.h>
|
|
|
#include <linux/suspend.h>
|
|
|
#include <linux/fault-inject.h>
|
|
|
#include <linux/random.h>
|
|
@@ -1692,6 +1693,28 @@ void mmc_detach_bus(struct mmc_host *host)
|
|
|
mmc_bus_put(host);
|
|
|
}
|
|
|
|
|
|
+static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
|
|
|
+ bool cd_irq)
|
|
|
+{
|
|
|
+#ifdef CONFIG_MMC_DEBUG
|
|
|
+ unsigned long flags;
|
|
|
+ spin_lock_irqsave(&host->lock, flags);
|
|
|
+ WARN_ON(host->removed);
|
|
|
+ spin_unlock_irqrestore(&host->lock, flags);
|
|
|
+#endif
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If the device is configured as wakeup, we prevent a new sleep for
|
|
|
+ * 5 s to give provision for user space to consume the event.
|
|
|
+ */
|
|
|
+ if (cd_irq && !(host->caps & MMC_CAP_NEEDS_POLL) &&
|
|
|
+ device_can_wakeup(mmc_dev(host)))
|
|
|
+ pm_wakeup_event(mmc_dev(host), 5000);
|
|
|
+
|
|
|
+ host->detect_change = 1;
|
|
|
+ mmc_schedule_delayed_work(&host->detect, delay);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* mmc_detect_change - process change of state on a MMC socket
|
|
|
* @host: host which changed state.
|
|
@@ -1704,16 +1727,8 @@ void mmc_detach_bus(struct mmc_host *host)
|
|
|
*/
|
|
|
void mmc_detect_change(struct mmc_host *host, unsigned long delay)
|
|
|
{
|
|
|
-#ifdef CONFIG_MMC_DEBUG
|
|
|
- unsigned long flags;
|
|
|
- spin_lock_irqsave(&host->lock, flags);
|
|
|
- WARN_ON(host->removed);
|
|
|
- spin_unlock_irqrestore(&host->lock, flags);
|
|
|
-#endif
|
|
|
- host->detect_change = 1;
|
|
|
- mmc_schedule_delayed_work(&host->detect, delay);
|
|
|
+ _mmc_detect_change(host, delay, true);
|
|
|
}
|
|
|
-
|
|
|
EXPORT_SYMBOL(mmc_detect_change);
|
|
|
|
|
|
void mmc_init_erase(struct mmc_card *card)
|
|
@@ -2392,7 +2407,7 @@ int mmc_detect_card_removed(struct mmc_host *host)
|
|
|
* rescan handle the card removal.
|
|
|
*/
|
|
|
cancel_delayed_work(&host->detect);
|
|
|
- mmc_detect_change(host, 0);
|
|
|
+ _mmc_detect_change(host, 0, false);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -2474,7 +2489,7 @@ void mmc_start_host(struct mmc_host *host)
|
|
|
mmc_power_off(host);
|
|
|
else
|
|
|
mmc_power_up(host, host->ocr_avail);
|
|
|
- mmc_detect_change(host, 0);
|
|
|
+ _mmc_detect_change(host, 0, false);
|
|
|
}
|
|
|
|
|
|
void mmc_stop_host(struct mmc_host *host)
|
|
@@ -2693,7 +2708,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
|
|
|
spin_lock_irqsave(&host->lock, flags);
|
|
|
host->rescan_disable = 0;
|
|
|
spin_unlock_irqrestore(&host->lock, flags);
|
|
|
- mmc_detect_change(host, 0);
|
|
|
+ _mmc_detect_change(host, 0, false);
|
|
|
|
|
|
}
|
|
|
|