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