From: Adrian Hunter <adrian.hun...@nokia.com>

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.hun...@nokia.com>
Acked-by: Matt Fleming <m...@console-pimps.org>
Cc: Ian Molton <i...@mnementh.co.uk>
Cc: "Roberto A. Foglietta" <roberto.foglie...@gmail.com>
Cc: Jarkko Lavinen <jarkko.lavi...@nokia.com>
Cc: Denis Karpov <ext-denis.2.kar...@nokia.com>
Cc: Pierre Ossman <pie...@ossman.eu>
Cc: Philip Langdale <phil...@overt.org>
Cc: "Madhusudhan" <madhu...@ti.com>
Cc: <linux-mmc@vger.kernel.org>
Signed-off-by: Andrew Morton <a...@linux-foundation.org>
---

 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to