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: Adrian Hunter <adrian.hunter@nokia.com> Acked-by: Matt 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: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
8ea926b22e
commit
319a3f1429
3 changed files with 28 additions and 9 deletions
|
@ -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)
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
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 {
|
||||||
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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue