mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-16 05:50:19 +00:00
mmc: core: Signal wakeup event at card insert/removal
We want to give user space provision to fully consume a card insert/remove event, when the event was caused by a wakeup irq. By signaling the wakeup event for a time of 5 s for devices configured as wakeup capable, we likely will be prevent a sleep long enough to let user space consume the event. To enable this feature, host drivers must thus configure their devices as wakeup capable. This is a reworked implementation of the old wakelocks for the mmc subsystem, originally authored by Colin Cross and San Mehat for the Android kernel. Zoran Markovic shall also be given cred for recently re-trying to upstream this feature. Cc: San Mehat <san@google.com> Cc: Colin Cross <ccross@android.com> Cc: John Stultz <john.stultz@linaro.org> Cc: Zoran Markovic <zoran.markovic@linaro.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Reviewed-by: Zoran Markovic <zoran.markovic@linaro.org> Signed-off-by: Chris Ball <cjb@laptop.org>
This commit is contained in:
parent
726d6f2374
commit
bbd43682eb
@ -23,6 +23,7 @@
|
|||||||
#include <linux/log2.h>
|
#include <linux/log2.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/pm_wakeup.h>
|
||||||
#include <linux/suspend.h>
|
#include <linux/suspend.h>
|
||||||
#include <linux/fault-inject.h>
|
#include <linux/fault-inject.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
@ -1692,6 +1693,28 @@ void mmc_detach_bus(struct mmc_host *host)
|
|||||||
mmc_bus_put(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
|
* mmc_detect_change - process change of state on a MMC socket
|
||||||
* @host: host which changed state.
|
* @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)
|
void mmc_detect_change(struct mmc_host *host, unsigned long delay)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_MMC_DEBUG
|
_mmc_detect_change(host, delay, true);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(mmc_detect_change);
|
EXPORT_SYMBOL(mmc_detect_change);
|
||||||
|
|
||||||
void mmc_init_erase(struct mmc_card *card)
|
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.
|
* rescan handle the card removal.
|
||||||
*/
|
*/
|
||||||
cancel_delayed_work(&host->detect);
|
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);
|
mmc_power_off(host);
|
||||||
else
|
else
|
||||||
mmc_power_up(host, host->ocr_avail);
|
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)
|
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);
|
spin_lock_irqsave(&host->lock, flags);
|
||||||
host->rescan_disable = 0;
|
host->rescan_disable = 0;
|
||||||
spin_unlock_irqrestore(&host->lock, flags);
|
spin_unlock_irqrestore(&host->lock, flags);
|
||||||
mmc_detect_change(host, 0);
|
_mmc_detect_change(host, 0, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user