|
@@ -461,16 +461,18 @@ 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)
|
|
|
+ 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 *host, atomic_t *abort)
|
|
|
|
|
|
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)
|