mtd/drivers/mtd/chips cfi_cmdset_0001.c,1.141,1.142

Nicolas Pitre nico at infradead.org
Tue Jun 8 17:26:24 EDT 2004


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

Modified Files:
	cfi_cmdset_0001.c 
Log Message:
Support for the multi hw partitions of the Intel L18 flash chips.
The non-partitioned cases should behave just like before.
However I'd like for someone else to look at the added logic for the
partitioned config in case I might have overlooked something.


Index: cfi_cmdset_0001.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/cfi_cmdset_0001.c,v
retrieving revision 1.141
retrieving revision 1.142
diff -u -r1.141 -r1.142
--- cfi_cmdset_0001.c	7 Jun 2004 03:28:59 -0000	1.141
+++ cfi_cmdset_0001.c	8 Jun 2004 21:26:21 -0000	1.142
@@ -81,17 +81,18 @@
 static void cfi_tell_features(struct cfi_pri_intelext *extp)
 {
 	int i;
-	printk("  Feature/Command Support: %4.4X\n", extp->FeatureSupport);
-	printk("     - Chip Erase:         %s\n", extp->FeatureSupport&1?"supported":"unsupported");
-	printk("     - Suspend Erase:      %s\n", extp->FeatureSupport&2?"supported":"unsupported");
-	printk("     - Suspend Program:    %s\n", extp->FeatureSupport&4?"supported":"unsupported");
-	printk("     - Legacy Lock/Unlock: %s\n", extp->FeatureSupport&8?"supported":"unsupported");
-	printk("     - Queued Erase:       %s\n", extp->FeatureSupport&16?"supported":"unsupported");
-	printk("     - Instant block lock: %s\n", extp->FeatureSupport&32?"supported":"unsupported");
-	printk("     - Protection Bits:    %s\n", extp->FeatureSupport&64?"supported":"unsupported");
-	printk("     - Page-mode read:     %s\n", extp->FeatureSupport&128?"supported":"unsupported");
-	printk("     - Synchronous read:   %s\n", extp->FeatureSupport&256?"supported":"unsupported");
-	for (i=9; i<32; i++) {
+	printk("  Feature/Command Support:      %4.4X\n", extp->FeatureSupport);
+	printk("     - Chip Erase:              %s\n", extp->FeatureSupport&1?"supported":"unsupported");
+	printk("     - Suspend Erase:           %s\n", extp->FeatureSupport&2?"supported":"unsupported");
+	printk("     - Suspend Program:         %s\n", extp->FeatureSupport&4?"supported":"unsupported");
+	printk("     - Legacy Lock/Unlock:      %s\n", extp->FeatureSupport&8?"supported":"unsupported");
+	printk("     - Queued Erase:            %s\n", extp->FeatureSupport&16?"supported":"unsupported");
+	printk("     - Instant block lock:      %s\n", extp->FeatureSupport&32?"supported":"unsupported");
+	printk("     - Protection Bits:         %s\n", extp->FeatureSupport&64?"supported":"unsupported");
+	printk("     - Page-mode read:          %s\n", extp->FeatureSupport&128?"supported":"unsupported");
+	printk("     - Synchronous read:        %s\n", extp->FeatureSupport&256?"supported":"unsupported");
+	printk("     - Simultaneous operations: %s\n", extp->FeatureSupport&512?"supported":"unsupported");
+	for (i=10; i<32; i++) {
 		if (extp->FeatureSupport & (1<<i)) 
 			printk("     - Unknown Bit %X:      supported\n", i);
 	}
@@ -215,10 +216,35 @@
 	}
 
 	for (i=0; i< cfi->numchips; i++) {
-		cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
-		cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
-		cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
-		cfi->chips[i].ref_point_counter = 0;
+		struct flchip *chip = &cfi->chips[i];
+		chip->word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
+		chip->buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
+		chip->erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
+		chip->ref_point_counter = 0;
+
+		/*
+		 * Probing of multi-partition flash ships.
+		 * This is extremely crude at the moment and should be
+		 * extracted entirely from the Intel extended query
+		 * data instead. 
+		 */
+		if (cfi->cmdset_priv) {
+			struct cfi_pri_intelext *extp = cfi->cmdset_priv;
+			if (extp->FeatureSupport & (1 << 9)) {
+				/*
+				 * The L18 flash memory array is divided
+				 * into multiple 8-Mbit partitions.
+				 */
+				int nbparts = 1 << (cfi->cfiq->DevSize - 20);
+				chip->partshift = __ffs(cfi->interleave) + 20;
+				chip->parts = kmalloc(nbparts * sizeof(*chip->parts), GFP_KERNEL);
+				if (!chip->parts) {
+					kfree(extp);
+					return NULL;
+				}
+				memset(chip->parts, 0, nbparts * sizeof(*chip->parts));
+			}
+		}
 	}		
 
 	map->fldrv = &cfi_intelext_chipdrv;
@@ -328,27 +354,82 @@
  *  *********** CHIP ACCESS FUNCTIONS ***********
  */
 
-static inline flstate_t get_state(struct flchip *chip, unsigned long adr)
+static flstate_t get_state(struct flchip *chip, unsigned long adr)
+{
+	flstate_t state = chip->state;
+	if (chip->parts) {
+		int part = (adr - chip->start) >> chip->partshift;
+		state = chip->parts[part].state;
+	}
+	return state;
+}
+
+static void set_state(struct flchip *chip, unsigned long adr, flstate_t mode)
 {
-	return chip->state;
+	if (!chip->parts) {
+		chip->state = mode;
+	} else {
+		int part = (adr - chip->start) >> chip->partshift;
+		chip->parts[part].state = mode;
+		/* erasing and writing are global states to the chip */
+		switch (mode) {
+		case FL_ERASING:
+			chip->in_progress_block_addr = adr;
+		case FL_ERASE_SUSPENDING:
+		case FL_ERASE_SUSPENDED:
+		case FL_WRITING:
+		case FL_WRITING_TO_BUFFER:
+		case FL_WRITE_SUSPENDING:
+		case FL_WRITE_SUSPENDED:
+			chip->state = mode;
+		default:
+			chip->state = FL_READY;
+		}
+	}
 }
 
-static inline void set_state(struct flchip *chip, unsigned long adr, flstate_t mode)
+static flstate_t get_oldstate(struct flchip *chip, unsigned long adr)
 {
-	chip->state = mode;
+	flstate_t state = chip->oldstate;
+	if (chip->parts) {
+		int part = (adr - chip->start) >> chip->partshift;
+		state = chip->parts[part].oldstate;
+	}
+	return state;
 }
 
-static inline flstate_t get_oldstate(struct flchip *chip, unsigned long adr)
+static void set_oldstate(struct flchip *chip, unsigned long adr, flstate_t mode)
 {
-	return chip->oldstate;
+	if (!chip->parts) {
+		chip->oldstate = mode;
+	} else {
+		int part = (adr - chip->start) >> chip->partshift;
+		chip->parts[part].oldstate = mode;
+		/* erasing and writing are still global states to the chip */
+		switch (mode) {
+		case FL_ERASING:
+		case FL_ERASE_SUSPENDING:
+		case FL_ERASE_SUSPENDED:
+		case FL_WRITING:
+		case FL_WRITING_TO_BUFFER:
+		case FL_WRITE_SUSPENDING:
+		case FL_WRITE_SUSPENDED:
+			chip->oldstate = mode;
+		default:
+			chip->oldstate = FL_READY;
+		}
+	}
 }
 
-static inline void set_oldstate(struct flchip *chip, unsigned long adr, flstate_t mode)
+static inline int same_partition(struct flchip *chip,
+				 unsigned long addr_a, unsigned long addr_b)
 {
-	chip->oldstate = mode;
+	if (!chip->parts)
+		return 1;
+	return (((addr_a ^ addr_b) >> chip->partshift) == 0);
 }
 
-static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
+static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, flstate_t mode)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -359,6 +440,22 @@
  resettime:
 	timeo = jiffies + HZ;
  retry:
+	if ( !same_partition(chip, adr, chip->in_progress_block_addr) &&
+	     !(chip->state == FL_READY && chip->oldstate == FL_READY) &&
+	      (mode == FL_WRITING || mode == FL_ERASING) ) {
+		/*
+		 * OK. We have contension on the write/erase operations
+		 * which are global to the chip and not per partition.
+		 * So let's fight it over in the partition where the
+		 * write/erase is currently occurring first.
+		 */
+		int ret = get_chip(map, chip, chip->in_progress_block_addr, mode);
+		if (ret)
+			return ret;
+		chip->suspender_block_addr = adr;
+		timeo = jiffies + HZ;
+	}
+
 	switch (get_state(chip, adr)) {
 
 	case FL_STATUS:
@@ -451,6 +548,11 @@
 {
 	struct cfi_private *cfi = map->fldrv_priv;
 
+	if ( !same_partition(chip, adr, chip->in_progress_block_addr) &&
+	      same_partition(chip, adr, chip->suspender_block_addr) &&
+	      chip->oldstate != FL_READY )
+		put_chip(map, chip, chip->in_progress_block_addr);
+
 	switch(get_oldstate(chip, adr)) {
 	case FL_ERASING:
 		/* What if one interleaved chip has finished and the 
@@ -1722,10 +1824,13 @@
 
 static void cfi_intelext_destroy(struct mtd_info *mtd)
 {
+	int i;
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
 	kfree(cfi->cmdset_priv);
 	kfree(cfi->cfiq);
+	for (i = 0; i < cfi->numchips; i++)
+		kfree(cfi->chips[i].parts);
 	kfree(cfi);
 	kfree(mtd->eraseregions);
 }





More information about the linux-mtd-cvs mailing list