aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/nand_base.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-23 05:37:03 -0400
committerThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-23 05:37:03 -0400
commita36ed2995c56d4f858ecb524a78837473e7115ae (patch)
tree510f31485713ae5be63a20fe29b3809f0fafbbb8 /drivers/mtd/nand/nand_base.c
parent819d6a32c397534c819d3c72a3947b7e7e4bec4b (diff)
[MTD] Simplify NAND locking
Replace the chip lock by a the controller lock. For simple drivers a dummy controller structure is created by the scan code. This simplifies the locking algorithm in nand_get/release_chip(). Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/mtd/nand/nand_base.c')
-rw-r--r--drivers/mtd/nand/nand_base.c81
1 files changed, 43 insertions, 38 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 08dffb7a9389..7933ca273c95 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -172,20 +172,12 @@ static void nand_release_device(struct mtd_info *mtd)
172 /* De-select the NAND device */ 172 /* De-select the NAND device */
173 this->select_chip(mtd, -1); 173 this->select_chip(mtd, -1);
174 174
175 if (this->controller) { 175 /* Release the controller and the chip */
176 /* Release the controller and the chip */ 176 spin_lock(&this->controller->lock);
177 spin_lock(&this->controller->lock); 177 this->controller->active = NULL;
178 this->controller->active = NULL; 178 this->state = FL_READY;
179 this->state = FL_READY; 179 wake_up(&this->controller->wq);
180 wake_up(&this->controller->wq); 180 spin_unlock(&this->controller->lock);
181 spin_unlock(&this->controller->lock);
182 } else {
183 /* Release the chip */
184 spin_lock(&this->chip_lock);
185 this->state = FL_READY;
186 wake_up(&this->wq);
187 spin_unlock(&this->chip_lock);
188 }
189} 181}
190 182
191/** 183/**
@@ -765,25 +757,18 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column,
765 */ 757 */
766static int nand_get_device(struct nand_chip *this, struct mtd_info *mtd, int new_state) 758static int nand_get_device(struct nand_chip *this, struct mtd_info *mtd, int new_state)
767{ 759{
768 struct nand_chip *active; 760 spinlock_t *lock = &this->controller->lock;
769 spinlock_t *lock; 761 wait_queue_head_t *wq = &this->controller->wq;
770 wait_queue_head_t *wq;
771 DECLARE_WAITQUEUE(wait, current); 762 DECLARE_WAITQUEUE(wait, current);
772
773 lock = (this->controller) ? &this->controller->lock : &this->chip_lock;
774 wq = (this->controller) ? &this->controller->wq : &this->wq;
775 retry: 763 retry:
776 active = this;
777 spin_lock(lock); 764 spin_lock(lock);
778 765
779 /* Hardware controller shared among independend devices */ 766 /* Hardware controller shared among independend devices */
780 if (this->controller) { 767 /* Hardware controller shared among independend devices */
781 if (this->controller->active) 768 if (!this->controller->active)
782 active = this->controller->active; 769 this->controller->active = this;
783 else 770
784 this->controller->active = this; 771 if (this->controller->active == this && this->state == FL_READY) {
785 }
786 if (active == this && this->state == FL_READY) {
787 this->state = new_state; 772 this->state = new_state;
788 spin_unlock(lock); 773 spin_unlock(lock);
789 return 0; 774 return 0;
@@ -2312,6 +2297,22 @@ static void nand_resume(struct mtd_info *mtd)
2312 2297
2313} 2298}
2314 2299
2300/*
2301 * Free allocated data structures
2302 */
2303static void nand_free_kmem(struct nand_chip *this)
2304{
2305 /* Buffer allocated by nand_scan ? */
2306 if (this->options & NAND_OOBBUF_ALLOC)
2307 kfree(this->oob_buf);
2308 /* Buffer allocated by nand_scan ? */
2309 if (this->options & NAND_DATABUF_ALLOC)
2310 kfree(this->data_buf);
2311 /* Controller allocated by nand_scan ? */
2312 if (this->options & NAND_CONTROLLER_ALLOC)
2313 kfree(this->controller);
2314}
2315
2315/* module_text_address() isn't exported, and it's mostly a pointless 2316/* module_text_address() isn't exported, and it's mostly a pointless
2316 test if this is a module _anyway_ -- they'd have to try _really_ hard 2317 test if this is a module _anyway_ -- they'd have to try _really_ hard
2317 to call us from in-kernel code if the core NAND support is modular. */ 2318 to call us from in-kernel code if the core NAND support is modular. */
@@ -2522,9 +2523,8 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
2522 len = mtd->oobblock + mtd->oobsize; 2523 len = mtd->oobblock + mtd->oobsize;
2523 this->data_buf = kmalloc(len, GFP_KERNEL); 2524 this->data_buf = kmalloc(len, GFP_KERNEL);
2524 if (!this->data_buf) { 2525 if (!this->data_buf) {
2525 if (this->options & NAND_OOBBUF_ALLOC)
2526 kfree(this->oob_buf);
2527 printk(KERN_ERR "nand_scan(): Cannot allocate data_buf\n"); 2526 printk(KERN_ERR "nand_scan(): Cannot allocate data_buf\n");
2527 nand_free_kmem(this);
2528 return -ENOMEM; 2528 return -ENOMEM;
2529 } 2529 }
2530 this->options |= NAND_DATABUF_ALLOC; 2530 this->options |= NAND_DATABUF_ALLOC;
@@ -2657,8 +2657,17 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
2657 2657
2658 /* Initialize state, waitqueue and spinlock */ 2658 /* Initialize state, waitqueue and spinlock */
2659 this->state = FL_READY; 2659 this->state = FL_READY;
2660 init_waitqueue_head(&this->wq); 2660 if (!this->controller) {
2661 spin_lock_init(&this->chip_lock); 2661 this->controller = kzalloc(sizeof(struct nand_hw_control),
2662 GFP_KERNEL);
2663 if (!this->controller) {
2664 nand_free_kmem(this);
2665 return -ENOMEM;
2666 }
2667 this->options |= NAND_CONTROLLER_ALLOC;
2668 }
2669 init_waitqueue_head(&this->controller->wq);
2670 spin_lock_init(&this->controller->lock);
2662 2671
2663 /* De-select the device */ 2672 /* De-select the device */
2664 this->select_chip(mtd, -1); 2673 this->select_chip(mtd, -1);
@@ -2718,12 +2727,8 @@ void nand_release(struct mtd_info *mtd)
2718 2727
2719 /* Free bad block table memory */ 2728 /* Free bad block table memory */
2720 kfree(this->bbt); 2729 kfree(this->bbt);
2721 /* Buffer allocated by nand_scan ? */ 2730 /* Free buffers */
2722 if (this->options & NAND_OOBBUF_ALLOC) 2731 nand_free_kmem(this);
2723 kfree(this->oob_buf);
2724 /* Buffer allocated by nand_scan ? */
2725 if (this->options & NAND_DATABUF_ALLOC)
2726 kfree(this->data_buf);
2727} 2732}
2728 2733
2729EXPORT_SYMBOL_GPL(nand_scan); 2734EXPORT_SYMBOL_GPL(nand_scan);