Commit 319a3f14 authored by Adrian Hunter's avatar Adrian Hunter Committed by Linus Torvalds

mmc: allow host claim / release nesting

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: default avatarAdrian Hunter <adrian.hunter@nokia.com>
Acked-by: default avatarMatt Fleming <matt@console-pimps.org>
Cc: Ian Molton <ian@mnementh.co.uk>
Cc: "Roberto A. Foglietta" <roberto.foglietta@gmail.com>
Cc: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Cc: Denis Karpov <ext-denis.2.karpov@nokia.com>
Cc: Pierre Ossman <pierre@ossman.eu>
Cc: Philip Langdale <philipl@overt.org>
Cc: "Madhusudhan" <madhu.cr@ti.com>
Cc: <linux-mmc@vger.kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 8ea926b2
...@@ -461,16 +461,18 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort) ...@@ -461,16 +461,18 @@ 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) if (stop || !host->claimed || host->claimer == current)
break; break;
spin_unlock_irqrestore(&host->lock, flags); spin_unlock_irqrestore(&host->lock, flags);
schedule(); schedule();
spin_lock_irqsave(&host->lock, flags); spin_lock_irqsave(&host->lock, flags);
} }
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
if (!stop) if (!stop) {
host->claimed = 1; host->claimed = 1;
else host->claimer = current;
host->claim_cnt += 1;
} else
wake_up(&host->wq); wake_up(&host->wq);
spin_unlock_irqrestore(&host->lock, flags); spin_unlock_irqrestore(&host->lock, flags);
remove_wait_queue(&host->wq, &wait); remove_wait_queue(&host->wq, &wait);
...@@ -481,29 +483,43 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort) ...@@ -481,29 +483,43 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
EXPORT_SYMBOL(__mmc_claim_host); 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; int claimed_host = 0;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&host->lock, flags); spin_lock_irqsave(&host->lock, flags);
if (!host->claimed) { if (!host->claimed || host->claimer == current) {
host->claimed = 1; host->claimed = 1;
host->claimer = current;
host->claim_cnt += 1;
claimed_host = 1; claimed_host = 1;
} }
spin_unlock_irqrestore(&host->lock, flags); spin_unlock_irqrestore(&host->lock, flags);
return claimed_host; return claimed_host;
} }
EXPORT_SYMBOL(mmc_try_claim_host);
static void mmc_do_release_host(struct mmc_host *host) static void mmc_do_release_host(struct mmc_host *host)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&host->lock, flags); spin_lock_irqsave(&host->lock, flags);
host->claimed = 0; if (--host->claim_cnt) {
spin_unlock_irqrestore(&host->lock, flags); /* Release for nested claim */
spin_unlock_irqrestore(&host->lock, flags);
wake_up(&host->wq); } 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) void mmc_host_deeper_disable(struct work_struct *work)
......
...@@ -139,6 +139,7 @@ extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int); ...@@ -139,6 +139,7 @@ extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int);
extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort); extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort);
extern void mmc_release_host(struct mmc_host *host); 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 * mmc_claim_host - exclusively claim a host
......
...@@ -182,6 +182,8 @@ struct mmc_host { ...@@ -182,6 +182,8 @@ 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 */
int claim_cnt; /* "claim" nesting count */
struct delayed_work detect; struct delayed_work detect;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment