mtd/drivers/mtd/nand nand_base.c,1.117,1.118

gleixner at infradead.org gleixner at infradead.org
Thu Sep 23 19:34:59 EDT 2004


Update of /home/cvs/mtd/drivers/mtd/nand
In directory phoenix.infradead.org:/tmp/cvs-serv19935

Modified Files:
	nand_base.c 
Log Message:
add support for hardware controllers shared by multiple independend devices

Index: nand_base.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/nand/nand_base.c,v
retrieving revision 1.117
retrieving revision 1.118
diff -u -r1.117 -r1.118
--- nand_base.c	23 Sep 2004 22:44:21 -0000	1.117
+++ nand_base.c	23 Sep 2004 23:34:56 -0000	1.118
@@ -24,6 +24,10 @@
  *  
  *  05-19-2004  tglx: Basic support for Renesas AG-AND chips
  *
+ *  09-24-2004  tglx: add support for hardware controllers (e.g. ECC) shared
+ *		among multiple independend devices. Suggestions and initial patch
+ *		from Ben Dooks <ben-mtd at fluff.org>
+ *
  * Credits:
  *	David Woodhouse for adding multichip support  
  *	
@@ -131,25 +135,31 @@
 #define nand_verify_pages(...) (0)
 #endif
 		
-static void nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new_state);
+static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state);
 
 /**
- * nand_release_chip - [GENERIC] release chip
+ * nand_release_device - [GENERIC] release chip
  * @mtd:	MTD device structure
  * 
  * Deselect, release chip lock and wake up anyone waiting on the device 
  */
-static void nand_release_chip (struct mtd_info *mtd)
+static void nand_release_device (struct mtd_info *mtd)
 {
 	struct nand_chip *this = mtd->priv;
 
 	/* De-select the NAND device */
 	this->select_chip(mtd, -1);
+	/* Do we have a hardware controller ? */
+	if (this->controller) {
+		spin_lock(&this->controller.lock);
+		active = NULL;
+		spin_unlock(&this->controller.lock);
+	}
 	/* Release the chip */
-	spin_lock_bh (&this->chip_lock);
+	spin_lock (&this->chip_lock);
 	this->state = FL_READY;
 	wake_up (&this->wq);
-	spin_unlock_bh (&this->chip_lock);
+	spin_unlock (&this->chip_lock);
 }
 
 /**
@@ -388,7 +398,7 @@
 		chipnr = (int)(ofs >> this->chip_shift);
 
 		/* Grab the lock and see if the device is available */
-		nand_get_chip (this, mtd, FL_READING);
+		nand_get_device (this, mtd, FL_READING);
 
 		/* Select the NAND device */
 		this->select_chip(mtd, chipnr);
@@ -410,7 +420,7 @@
 		
 	if (getchip) {
 		/* Deselect and wake up anyone waiting on the device */
-		nand_release_chip(mtd);
+		nand_release_device(mtd);
 	}	
 	
 	return res;
@@ -689,15 +699,16 @@
 }
 
 /**
- * nand_get_chip - [GENERIC] Get chip for selected access
+ * nand_get_device - [GENERIC] Get chip for selected access
  * @this:	the nand chip descriptor
  * @mtd:	MTD device structure
  * @new_state:	the state which is requested 
  *
  * Get the device and lock it for exclusive access
  */
-static void nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new_state)
+static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state)
 {
+	struct nand_chip *active = this;
 
 	DECLARE_WAITQUEUE (wait, current);
 
@@ -705,19 +716,29 @@
 	 * Grab the lock and see if the device is available 
 	*/
 retry:
-	spin_lock_bh (&this->chip_lock);
-
-	if (this->state == FL_READY) {
-		this->state = new_state;
-		spin_unlock_bh (&this->chip_lock);
-		return;
+	/* 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 (&this->wq, &wait);
-	spin_unlock_bh (&this->chip_lock);
+	add_wait_queue (&active->wq, &wait);
+	spin_unlock (&active->chip_lock);
 	schedule ();
-	remove_wait_queue (&this->wq, &wait);
+	remove_wait_queue (&active->wq, &wait);
 	goto retry;
 }
 
@@ -1045,7 +1066,7 @@
 	}
 
 	/* Grab the lock and see if the device is available */
-	nand_get_chip (this, mtd ,FL_READING);
+	nand_get_device (this, mtd ,FL_READING);
 
 	/* use userspace supplied oobinfo, if zero */
 	if (oobsel == NULL)
@@ -1275,7 +1296,7 @@
 	}
 
 	/* Deselect and wake up anyone waiting on the device */
-	nand_release_chip(mtd);
+	nand_release_device(mtd);
 
 	/*
 	 * Return success, if no ECC failures, else -EBADMSG
@@ -1322,7 +1343,7 @@
 	}
 
 	/* Grab the lock and see if the device is available */
-	nand_get_chip (this, mtd , FL_READING);
+	nand_get_device (this, mtd , FL_READING);
 
 	/* Select the NAND device */
 	this->select_chip(mtd, chipnr);
@@ -1373,7 +1394,7 @@
 	}
 
 	/* Deselect and wake up anyone waiting on the device */
-	nand_release_chip(mtd);
+	nand_release_device(mtd);
 
 	/* Return happy */
 	*retlen = len;
@@ -1407,7 +1428,7 @@
 	}
 
 	/* Grab the lock and see if the device is available */
-	nand_get_chip (this, mtd , FL_READING);
+	nand_get_device (this, mtd , FL_READING);
 
 	this->select_chip (mtd, chip);
 	
@@ -1436,7 +1457,7 @@
 	}
 
 	/* Deselect and wake up anyone waiting on the device */
-	nand_release_chip(mtd);
+	nand_release_device(mtd);
 	return 0;
 }
 
@@ -1558,7 +1579,7 @@
 	}
 
 	/* Grab the lock and see if the device is available */
-	nand_get_chip (this, mtd, FL_WRITING);
+	nand_get_device (this, mtd, FL_WRITING);
 
 	/* Calculate chipnr */
 	chipnr = (int)(to >> this->chip_shift);
@@ -1663,7 +1684,7 @@
 
 out:
 	/* Deselect and wake up anyone waiting on the device */
-	nand_release_chip(mtd);
+	nand_release_device(mtd);
 
 	return ret;
 }
@@ -1703,7 +1724,7 @@
 	}
 
 	/* Grab the lock and see if the device is available */
-	nand_get_chip (this, mtd, FL_WRITING);
+	nand_get_device (this, mtd, FL_WRITING);
 
 	/* Select the NAND device */
 	this->select_chip(mtd, chipnr);
@@ -1765,7 +1786,7 @@
 	ret = 0;
 out:
 	/* Deselect and wake up anyone waiting on the device */
-	nand_release_chip(mtd);
+	nand_release_device(mtd);
 
 	return ret;
 }
@@ -1832,7 +1853,7 @@
 	}
 
 	/* Grab the lock and see if the device is available */
-	nand_get_chip (this, mtd, FL_WRITING);
+	nand_get_device (this, mtd, FL_WRITING);
 
 	/* Get the current chip-nr */
 	chipnr = (int) (to >> this->chip_shift);
@@ -1946,7 +1967,7 @@
 	ret = 0;
 out:
 	/* Deselect and wake up anyone waiting on the device */
-	nand_release_chip(mtd);
+	nand_release_device(mtd);
 
 	*retlen = written;
 	return ret;
@@ -2035,7 +2056,7 @@
 	instr->fail_addr = 0xffffffff;
 
 	/* Grab the lock and see if the device is available */
-	nand_get_chip (this, mtd, FL_ERASING);
+	nand_get_device (this, mtd, FL_ERASING);
 
 	/* Shift to get first page */
 	page = (int) (instr->addr >> this->page_shift);
@@ -2106,7 +2127,7 @@
 		mtd_erase_callback(instr);
 
 	/* Deselect and wake up anyone waiting on the device */
-	nand_release_chip(mtd);
+	nand_release_device(mtd);
 
 	/* Return more or less happy */
 	return ret;
@@ -2121,43 +2142,13 @@
 static void nand_sync (struct mtd_info *mtd)
 {
 	struct nand_chip *this = mtd->priv;
-	DECLARE_WAITQUEUE (wait, current);
 
 	DEBUG (MTD_DEBUG_LEVEL3, "nand_sync: called\n");
 
-retry:
-	/* Grab the spinlock */
-	spin_lock_bh (&this->chip_lock);
-
-	/* See what's going on */
-	switch (this->state) {
-	case FL_READY:
-	case FL_SYNCING:
-		this->state = FL_SYNCING;
-		spin_unlock_bh (&this->chip_lock);
-		break;
-
-	default:
-		/* Not an idle state */
-		add_wait_queue (&this->wq, &wait);
-		spin_unlock_bh (&this->chip_lock);
-		schedule ();
-
-		remove_wait_queue (&this->wq, &wait);
-		goto retry;
-	}
-
-	/* Lock the device */
-	spin_lock_bh (&this->chip_lock);
-
-	/* Set the device to be ready again */
-	if (this->state == FL_SYNCING) {
-		this->state = FL_READY;
-		wake_up (&this->wq);
-	}
-
-	/* Unlock the device */
-	spin_unlock_bh (&this->chip_lock);
+	/* Grab the lock and see if the device is available */
+	nand_get_device (this, mtd, FL_SYNCING);
+	/* Release it and go back */
+	nand_release_device (mtd);
 }
 
 





More information about the linux-mtd-cvs mailing list