From: Adrian Hunter <adrian.hunter@xxxxxxxxx> This change allows the MMC host to be claimed in situations where the host may or may not have already been claimed. Also 'mmc_try_claim_host()' is now exported. Signed-off-by: Adrian Hunter <adrian.hunter@xxxxxxxxx> Acked-by: Matt Fleming <matt@xxxxxxxxxxxxxxxxx> Cc: Ian Molton <ian@xxxxxxxxxxxxxx> Cc: "Roberto A. Foglietta" <roberto.foglietta@xxxxxxxxx> Cc: Jarkko Lavinen <jarkko.lavinen@xxxxxxxxx> Cc: Denis Karpov <ext-denis.2.karpov@xxxxxxxxx> Cc: Pierre Ossman <pierre@xxxxxxxxx> Cc: Philip Langdale <philipl@xxxxxxxxx> Cc: "Madhusudhan" <madhu.cr@xxxxxx> Cc: <linux-mmc@xxxxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- drivers/mmc/core/core.c | 34 +++++++++++++++++++++++++--------- include/linux/mmc/core.h | 1 + include/linux/mmc/host.h | 2 ++ 3 files changed, 28 insertions(+), 9 deletions(-) diff -puN drivers/mmc/core/core.c~mmc-allow-host-claim-release-nesting drivers/mmc/core/core.c --- a/drivers/mmc/core/core.c~mmc-allow-host-claim-release-nesting +++ a/drivers/mmc/core/core.c @@ -461,16 +461,18 @@ int __mmc_claim_host(struct mmc_host *ho while (1) { set_current_state(TASK_UNINTERRUPTIBLE); stop = abort ? atomic_read(abort) : 0; - if (stop || !host->claimed) + if (stop || !host->claimed || host->claimer == current) break; spin_unlock_irqrestore(&host->lock, flags); schedule(); spin_lock_irqsave(&host->lock, flags); } set_current_state(TASK_RUNNING); - if (!stop) + if (!stop) { host->claimed = 1; - else + host->claimer = current; + host->claim_cnt += 1; + } else wake_up(&host->wq); spin_unlock_irqrestore(&host->lock, flags); remove_wait_queue(&host->wq, &wait); @@ -481,29 +483,43 @@ int __mmc_claim_host(struct mmc_host *ho EXPORT_SYMBOL(__mmc_claim_host); -static int mmc_try_claim_host(struct mmc_host *host) +/** + * mmc_try_claim_host - try exclusively to claim a host + * @host: mmc host to claim + * + * Returns %1 if the host is claimed, %0 otherwise. + */ +int mmc_try_claim_host(struct mmc_host *host) { int claimed_host = 0; unsigned long flags; spin_lock_irqsave(&host->lock, flags); - if (!host->claimed) { + if (!host->claimed || host->claimer == current) { host->claimed = 1; + host->claimer = current; + host->claim_cnt += 1; claimed_host = 1; } spin_unlock_irqrestore(&host->lock, flags); return claimed_host; } +EXPORT_SYMBOL(mmc_try_claim_host); static void mmc_do_release_host(struct mmc_host *host) { unsigned long flags; spin_lock_irqsave(&host->lock, flags); - host->claimed = 0; - spin_unlock_irqrestore(&host->lock, flags); - - wake_up(&host->wq); + if (--host->claim_cnt) { + /* Release for nested claim */ + spin_unlock_irqrestore(&host->lock, flags); + } else { + host->claimed = 0; + host->claimer = NULL; + spin_unlock_irqrestore(&host->lock, flags); + wake_up(&host->wq); + } } void mmc_host_deeper_disable(struct work_struct *work) diff -puN include/linux/mmc/core.h~mmc-allow-host-claim-release-nesting include/linux/mmc/core.h --- a/include/linux/mmc/core.h~mmc-allow-host-claim-release-nesting +++ a/include/linux/mmc/core.h @@ -139,6 +139,7 @@ extern unsigned int mmc_align_data_size( extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort); extern void mmc_release_host(struct mmc_host *host); +extern int mmc_try_claim_host(struct mmc_host *host); /** * mmc_claim_host - exclusively claim a host diff -puN include/linux/mmc/host.h~mmc-allow-host-claim-release-nesting include/linux/mmc/host.h --- a/include/linux/mmc/host.h~mmc-allow-host-claim-release-nesting +++ a/include/linux/mmc/host.h @@ -182,6 +182,8 @@ 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 */ + int claim_cnt; /* "claim" nesting count */ struct delayed_work detect; _ -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html