diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2017-09-22 15:36:51 +0300 |
---|---|---|
committer | Jason Liu <jason.hui.liu@nxp.com> | 2019-02-12 10:28:17 +0800 |
commit | 10400dbfd99be098589add6667605f2a1efeddb6 (patch) | |
tree | 176b75fb20a6791fbde685538e264f0b17c38f75 | |
parent | fb62ba05f867bf1915773d9737eee75036b020fd (diff) |
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>
(cherry picked from commit 6c0cedd1ef9527ef13e66875746570e76a3188a7)
Adjust for small imx changes in debugfs
Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
-rw-r--r-- | drivers/mmc/core/block.c | 4 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 48 | ||||
-rw-r--r-- | drivers/mmc/core/core.h | 9 | ||||
-rw-r--r-- | drivers/mmc/core/debugfs.c | 8 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 4 | ||||
-rw-r--r-- | drivers/mmc/core/sd.c | 4 | ||||
-rw-r--r-- | drivers/mmc/core/sdio_irq.c | 3 | ||||
-rw-r--r-- | include/linux/mmc/host.h | 7 |
8 files changed, 64 insertions, 23 deletions
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 0ae53d219c5b..0b7c8e14a7b2 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -2015,7 +2015,7 @@ void mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) if (req && !mq->qcnt) /* 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); if (ret) { @@ -2078,7 +2078,7 @@ void mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) out: if (!mq->qcnt) - mmc_put_card(card); + mmc_put_card(card, NULL); } static inline int mmc_blk_readonly(struct mmc_card *card) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index d14f23b005c0..7b04db81494f 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -985,9 +985,36 @@ unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz) } 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 * @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 * * Claim a host for a set of operations. If @abort is non null and @@ -995,8 +1022,10 @@ EXPORT_SYMBOL(mmc_align_data_size); * that non-zero value without acquiring the lock. Returns zero * 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); unsigned long flags; int stop; @@ -1009,7 +1038,7 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort) while (1) { set_current_state(TASK_UNINTERRUPTIBLE); stop = abort ? atomic_read(abort) : 0; - if (stop || !host->claimed || host->claimer == current) + if (stop || !host->claimed || mmc_ctx_matches(host, ctx, task)) break; spin_unlock_irqrestore(&host->lock, flags); schedule(); @@ -1018,7 +1047,7 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort) set_current_state(TASK_RUNNING); if (!stop) { host->claimed = 1; - host->claimer = current; + mmc_ctx_set_claimer(host, ctx, task); host->claim_cnt += 1; if (host->claim_cnt == 1) pm = true; @@ -1053,6 +1082,7 @@ void mmc_release_host(struct mmc_host *host) spin_unlock_irqrestore(&host->lock, flags); } else { host->claimed = 0; + host->claimer->task = NULL; host->claimer = NULL; spin_unlock_irqrestore(&host->lock, flags); wake_up(&host->wq); @@ -1066,10 +1096,10 @@ EXPORT_SYMBOL(mmc_release_host); * This is a helper function, which fetches a runtime pm reference for the * 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); - mmc_claim_host(card->host); + __mmc_claim_host(card->host, ctx, NULL); } EXPORT_SYMBOL(mmc_get_card); @@ -1077,9 +1107,13 @@ EXPORT_SYMBOL(mmc_get_card); * This is a helper function, which releases the host and drops the runtime * 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_put_autosuspend(&card->dev); } diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 90ce8f2a9343..ba5a8fea0dc2 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -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, 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_get_card(struct mmc_card *card); -void mmc_put_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, struct mmc_ctx *ctx); /** * 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) { - __mmc_claim_host(host, NULL); + __mmc_claim_host(host, NULL, NULL); } int mmc_cqe_start_req(struct mmc_host *host, struct mmc_request *mrq); diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index c97311174d31..83a4e64112fc 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -59,7 +59,7 @@ static int mmc_ios_show(struct seq_file *s, void *data) const char *str; if (host->card) - mmc_get_card(host->card); + mmc_get_card(host->card, NULL); seq_printf(s, "clock:\t\t%u Hz\n", ios->clock); if (host->actual_clock) @@ -198,7 +198,7 @@ static int mmc_ios_show(struct seq_file *s, void *data) seq_printf(s, "driver type:\t%u (%s)\n", ios->drv_type, str); if (host->card) - mmc_put_card(host->card); + mmc_put_card(host->card, NULL); return 0; } @@ -220,10 +220,10 @@ static int mmc_clock_opt_get(void *data, u64 *val) struct mmc_host *host = data; if (host->card) - mmc_get_card(host->card); + mmc_get_card(host->card, NULL); *val = host->ios.clock; if (host->card) - mmc_put_card(host->card); + mmc_put_card(host->card, NULL); return 0; } diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index a243eba3071a..98819a0f0934 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1946,14 +1946,14 @@ static void mmc_detect(struct mmc_host *host) { int err; - mmc_get_card(host->card); + mmc_get_card(host->card, NULL); /* * Just check if our card has been removed. */ err = _mmc_detect_card_removed(host); - mmc_put_card(host->card); + mmc_put_card(host->card, NULL); if (err) { mmc_remove(host); diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index cf640239fcdd..50786e784199 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1063,14 +1063,14 @@ static void mmc_sd_detect(struct mmc_host *host) { int err; - mmc_get_card(host->card); + mmc_get_card(host->card, NULL); /* * Just check if our card has been removed. */ err = _mmc_detect_card_removed(host); - mmc_put_card(host->card); + mmc_put_card(host->card, NULL); if (err) { mmc_sd_remove(host); diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index c771843e4c15..7a2eaf8410a3 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c @@ -155,7 +155,8 @@ static int sdio_irq_thread(void *_host) * holding of the host lock does not cover too much work * 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) break; ret = process_sdio_pending_irqs(host); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index a25afef241a8..56fb075f7b85 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -255,6 +255,10 @@ struct mmc_supply { struct regulator *vqmmc; /* Optional Vccq supply */ }; +struct mmc_ctx { + struct task_struct *task; +}; + struct mmc_host { struct device *parent; struct device class_dev; @@ -390,8 +394,9 @@ struct mmc_host { struct mmc_card *card; /* device attached to this host */ 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 */ + struct mmc_ctx default_ctx; /* default context */ struct delayed_work detect; int detect_change; /* card detect flag */ |