mtd/drivers/mtd ssfdc.c,1.1,1.2

Simon Haynes baydel at infradead.org
Wed Aug 25 06:06:32 EDT 2004


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

Modified Files:
	ssfdc.c 
Log Message:
Fixed problems caused by calling mtd->read and not mtd->read_ecc

Index: ssfdc.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/ssfdc.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ssfdc.c	11 Aug 2004 09:57:08 -0000	1.1
+++ ssfdc.c	25 Aug 2004 10:06:29 -0000	1.2
@@ -57,6 +57,18 @@
  * but it should give an indication of what I think is required. Maybe there is
  * something it mtd that can help
  *
+ * 17th August 2004 MHB
+ *
+ * Following updating CVS I noticed some single bit data corruption. I believe
+ * that this was down to the fact that I was using mtd->read instead of mtd->read_ecc
+ * and that mtd->read was applying it's own error corretion from the wrong ecc bytes
+ * I have now corrected this.
+ *
+ * During this time I noticed that while in allocate new I only seem to look for blocks
+ * in 1 zone. So this limits the partition size to 16MB with all the other SMC size
+ * restrictions
+
+
 */
 
 #include <linux/config.h>
@@ -146,6 +158,7 @@
 static unsigned char ssfdc_ffoob_buf[OOB_SIZE * SECTORS_PER_BLOCK];
 static unsigned char ssfdc_oob_buf[OOB_SIZE * SECTORS_PER_BLOCK];
 
+
 static struct nand_oobinfo ssfdc_ffoob_info = {
 	.useecc = 0,
 };
@@ -660,11 +673,27 @@
 
 		if(physical >= 0) {
 			if(ssfdc_cached != physical) {
-	   			pt_smcpart->mtd->read(pt_smcpart->mtd, physical, SMC_BLOCK_SIZE, &retlen, ssfdc_scratch);
+	   			pt_smcpart->mtd->read_ecc(pt_smcpart->mtd, physical, SMC_BLOCK_SIZE, &retlen, ssfdc_scratch,
+					 ssfdc_oob_buf, &ssfdc_ffoob_info);
 				if(retlen != SMC_BLOCK_SIZE) {
 					printk(KERN_WARNING "ssfdc_write : failed to read physical\n");
 					return -ENXIO;
 				}
+
+				for(sc=0; sc<SECTORS_PER_BLOCK; sc++) {
+	   				pt_smcpart->mtd->read_oob(pt_smcpart->mtd, physical + (sc * SECTOR_SIZE), sizeof(ssfdc_buffer), &retlen, ssfdc_buffer);
+					if(retlen != sizeof(ssfdc_buffer)) {
+						printk(KERN_WARNING "ssfdc_write : failed to read physical oob\n");
+						return -ENXIO;
+					}
+
+					nand_calculate_ecc (pt_smcpart->mtd, &ssfdc_scratch[sc * SECTOR_SIZE], &ecc_calc[0]);
+					nand_calculate_ecc (pt_smcpart->mtd, &ssfdc_scratch[(sc * SECTOR_SIZE) + 256], &ecc_calc[3]);
+					for(i=0; i<6; i++) ecc_code[i] = ssfdc_buffer[ssfdc_ecc[i]];
+					nand_correct_data(pt_smcpart->mtd, &ssfdc_scratch[sc * SECTOR_SIZE], &ecc_code[0], &ecc_calc[0]);
+					nand_correct_data(pt_smcpart->mtd, &ssfdc_scratch[(sc * SECTOR_SIZE) + 256], &ecc_code[3], &ecc_calc[3]);
+				}
+
 			}
 			
 			for(sc=0; sc<SECTORS_PER_BLOCK; sc++) {
@@ -672,7 +701,6 @@
 					PDEBUG("offset %d, sector %d\n", offset, sc);
 					continue;
 				}
-
    				pt_smcpart->mtd->read_oob(pt_smcpart->mtd, physical + (sc * SECTOR_SIZE), sizeof(ssfdc_buffer), &retlen, ssfdc_buffer);
 				if(retlen != sizeof(ssfdc_buffer)) {
 					printk(KERN_WARNING "ssfdc_write : failed to read physical oob\n");
@@ -684,8 +712,7 @@
 				for(i=0; i<6; i++) ecc_code[i] = ssfdc_buffer[ssfdc_ecc[i]];
 				nand_correct_data(pt_smcpart->mtd, &ssfdc_scratch[sc * SECTOR_SIZE], &ecc_code[0], &ecc_calc[0]);
 				nand_correct_data(pt_smcpart->mtd, &ssfdc_scratch[(sc * SECTOR_SIZE) + 256], &ecc_code[3], &ecc_calc[3]);
-
-
+				
 				/* find out if the block is being used */
 
 
@@ -709,35 +736,25 @@
 						return -ENXIO;
 					}
 
-/*
-
-                    pt_smcpart->mtd->write_oob(pt_smcpart->mtd, physical + (sc * SECTOR_SIZE),
-                                        OOB_SIZE,&retlen, ssfdc_buffer);
-					if(retlen != OOB_SIZE) {
-						printk(KERN_WARNING "ssfdc_write : failed to write physical oob blank\n");
-						return -ENXIO;
-					}
-*/
                     ptr_done += SECTOR_SIZE;
 					if(ptr_done >= size) break;
 				}
 				else {
 					new = ssfdc_allocate_new(pt_smcpart, zone);
 					/* erase the old block */
-		            		*(pt_physical + ((physical % ZONE_SIZE) / SMC_BLOCK_SIZE)) = 0xFFFFFFFF;
+		            *(pt_physical + ((physical % ZONE_SIZE) / SMC_BLOCK_SIZE)) = 0xFFFFFFFF;
 
 					PDEBUG("ssfdc_write : physical 0x%x + 0x%x = 0x%x\n",
 						(unsigned int)pt_physical, ((physical % ZONE_SIZE) / SMC_BLOCK_SIZE), 0xFFFFFFFF);
 					do_erase = TRUE;
-//					ssfdc_erase(pt_smcpart, physical);
 					PDEBUG("ssfdc_write : zone %d, block %d, sector %d, lbn %d, written, physical 0x%x, new 0x%x\n",
 						zone, block, sc, sector, physical, new);
 					break;
 				}
 			}
-			ssfdc_cached = 0xFFFFFFFF;
 		}
 		else {
+			ssfdc_cached = 0xFFFFFFFF;
 			memset(ssfdc_scratch, 0xFF, sizeof(ssfdc_scratch));
 			new = ssfdc_allocate_new(pt_smcpart, zone);
 			PDEBUG("ssfdc_write : zone %d, block %d, lbn %d, physical 0x%x, unallocated, new 0x%x\n",
@@ -761,22 +778,15 @@
                 		ssfdc_buffer[7] = ssfdc_buffer[12] = i & 0xFF;
                 		ssfdc_buffer[6] = ssfdc_buffer[11] = (i & 0xFF00) >> 0x08;
                 memcpy(&ssfdc_oob_buf[sc * OOB_SIZE], ssfdc_buffer, OOB_SIZE);
-/*
-                pt_smcpart->mtd->write_oob(pt_smcpart->mtd, new + (sc * SECTOR_SIZE), sizeof(ssfdc_buffer), &retlen, ssfdc_buffer);
-				if(retlen != OOB_SIZE) {
-					printk(KERN_WARNING "ssfdc_write : failed to write physical oob\n");
-					return -ENXIO;
-				}
-*/
 			}
 
+
 	   		pt_smcpart->mtd->write_ecc(pt_smcpart->mtd, new, SMC_BLOCK_SIZE, &retlen, ssfdc_scratch,
                         ssfdc_oob_buf, &ssfdc_ffoob_info);
 			if(retlen != SMC_BLOCK_SIZE) {
-				printk(KERN_WARNING "ssfdc_write : failed to write physical 0x%x, returned 0x%x\n", new, retlen);
+				printk(KERN_WARNING "ssfdc_write : failed to write block, physical 0x%x, returned 0x%x\n", new, retlen);
 				return -ENXIO;
 			}
-
 			/* change the mapping table to reflect the new block placement */
 
 			*(pt_logical + block) = (new % ZONE_SIZE) / SMC_BLOCK_SIZE;
@@ -789,7 +799,7 @@
 
 
 			ssfdc_cached = new;
-   	    	}
+   	    }
 
 
 		ptr += size;
@@ -830,7 +840,7 @@
 
 
 	while (new != pt_smcpart->last_written[zone]) {
-        	block = new % BLOCKS_PER_ZONE;
+       	block = new % BLOCKS_PER_ZONE;
 		pt_physical = pt_smcpart->zone + (zone * 2048) + 1024 + block;
 		physical = (zone * ZONE_SIZE) + (block * SMC_BLOCK_SIZE);
 
@@ -910,7 +920,8 @@
 		physical = ssfdc_physical(pt_smcpart, zone, block);
 		if(physical >=  0) {
 			if(ssfdc_cached != physical) {
-           		pt_smcpart->mtd->read(pt_smcpart->mtd, physical, SMC_BLOCK_SIZE, &retlen, ssfdc_scratch);
+           		pt_smcpart->mtd->read_ecc(pt_smcpart->mtd, physical, SMC_BLOCK_SIZE, &retlen, ssfdc_scratch,
+													 ssfdc_oob_buf, &ssfdc_ffoob_info);
 				if(retlen != SMC_BLOCK_SIZE) {
 					printk(KERN_WARNING "ssfdc_read : failed to read physical\n");
 					return -ENXIO;
@@ -993,7 +1004,8 @@
 
 	down(&ssfdc_semaphore);
 
-	pt_smcpart->mtd->read(pt_smcpart->mtd, offset, SMC_BLOCK_SIZE, &retlen, junk);
+	pt_smcpart->mtd->read_ecc(pt_smcpart->mtd, offset, SMC_BLOCK_SIZE, &retlen, junk,
+							 ssfdc_oob_buf, &ssfdc_ffoob_info);
 	if(retlen != SMC_BLOCK_SIZE) {
            	printk(KERN_WARNING "ssfdc_erase : offset 0x%x, read returned length %d\n", offset, retlen);
 		goto end;





More information about the linux-mtd-cvs mailing list