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:
Adrian Hunter 2017-09-22 15:36:51 +03:00 committed by Ulf Hansson
parent 9ca28c5cd9
commit 6c0cedd1ef
7 changed files with 60 additions and 19 deletions

View File

@ -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)

View File

@ -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);
} }

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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 */