Merge master.kernel.org:/pub/scm/linux/kernel/git/dtor/input
[pandora-kernel.git] / drivers / mtd / nand / nand_base.c
index f1db0bf..eee5115 100644 (file)
@@ -59,7 +59,7 @@
  *     The AG-AND chips have nice features for speed improvement,
  *     which are not supported yet. Read / program 4 pages in one go.
  *
- * $Id: nand_base.c,v 1.143 2005/05/19 16:10:22 gleixner Exp $
+ * $Id: nand_base.c,v 1.147 2005/07/15 07:18:06 gleixner Exp $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -167,17 +167,21 @@ static void nand_release_device (struct mtd_info *mtd)
 
        /* De-select the NAND device */
        this->select_chip(mtd, -1);
-       /* Do we have a hardware controller ? */
+
        if (this->controller) {
+               /* Release the controller and the chip */
                spin_lock(&this->controller->lock);
                this->controller->active = NULL;
+               this->state = FL_READY;
+               wake_up(&this->controller->wq);
                spin_unlock(&this->controller->lock);
+       } else {
+               /* Release the chip */
+               spin_lock(&this->chip_lock);
+               this->state = FL_READY;
+               wake_up(&this->wq);
+               spin_unlock(&this->chip_lock);
        }
-       /* Release the chip */
-       spin_lock (&this->chip_lock);
-       this->state = FL_READY;
-       wake_up (&this->wq);
-       spin_unlock (&this->chip_lock);
 }
 
 /**
@@ -753,37 +757,34 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column,
  */
 static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state)
 {
-       struct nand_chip *active = this;
-
+       struct nand_chip *active;
+       spinlock_t *lock;
+       wait_queue_head_t *wq;
        DECLARE_WAITQUEUE (wait, current);
 
-       /* 
-        * Grab the lock and see if the device is available 
-       */
+       lock = (this->controller) ? &this->controller->lock : &this->chip_lock;
+       wq = (this->controller) ? &this->controller->wq : &this->wq;
 retry:
+       active = this;
+       spin_lock(lock);
+
        /* Hardware controller shared among independend devices */
        if (this->controller) {
-               spin_lock (&this->controller->lock);
                if (this->controller->active)
                        active = this->controller->active;
                else
                        this->controller->active = this;
-               spin_unlock (&this->controller->lock);
        }
-       
-       if (active == this) {
-               spin_lock (&this->chip_lock);
-               if (this->state == FL_READY) {
-                       this->state = new_state;
-                       spin_unlock (&this->chip_lock);
-                       return;
-               }
-       }       
-       set_current_state (TASK_UNINTERRUPTIBLE);
-       add_wait_queue (&active->wq, &wait);
-       spin_unlock (&active->chip_lock);
-       schedule ();
-       remove_wait_queue (&active->wq, &wait);
+       if (active == this && this->state == FL_READY) {
+               this->state = new_state;
+               spin_unlock(lock);
+               return;
+       }
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       add_wait_queue(wq, &wait);
+       spin_unlock(lock);
+       schedule();
+       remove_wait_queue(wq, &wait);
        goto retry;
 }
 
@@ -1408,16 +1409,6 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t
                thislen = min_t(int, thislen, len);
                this->read_buf(mtd, &buf[i], thislen);
                i += thislen;
-               
-               /* Apply delay or wait for ready/busy pin 
-                * Do this before the AUTOINCR check, so no problems
-                * arise if a chip which does auto increment
-                * is marked as NOAUTOINCR by the board driver.
-               */
-               if (!this->dev_ready) 
-                       udelay (this->chip_delay);
-               else
-                       nand_wait_ready(mtd);
 
                /* Read more ? */
                if (i < len) {
@@ -1431,6 +1422,16 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t
                                this->select_chip(mtd, chipnr);
                        }
                                
+                       /* Apply delay or wait for ready/busy pin 
+                        * Do this before the AUTOINCR check, so no problems
+                        * arise if a chip which does auto increment
+                        * is marked as NOAUTOINCR by the board driver.
+                        */
+                       if (!this->dev_ready) 
+                               udelay (this->chip_delay);
+                       else
+                               nand_wait_ready(mtd);
+
                        /* Check, if the chip supports auto page increment 
                         * or if we have hit a block boundary. 
                        */ 
@@ -2685,8 +2686,8 @@ void nand_release (struct mtd_info *mtd)
                kfree (this->data_buf);
 }
 
-EXPORT_SYMBOL (nand_scan);
-EXPORT_SYMBOL (nand_release);
+EXPORT_SYMBOL_GPL (nand_scan);
+EXPORT_SYMBOL_GPL (nand_release);
 
 MODULE_LICENSE ("GPL");
 MODULE_AUTHOR ("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");