Skip to content

Commit

Permalink
[MTD] NAND Replace oobinfo by ecclayout
Browse files Browse the repository at this point in the history
The nand_oobinfo structure is not fitting the newer error correction
demands anymore. Replace it by struct nand_ecclayout and fixup the users
all over the place. Keep the nand_oobinfo based ioctl for user space
compability reasons.

Signed-off-by: Thomas Gleixner <[email protected]>
  • Loading branch information
Thomas Gleixner committed May 29, 2006
1 parent ff268fb commit 5bd34c0
Show file tree
Hide file tree
Showing 20 changed files with 134 additions and 99 deletions.
26 changes: 24 additions & 2 deletions drivers/mtd/mtdchar.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,14 +512,36 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
break;
}

/* Legacy interface */
case MEMGETOOBSEL:
{
if (copy_to_user(argp, mtd->oobinfo,
sizeof(struct nand_oobinfo)))
struct nand_oobinfo oi;

if (!mtd->ecclayout)
return -EOPNOTSUPP;
if (mtd->ecclayout->eccbytes > ARRAY_SIZE(oi.eccpos))
return -EINVAL;

oi.useecc = MTD_NANDECC_AUTOPLACE;
memcpy(&oi.eccpos, mtd->ecclayout->eccpos, sizeof(oi.eccpos));
memcpy(&oi.oobfree, mtd->ecclayout->oobfree,
sizeof(oi.oobfree));

if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo)))
return -EFAULT;
break;
}

case ECCGETLAYOUT:

if (!mtd->ecclayout)
return -EOPNOTSUPP;

if (copy_to_user(argp, &mtd->ecclayout,
sizeof(struct nand_ecclayout)))
return -EFAULT;
break;

case MEMGETBADBLOCK:
{
loff_t offs;
Expand Down
2 changes: 1 addition & 1 deletion drivers/mtd/mtdconcat.c
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c

}

concat->mtd.oobinfo = subdev[0]->oobinfo;
concat->mtd.ecclayout = subdev[0]->ecclayout;

concat->num_subdev = num_devs;
concat->mtd.name = name;
Expand Down
2 changes: 1 addition & 1 deletion drivers/mtd/mtdpart.c
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ int add_mtd_partitions(struct mtd_info *master,
parts[i].name);
}

slave->mtd.oobinfo = master->oobinfo;
slave->mtd.ecclayout = master->ecclayout;

if(parts[i].mtdp)
{ /* store the object pointer (caller may or may not register it */
Expand Down
5 changes: 2 additions & 3 deletions drivers/mtd/nand/diskonchip.c
Original file line number Diff line number Diff line change
Expand Up @@ -1058,8 +1058,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,
* safer. The only problem with it is that any code that parses oobfree must
* be able to handle out-of-order segments.
*/
static struct nand_oobinfo doc200x_oobinfo = {
.useecc = MTD_NANDECC_AUTOPLACE,
static struct nand_ecclayout doc200x_oobinfo = {
.eccbytes = 6,
.eccpos = {0, 1, 2, 3, 4, 5},
.oobfree = {{8, 8}, {6, 2}}
Expand Down Expand Up @@ -1662,7 +1661,7 @@ static int __init doc_probe(unsigned long physadr)
nand->ecc.calculate = doc200x_calculate_ecc;
nand->ecc.correct = doc200x_correct_data;

nand->autooob = &doc200x_oobinfo;
nand->ecc.layout = &doc200x_oobinfo;
nand->ecc.mode = NAND_ECC_HW_SYNDROME;
nand->ecc.size = 512;
nand->ecc.bytes = 6;
Expand Down
52 changes: 33 additions & 19 deletions drivers/mtd/nand/nand_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,28 +52,33 @@
#endif

/* Define default oob placement schemes for large and small page devices */
static struct nand_oobinfo nand_oob_8 = {
.useecc = MTD_NANDECC_AUTOPLACE,
static struct nand_ecclayout nand_oob_8 = {
.eccbytes = 3,
.eccpos = {0, 1, 2},
.oobfree = {{3, 2}, {6, 2}}
.oobfree = {
{.offset = 3,
.length = 2},
{.offset = 6,
.length = 2}}
};

static struct nand_oobinfo nand_oob_16 = {
.useecc = MTD_NANDECC_AUTOPLACE,
static struct nand_ecclayout nand_oob_16 = {
.eccbytes = 6,
.eccpos = {0, 1, 2, 3, 6, 7},
.oobfree = {{8, 8}}
.oobfree = {
{.offset = 8,
. length = 8}}
};

static struct nand_oobinfo nand_oob_64 = {
.useecc = MTD_NANDECC_AUTOPLACE,
static struct nand_ecclayout nand_oob_64 = {
.eccbytes = 24,
.eccpos = {
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63},
.oobfree = {{2, 38}}
.oobfree = {
{.offset = 2,
.length = 38}}
};

/* This is used for padding purposes in nand_write_oob */
Expand Down Expand Up @@ -749,7 +754,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *p = buf;
uint8_t *ecc_calc = chip->buffers.ecccalc;
uint8_t *ecc_code = chip->buffers.ecccode;
int *eccpos = chip->autooob->eccpos;
int *eccpos = chip->ecc.layout->eccpos;

chip->read_buf(mtd, buf, mtd->writesize);
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
Expand Down Expand Up @@ -795,7 +800,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *p = buf;
uint8_t *ecc_calc = chip->buffers.ecccalc;
uint8_t *ecc_code = chip->buffers.ecccode;
int *eccpos = chip->autooob->eccpos;
int *eccpos = chip->ecc.layout->eccpos;

for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
chip->ecc.hwctl(mtd, NAND_ECC_READ);
Expand Down Expand Up @@ -1198,7 +1203,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
int eccsteps = chip->ecc.steps;
uint8_t *ecc_calc = chip->buffers.ecccalc;
const uint8_t *p = buf;
int *eccpos = chip->autooob->eccpos;
int *eccpos = chip->ecc.layout->eccpos;

if (chip->ecc.mode != NAND_ECC_NONE) {
/* Software ecc calculation */
Expand Down Expand Up @@ -1227,7 +1232,7 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
int eccsteps = chip->ecc.steps;
uint8_t *ecc_calc = chip->buffers.ecccalc;
const uint8_t *p = buf;
int *eccpos = chip->autooob->eccpos;
int *eccpos = chip->ecc.layout->eccpos;

for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
Expand Down Expand Up @@ -2124,16 +2129,16 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
/*
* If no default placement scheme is given, select an appropriate one
*/
if (!chip->autooob) {
if (!chip->ecc.layout) {
switch (mtd->oobsize) {
case 8:
chip->autooob = &nand_oob_8;
chip->ecc.layout = &nand_oob_8;
break;
case 16:
chip->autooob = &nand_oob_16;
chip->ecc.layout = &nand_oob_16;
break;
case 64:
chip->autooob = &nand_oob_64;
chip->ecc.layout = &nand_oob_64;
break;
default:
printk(KERN_WARNING "No oob scheme defined for "
Expand Down Expand Up @@ -2197,6 +2202,15 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
BUG();
}

/*
* The number of bytes available for a client to place data into
* the out of band area
*/
chip->ecc.layout->oobavail = 0;
for (i = 0; chip->ecc.layout->oobfree[i].length; i++)
chip->ecc.layout->oobavail +=
chip->ecc.layout->oobfree[i].length;

/*
* Set the number of read / write steps for one page depending on ECC
* mode
Expand Down Expand Up @@ -2236,8 +2250,8 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
mtd->block_isbad = nand_block_isbad;
mtd->block_markbad = nand_block_markbad;

/* and make the autooob the default one */
mtd->oobinfo = chip->autooob;
/* propagate ecc.layout to mtd_info */
mtd->ecclayout = chip->ecc.layout;

/* Check, if we should skip the bad block table scan */
if (chip->options & NAND_SKIP_BBTSCAN)
Expand Down
2 changes: 1 addition & 1 deletion drivers/mtd/nand/ndfc.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
chip->ecc.mode = NAND_ECC_HW;
chip->ecc.size = 256;
chip->ecc.bytes = 3;
chip->autooob = mtd->pl_chip->oobinfo;
chip->ecclayout = mtd->pl_chip->ecclayout;
mtd->mtd.priv = chip;
mtd->mtd.owner = THIS_MODULE;
}
Expand Down
5 changes: 2 additions & 3 deletions drivers/mtd/nand/rtc_from4.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,7 @@ static struct rs_control *rs_decoder;
/*
* hardware specific Out Of Band information
*/
static struct nand_oobinfo rtc_from4_nand_oobinfo = {
.useecc = MTD_NANDECC_AUTOPLACE,
static struct nand_ecclayout rtc_from4_nand_oobinfo = {
.eccbytes = 32,
.eccpos = {
0, 1, 2, 3, 4, 5, 6, 7,
Expand Down Expand Up @@ -574,7 +573,7 @@ static int __init rtc_from4_init(void)
/* return the status of extra status and ECC checks */
this->errstat = rtc_from4_errstat;
/* set the nand_oobinfo to support FPGA H/W error detection */
this->autooob = &rtc_from4_nand_oobinfo;
this->ecc.layout = &rtc_from4_nand_oobinfo;
this->ecc.hwctl = rtc_from4_enable_hwecc;
this->ecc.calculate = rtc_from4_calculate_ecc;
this->ecc.correct = rtc_from4_correct_data;
Expand Down
5 changes: 2 additions & 3 deletions drivers/mtd/nand/s3c2410.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@ static int hardware_ecc = 0;
/* new oob placement block for use with hardware ecc generation
*/

static struct nand_oobinfo nand_hw_eccoob = {
.useecc = MTD_NANDECC_AUTOPLACE,
static struct nand_ecclayout nand_hw_eccoob = {
.eccbytes = 3,
.eccpos = {0, 1, 2},
.oobfree = {{8, 8}}
Expand Down Expand Up @@ -502,7 +501,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
chip->ecc.mode = NAND_ECC_HW;
chip->ecc.size = 512;
chip->ecc.bytes = 3;
chip->autooob = &nand_hw_eccoob;
chip->ecc.layout = &nand_hw_eccoob;

if (info->is_s3c2440) {
chip->ecc.hwctl = s3c2440_nand_enable_hwecc;
Expand Down
5 changes: 2 additions & 3 deletions drivers/mtd/nand/sharpsl.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,7 @@ static struct nand_bbt_descr sharpsl_akita_bbt = {
.pattern = scan_ff_pattern
};

static struct nand_oobinfo akita_oobinfo = {
.useecc = MTD_NANDECC_AUTOPLACE,
static struct nand_ecclayout akita_oobinfo = {
.eccbytes = 24,
.eccpos = {
0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11,
Expand Down Expand Up @@ -202,7 +201,7 @@ static int __init sharpsl_nand_init(void)
this->badblock_pattern = &sharpsl_bbt;
if (machine_is_akita() || machine_is_borzoi()) {
this->badblock_pattern = &sharpsl_akita_bbt;
this->autooob = &akita_oobinfo;
this->ecc.layout = &akita_oobinfo;
}
this->ecc.hwctl = sharpsl_nand_enable_hwecc;
this->ecc.calculate = sharpsl_nand_calculate_ecc;
Expand Down
14 changes: 6 additions & 8 deletions drivers/mtd/onenand/onenand_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
/**
* onenand_oob_64 - oob info for large (2KB) page
*/
static struct nand_oobinfo onenand_oob_64 = {
.useecc = MTD_NANDECC_AUTOPLACE,
static struct nand_ecclayout onenand_oob_64 = {
.eccbytes = 20,
.eccpos = {
8, 9, 10, 11, 12,
Expand All @@ -41,8 +40,7 @@ static struct nand_oobinfo onenand_oob_64 = {
/**
* onenand_oob_32 - oob info for middle (1KB) page
*/
static struct nand_oobinfo onenand_oob_32 = {
.useecc = MTD_NANDECC_AUTOPLACE,
static struct nand_ecclayout onenand_oob_32 = {
.eccbytes = 10,
.eccpos = {
8, 9, 10, 11, 12,
Expand Down Expand Up @@ -1747,22 +1745,22 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)

switch (mtd->oobsize) {
case 64:
this->autooob = &onenand_oob_64;
this->ecclayout = &onenand_oob_64;
break;

case 32:
this->autooob = &onenand_oob_32;
this->ecclayout = &onenand_oob_32;
break;

default:
printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n",
mtd->oobsize);
/* To prevent kernel oops */
this->autooob = &onenand_oob_32;
this->ecclayout = &onenand_oob_32;
break;
}

mtd->oobinfo = this->autooob;
mtd->ecclayout = this->ecclayout;

/* Fill in remaining MTD driver data */
mtd->type = MTD_NANDFLASH;
Expand Down
2 changes: 1 addition & 1 deletion fs/jffs2/jffs2_fs_sb.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ struct jffs2_sb_info {
struct rw_semaphore wbuf_sem; /* Protects the write buffer */

/* Information about out-of-band area usage... */
struct nand_oobinfo *oobinfo;
struct nand_ecclayout *ecclayout;
uint32_t badblock_pos;
uint32_t fsdata_pos;
uint32_t fsdata_len;
Expand Down
51 changes: 16 additions & 35 deletions fs/jffs2/wbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1140,18 +1140,9 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *
return 1;
}

#define NAND_JFFS2_OOB16_FSDALEN 8

static struct nand_oobinfo jffs2_oobinfo_docecc = {
.useecc = MTD_NANDECC_PLACE,
.eccbytes = 6,
.eccpos = {0,1,2,3,4,5}
};


static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c)
{
struct nand_oobinfo *oinfo = c->mtd->oobinfo;
struct nand_ecclayout *oinfo = c->mtd->ecclayout;

/* Do this only, if we have an oob buffer */
if (!c->mtd->oobsize)
Expand All @@ -1161,33 +1152,23 @@ static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c)
c->cleanmarker_size = 0;

/* Should we use autoplacement ? */
if (oinfo && oinfo->useecc == MTD_NANDECC_AUTOPLACE) {
D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n"));
/* Get the position of the free bytes */
if (!oinfo->oobfree[0][1]) {
printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep. Autoplacement selected and no empty space in oob\n");
return -ENOSPC;
}
c->fsdata_pos = oinfo->oobfree[0][0];
c->fsdata_len = oinfo->oobfree[0][1];
if (c->fsdata_len > 8)
c->fsdata_len = 8;
} else {
/* This is just a legacy fallback and should go away soon */
switch(c->mtd->ecctype) {
case MTD_ECC_RS_DiskOnChip:
printk(KERN_WARNING "JFFS2 using DiskOnChip hardware ECC without autoplacement. Fix it!\n");
c->oobinfo = &jffs2_oobinfo_docecc;
c->fsdata_pos = 6;
c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN;
c->badblock_pos = 15;
break;
if (!oinfo) {
D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n"));
return -EINVAL;
}

default:
D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n"));
return -EINVAL;
}
D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n"));
/* Get the position of the free bytes */
if (!oinfo->oobfree[0].length) {
printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep."
" Autoplacement selected and no empty space in oob\n");
return -ENOSPC;
}
c->fsdata_pos = oinfo->oobfree[0].offset;
c->fsdata_len = oinfo->oobfree[0].length;
if (c->fsdata_len > 8)
c->fsdata_len = 8;

return 0;
}

Expand Down
Loading

0 comments on commit 5bd34c0

Please sign in to comment.