aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2017-05-11 13:45:55 +0200
committerUlf Hansson <ulf.hansson@linaro.org>2017-09-07 13:59:56 +0200
commitaf537c0c10a4435868726982d20bcc2defdfad2c (patch)
treef3f84702e8d282651b308c83e8781389efb024d0
parent94a490360f96fad845dfeaa282141a3b73c3c186 (diff)
mmc: core: Allow mmc block device to re-claim the hostref_mmc_claim_host
The current mmc block device implementation is tricky when it comes to claim and release of the host, while processing I/O requests. In principle we need to claim the host at the first request entering the queue and then we need to release the host, as soon as the queue becomes empty. This complexity relates to the asynchronous request mechanism that the mmc block device driver implements. For the legacy block interface that we currently implements, the above issue can be addressed, as we can find out when the queue really becomes empty. However, to find out whether the queue is empty, isn't really an applicable method when using the new blk-mq interface, as requests are instead pushed to us via the struct struct blk_mq_ops and its function pointers. Being able to support the asynchronous request method using the blk-mq interface, means we have to allow the mmc block device driver to re-claim the host from different tasks/contexts, as we may have > 1 request to operate upon. Therefore, let's extend the mmc_claim_host() API to support reference counting for the mmc block device. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/core/core.c14
-rw-r--r--drivers/mmc/core/core.h7
-rw-r--r--include/linux/mmc/host.h1
3 files changed, 17 insertions, 5 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 060bbafcdfad..70fd0f0cfd31 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -833,12 +833,12 @@ unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz)
EXPORT_SYMBOL(mmc_align_data_size);
/**
- * mmc_claim_host - exclusively claim a host
+ * __mmc_claim_host - exclusively claim a host
* @host: mmc host to claim
*
* Claim a host for a set of operations.
*/
-void mmc_claim_host(struct mmc_host *host)
+void __mmc_claim_host(struct mmc_host *host, bool is_blkdev)
{
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
@@ -850,7 +850,11 @@ void mmc_claim_host(struct mmc_host *host)
spin_lock_irqsave(&host->lock, flags);
while (1) {
set_current_state(TASK_UNINTERRUPTIBLE);
- if (!host->claimed || host->claimer == current)
+ if (!host->claimed)
+ break;
+ if (host->claimer_is_blkdev && is_blkdev)
+ break;
+ if (host->claimer == current)
break;
spin_unlock_irqrestore(&host->lock, flags);
schedule();
@@ -859,6 +863,7 @@ void mmc_claim_host(struct mmc_host *host)
set_current_state(TASK_RUNNING);
host->claimed = 1;
host->claimer = current;
+ host->claimer_is_blkdev = is_blkdev;
host->claim_cnt += 1;
if (host->claim_cnt == 1)
pm = true;
@@ -868,7 +873,7 @@ void mmc_claim_host(struct mmc_host *host)
if (pm)
pm_runtime_get_sync(mmc_dev(host));
}
-EXPORT_SYMBOL(mmc_claim_host);
+EXPORT_SYMBOL(__mmc_claim_host);
/**
* mmc_release_host - release a host
@@ -890,6 +895,7 @@ void mmc_release_host(struct mmc_host *host)
} else {
host->claimed = 0;
host->claimer = NULL;
+ host->claimer_is_blkdev = 0;
spin_unlock_irqrestore(&host->lock, flags);
wake_up(&host->wq);
pm_runtime_mark_last_busy(mmc_dev(host));
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index f24261a500e4..f9f02ffa7b03 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -128,9 +128,14 @@ 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);
-void mmc_claim_host(struct mmc_host *host);
+void __mmc_claim_host(struct mmc_host *host, bool is_blkdev);
void mmc_release_host(struct mmc_host *host);
void mmc_get_card(struct mmc_card *card);
void mmc_put_card(struct mmc_card *card);
+static inline void mmc_claim_host(struct mmc_host *host)
+{
+ __mmc_claim_host(host, 0);
+}
+
#endif
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index c2911f232eac..021ad8bd4297 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -389,6 +389,7 @@ struct mmc_host {
wait_queue_head_t wq;
struct task_struct *claimer; /* task that has host claimed */
+ bool claimer_is_blkdev; /* claimer is blkdev */
int claim_cnt; /* "claim" nesting count */
struct delayed_work detect;