mmc: core: Introduce host claiming by context
Currently the host can be claimed by a task. Change this so that the host can be claimed by a context that may or may not be a task. This provides for the host to be claimed by a block driver queue to support blk-mq, while maintaining compatibility with the existing use of mmc_claim_host(). Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
parent
9ca28c5cd9
commit
6c0cedd1ef
|
@ -1989,7 +1989,7 @@ void mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
|
||||||
|
|
||||||
if (req && !mq->qcnt)
|
if (req && !mq->qcnt)
|
||||||
/* claim host only for the first request */
|
/* claim host only for the first request */
|
||||||
mmc_get_card(card);
|
mmc_get_card(card, NULL);
|
||||||
|
|
||||||
ret = mmc_blk_part_switch(card, md->part_type);
|
ret = mmc_blk_part_switch(card, md->part_type);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -2052,7 +2052,7 @@ void mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (!mq->qcnt)
|
if (!mq->qcnt)
|
||||||
mmc_put_card(card);
|
mmc_put_card(card, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int mmc_blk_readonly(struct mmc_card *card)
|
static inline int mmc_blk_readonly(struct mmc_card *card)
|
||||||
|
|
|
@ -832,9 +832,36 @@ unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mmc_align_data_size);
|
EXPORT_SYMBOL(mmc_align_data_size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allow claiming an already claimed host if the context is the same or there is
|
||||||
|
* no context but the task is the same.
|
||||||
|
*/
|
||||||
|
static inline bool mmc_ctx_matches(struct mmc_host *host, struct mmc_ctx *ctx,
|
||||||
|
struct task_struct *task)
|
||||||
|
{
|
||||||
|
return host->claimer == ctx ||
|
||||||
|
(!ctx && task && host->claimer->task == task);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mmc_ctx_set_claimer(struct mmc_host *host,
|
||||||
|
struct mmc_ctx *ctx,
|
||||||
|
struct task_struct *task)
|
||||||
|
{
|
||||||
|
if (!host->claimer) {
|
||||||
|
if (ctx)
|
||||||
|
host->claimer = ctx;
|
||||||
|
else
|
||||||
|
host->claimer = &host->default_ctx;
|
||||||
|
}
|
||||||
|
if (task)
|
||||||
|
host->claimer->task = task;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __mmc_claim_host - exclusively claim a host
|
* __mmc_claim_host - exclusively claim a host
|
||||||
* @host: mmc host to claim
|
* @host: mmc host to claim
|
||||||
|
* @ctx: context that claims the host or NULL in which case the default
|
||||||
|
* context will be used
|
||||||
* @abort: whether or not the operation should be aborted
|
* @abort: whether or not the operation should be aborted
|
||||||
*
|
*
|
||||||
* Claim a host for a set of operations. If @abort is non null and
|
* Claim a host for a set of operations. If @abort is non null and
|
||||||
|
@ -842,8 +869,10 @@ EXPORT_SYMBOL(mmc_align_data_size);
|
||||||
* that non-zero value without acquiring the lock. Returns zero
|
* that non-zero value without acquiring the lock. Returns zero
|
||||||
* with the lock held otherwise.
|
* with the lock held otherwise.
|
||||||
*/
|
*/
|
||||||
int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
|
int __mmc_claim_host(struct mmc_host *host, struct mmc_ctx *ctx,
|
||||||
|
atomic_t *abort)
|
||||||
{
|
{
|
||||||
|
struct task_struct *task = ctx ? NULL : current;
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int stop;
|
int stop;
|
||||||
|
@ -856,7 +885,7 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
|
||||||
while (1) {
|
while (1) {
|
||||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||||
stop = abort ? atomic_read(abort) : 0;
|
stop = abort ? atomic_read(abort) : 0;
|
||||||
if (stop || !host->claimed || host->claimer == current)
|
if (stop || !host->claimed || mmc_ctx_matches(host, ctx, task))
|
||||||
break;
|
break;
|
||||||
spin_unlock_irqrestore(&host->lock, flags);
|
spin_unlock_irqrestore(&host->lock, flags);
|
||||||
schedule();
|
schedule();
|
||||||
|
@ -865,7 +894,7 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
|
||||||
set_current_state(TASK_RUNNING);
|
set_current_state(TASK_RUNNING);
|
||||||
if (!stop) {
|
if (!stop) {
|
||||||
host->claimed = 1;
|
host->claimed = 1;
|
||||||
host->claimer = current;
|
mmc_ctx_set_claimer(host, ctx, task);
|
||||||
host->claim_cnt += 1;
|
host->claim_cnt += 1;
|
||||||
if (host->claim_cnt == 1)
|
if (host->claim_cnt == 1)
|
||||||
pm = true;
|
pm = true;
|
||||||
|
@ -900,6 +929,7 @@ void mmc_release_host(struct mmc_host *host)
|
||||||
spin_unlock_irqrestore(&host->lock, flags);
|
spin_unlock_irqrestore(&host->lock, flags);
|
||||||
} else {
|
} else {
|
||||||
host->claimed = 0;
|
host->claimed = 0;
|
||||||
|
host->claimer->task = NULL;
|
||||||
host->claimer = NULL;
|
host->claimer = NULL;
|
||||||
spin_unlock_irqrestore(&host->lock, flags);
|
spin_unlock_irqrestore(&host->lock, flags);
|
||||||
wake_up(&host->wq);
|
wake_up(&host->wq);
|
||||||
|
@ -913,10 +943,10 @@ EXPORT_SYMBOL(mmc_release_host);
|
||||||
* This is a helper function, which fetches a runtime pm reference for the
|
* This is a helper function, which fetches a runtime pm reference for the
|
||||||
* card device and also claims the host.
|
* card device and also claims the host.
|
||||||
*/
|
*/
|
||||||
void mmc_get_card(struct mmc_card *card)
|
void mmc_get_card(struct mmc_card *card, struct mmc_ctx *ctx)
|
||||||
{
|
{
|
||||||
pm_runtime_get_sync(&card->dev);
|
pm_runtime_get_sync(&card->dev);
|
||||||
mmc_claim_host(card->host);
|
__mmc_claim_host(card->host, ctx, NULL);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mmc_get_card);
|
EXPORT_SYMBOL(mmc_get_card);
|
||||||
|
|
||||||
|
@ -924,9 +954,13 @@ EXPORT_SYMBOL(mmc_get_card);
|
||||||
* This is a helper function, which releases the host and drops the runtime
|
* This is a helper function, which releases the host and drops the runtime
|
||||||
* pm reference for the card device.
|
* pm reference for the card device.
|
||||||
*/
|
*/
|
||||||
void mmc_put_card(struct mmc_card *card)
|
void mmc_put_card(struct mmc_card *card, struct mmc_ctx *ctx)
|
||||||
{
|
{
|
||||||
mmc_release_host(card->host);
|
struct mmc_host *host = card->host;
|
||||||
|
|
||||||
|
WARN_ON(ctx && host->claimer != ctx);
|
||||||
|
|
||||||
|
mmc_release_host(host);
|
||||||
pm_runtime_mark_last_busy(&card->dev);
|
pm_runtime_mark_last_busy(&card->dev);
|
||||||
pm_runtime_put_autosuspend(&card->dev);
|
pm_runtime_put_autosuspend(&card->dev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,10 +128,11 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen);
|
||||||
int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount,
|
int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount,
|
||||||
bool is_rel_write);
|
bool is_rel_write);
|
||||||
|
|
||||||
int __mmc_claim_host(struct mmc_host *host, atomic_t *abort);
|
int __mmc_claim_host(struct mmc_host *host, struct mmc_ctx *ctx,
|
||||||
|
atomic_t *abort);
|
||||||
void mmc_release_host(struct mmc_host *host);
|
void mmc_release_host(struct mmc_host *host);
|
||||||
void mmc_get_card(struct mmc_card *card);
|
void mmc_get_card(struct mmc_card *card, struct mmc_ctx *ctx);
|
||||||
void mmc_put_card(struct mmc_card *card);
|
void mmc_put_card(struct mmc_card *card, struct mmc_ctx *ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mmc_claim_host - exclusively claim a host
|
* mmc_claim_host - exclusively claim a host
|
||||||
|
@ -141,7 +142,7 @@ void mmc_put_card(struct mmc_card *card);
|
||||||
*/
|
*/
|
||||||
static inline void mmc_claim_host(struct mmc_host *host)
|
static inline void mmc_claim_host(struct mmc_host *host)
|
||||||
{
|
{
|
||||||
__mmc_claim_host(host, NULL);
|
__mmc_claim_host(host, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1911,14 +1911,14 @@ static void mmc_detect(struct mmc_host *host)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
mmc_get_card(host->card);
|
mmc_get_card(host->card, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Just check if our card has been removed.
|
* Just check if our card has been removed.
|
||||||
*/
|
*/
|
||||||
err = _mmc_detect_card_removed(host);
|
err = _mmc_detect_card_removed(host);
|
||||||
|
|
||||||
mmc_put_card(host->card);
|
mmc_put_card(host->card, NULL);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
mmc_remove(host);
|
mmc_remove(host);
|
||||||
|
|
|
@ -1056,14 +1056,14 @@ static void mmc_sd_detect(struct mmc_host *host)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
mmc_get_card(host->card);
|
mmc_get_card(host->card, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Just check if our card has been removed.
|
* Just check if our card has been removed.
|
||||||
*/
|
*/
|
||||||
err = _mmc_detect_card_removed(host);
|
err = _mmc_detect_card_removed(host);
|
||||||
|
|
||||||
mmc_put_card(host->card);
|
mmc_put_card(host->card, NULL);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
mmc_sd_remove(host);
|
mmc_sd_remove(host);
|
||||||
|
|
|
@ -155,7 +155,8 @@ static int sdio_irq_thread(void *_host)
|
||||||
* holding of the host lock does not cover too much work
|
* holding of the host lock does not cover too much work
|
||||||
* that doesn't require that lock to be held.
|
* that doesn't require that lock to be held.
|
||||||
*/
|
*/
|
||||||
ret = __mmc_claim_host(host, &host->sdio_irq_thread_abort);
|
ret = __mmc_claim_host(host, NULL,
|
||||||
|
&host->sdio_irq_thread_abort);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
ret = process_sdio_pending_irqs(host);
|
ret = process_sdio_pending_irqs(host);
|
||||||
|
|
|
@ -255,6 +255,10 @@ struct mmc_supply {
|
||||||
struct regulator *vqmmc; /* Optional Vccq supply */
|
struct regulator *vqmmc; /* Optional Vccq supply */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mmc_ctx {
|
||||||
|
struct task_struct *task;
|
||||||
|
};
|
||||||
|
|
||||||
struct mmc_host {
|
struct mmc_host {
|
||||||
struct device *parent;
|
struct device *parent;
|
||||||
struct device class_dev;
|
struct device class_dev;
|
||||||
|
@ -388,8 +392,9 @@ struct mmc_host {
|
||||||
struct mmc_card *card; /* device attached to this host */
|
struct mmc_card *card; /* device attached to this host */
|
||||||
|
|
||||||
wait_queue_head_t wq;
|
wait_queue_head_t wq;
|
||||||
struct task_struct *claimer; /* task that has host claimed */
|
struct mmc_ctx *claimer; /* context that has host claimed */
|
||||||
int claim_cnt; /* "claim" nesting count */
|
int claim_cnt; /* "claim" nesting count */
|
||||||
|
struct mmc_ctx default_ctx; /* default context */
|
||||||
|
|
||||||
struct delayed_work detect;
|
struct delayed_work detect;
|
||||||
int detect_change; /* card detect flag */
|
int detect_change; /* card detect flag */
|
||||||
|
|
Loading…
Reference in New Issue