Commit 846031d3 authored by Boris Brezillon's avatar Boris Brezillon

mtd: nand: core: use mtd_ooblayout_xxx() helpers where appropriate

The mtd_ooblayout_xxx() helper functions have been added to avoid direct
accesses to the ecclayout field, and thus ease for future reworks.
Use these helpers in all places where the oobfree[] and eccpos[] arrays
where directly accessed.
Signed-off-by: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
parent c2b78452
...@@ -1279,13 +1279,12 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd, ...@@ -1279,13 +1279,12 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd,
static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page) uint8_t *buf, int oob_required, int page)
{ {
int i, eccsize = chip->ecc.size; int i, eccsize = chip->ecc.size, ret;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
int eccsteps = chip->ecc.steps; int eccsteps = chip->ecc.steps;
uint8_t *p = buf; uint8_t *p = buf;
uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_calc = chip->buffers->ecccalc;
uint8_t *ecc_code = chip->buffers->ecccode; uint8_t *ecc_code = chip->buffers->ecccode;
uint32_t *eccpos = chip->ecc.layout->eccpos;
unsigned int max_bitflips = 0; unsigned int max_bitflips = 0;
chip->ecc.read_page_raw(mtd, chip, buf, 1, page); chip->ecc.read_page_raw(mtd, chip, buf, 1, page);
...@@ -1293,8 +1292,10 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1293,8 +1292,10 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
chip->ecc.calculate(mtd, p, &ecc_calc[i]); chip->ecc.calculate(mtd, p, &ecc_calc[i]);
for (i = 0; i < chip->ecc.total; i++) ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
ecc_code[i] = chip->oob_poi[eccpos[i]]; chip->ecc.total);
if (ret)
return ret;
eccsteps = chip->ecc.steps; eccsteps = chip->ecc.steps;
p = buf; p = buf;
...@@ -1326,14 +1327,14 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1326,14 +1327,14 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi,
int page) int page)
{ {
int start_step, end_step, num_steps; int start_step, end_step, num_steps, ret;
uint32_t *eccpos = chip->ecc.layout->eccpos;
uint8_t *p; uint8_t *p;
int data_col_addr, i, gaps = 0; int data_col_addr, i, gaps = 0;
int datafrag_len, eccfrag_len, aligned_len, aligned_pos; int datafrag_len, eccfrag_len, aligned_len, aligned_pos;
int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1;
int index; int index, section = 0;
unsigned int max_bitflips = 0; unsigned int max_bitflips = 0;
struct mtd_oob_region oobregion = { };
/* Column address within the page aligned to ECC size (256bytes) */ /* Column address within the page aligned to ECC size (256bytes) */
start_step = data_offs / chip->ecc.size; start_step = data_offs / chip->ecc.size;
...@@ -1361,12 +1362,13 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1361,12 +1362,13 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
* The performance is faster if we position offsets according to * The performance is faster if we position offsets according to
* ecc.pos. Let's make sure that there are no gaps in ECC positions. * ecc.pos. Let's make sure that there are no gaps in ECC positions.
*/ */
for (i = 0; i < eccfrag_len - 1; i++) { ret = mtd_ooblayout_find_eccregion(mtd, index, &section, &oobregion);
if (eccpos[i + index] + 1 != eccpos[i + index + 1]) { if (ret)
gaps = 1; return ret;
break;
} if (oobregion.length < eccfrag_len)
} gaps = 1;
if (gaps) { if (gaps) {
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
...@@ -1375,20 +1377,23 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1375,20 +1377,23 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
* Send the command to read the particular ECC bytes take care * Send the command to read the particular ECC bytes take care
* about buswidth alignment in read_buf. * about buswidth alignment in read_buf.
*/ */
aligned_pos = eccpos[index] & ~(busw - 1); aligned_pos = oobregion.offset & ~(busw - 1);
aligned_len = eccfrag_len; aligned_len = eccfrag_len;
if (eccpos[index] & (busw - 1)) if (oobregion.offset & (busw - 1))
aligned_len++; aligned_len++;
if (eccpos[index + (num_steps * chip->ecc.bytes)] & (busw - 1)) if ((oobregion.offset + (num_steps * chip->ecc.bytes)) &
(busw - 1))
aligned_len++; aligned_len++;
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
mtd->writesize + aligned_pos, -1); mtd->writesize + aligned_pos, -1);
chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len); chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
} }
for (i = 0; i < eccfrag_len; i++) ret = mtd_ooblayout_get_eccbytes(mtd, chip->buffers->ecccode,
chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + index]]; chip->oob_poi, index, eccfrag_len);
if (ret)
return ret;
p = bufpoi + data_col_addr; p = bufpoi + data_col_addr;
for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) { for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) {
...@@ -1429,13 +1434,12 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1429,13 +1434,12 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page) uint8_t *buf, int oob_required, int page)
{ {
int i, eccsize = chip->ecc.size; int i, eccsize = chip->ecc.size, ret;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
int eccsteps = chip->ecc.steps; int eccsteps = chip->ecc.steps;
uint8_t *p = buf; uint8_t *p = buf;
uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_calc = chip->buffers->ecccalc;
uint8_t *ecc_code = chip->buffers->ecccode; uint8_t *ecc_code = chip->buffers->ecccode;
uint32_t *eccpos = chip->ecc.layout->eccpos;
unsigned int max_bitflips = 0; unsigned int max_bitflips = 0;
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
...@@ -1445,8 +1449,10 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1445,8 +1449,10 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
} }
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
for (i = 0; i < chip->ecc.total; i++) ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
ecc_code[i] = chip->oob_poi[eccpos[i]]; chip->ecc.total);
if (ret)
return ret;
eccsteps = chip->ecc.steps; eccsteps = chip->ecc.steps;
p = buf; p = buf;
...@@ -1491,12 +1497,11 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1491,12 +1497,11 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
struct nand_chip *chip, uint8_t *buf, int oob_required, int page) struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
{ {
int i, eccsize = chip->ecc.size; int i, eccsize = chip->ecc.size, ret;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
int eccsteps = chip->ecc.steps; int eccsteps = chip->ecc.steps;
uint8_t *p = buf; uint8_t *p = buf;
uint8_t *ecc_code = chip->buffers->ecccode; uint8_t *ecc_code = chip->buffers->ecccode;
uint32_t *eccpos = chip->ecc.layout->eccpos;
uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_calc = chip->buffers->ecccalc;
unsigned int max_bitflips = 0; unsigned int max_bitflips = 0;
...@@ -1505,8 +1510,10 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, ...@@ -1505,8 +1510,10 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
for (i = 0; i < chip->ecc.total; i++) ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
ecc_code[i] = chip->oob_poi[eccpos[i]]; chip->ecc.total);
if (ret)
return ret;
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
int stat; int stat;
...@@ -1607,14 +1614,17 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1607,14 +1614,17 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
/** /**
* nand_transfer_oob - [INTERN] Transfer oob to client buffer * nand_transfer_oob - [INTERN] Transfer oob to client buffer
* @chip: nand chip structure * @mtd: mtd info structure
* @oob: oob destination address * @oob: oob destination address
* @ops: oob ops structure * @ops: oob ops structure
* @len: size of oob to transfer * @len: size of oob to transfer
*/ */
static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, static uint8_t *nand_transfer_oob(struct mtd_info *mtd, uint8_t *oob,
struct mtd_oob_ops *ops, size_t len) struct mtd_oob_ops *ops, size_t len)
{ {
struct nand_chip *chip = mtd_to_nand(mtd);
int ret;
switch (ops->mode) { switch (ops->mode) {
case MTD_OPS_PLACE_OOB: case MTD_OPS_PLACE_OOB:
...@@ -1622,31 +1632,12 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, ...@@ -1622,31 +1632,12 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
memcpy(oob, chip->oob_poi + ops->ooboffs, len); memcpy(oob, chip->oob_poi + ops->ooboffs, len);
return oob + len; return oob + len;
case MTD_OPS_AUTO_OOB: { case MTD_OPS_AUTO_OOB:
struct nand_oobfree *free = chip->ecc.layout->oobfree; ret = mtd_ooblayout_get_databytes(mtd, oob, chip->oob_poi,
uint32_t boffs = 0, roffs = ops->ooboffs; ops->ooboffs, len);
size_t bytes = 0; BUG_ON(ret);
return oob + len;
for (; free->length && len; free++, len -= bytes) {
/* Read request not from offset 0? */
if (unlikely(roffs)) {
if (roffs >= free->length) {
roffs -= free->length;
continue;
}
boffs = free->offset + roffs;
bytes = min_t(size_t, len,
(free->length - roffs));
roffs = 0;
} else {
bytes = min_t(size_t, len, free->length);
boffs = free->offset;
}
memcpy(oob, chip->oob_poi + boffs, bytes);
oob += bytes;
}
return oob;
}
default: default:
BUG(); BUG();
} }
...@@ -1780,7 +1771,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, ...@@ -1780,7 +1771,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
int toread = min(oobreadlen, max_oobsize); int toread = min(oobreadlen, max_oobsize);
if (toread) { if (toread) {
oob = nand_transfer_oob(chip, oob = nand_transfer_oob(mtd,
oob, ops, toread); oob, ops, toread);
oobreadlen -= toread; oobreadlen -= toread;
} }
...@@ -2080,7 +2071,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, ...@@ -2080,7 +2071,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
break; break;
len = min(len, readlen); len = min(len, readlen);
buf = nand_transfer_oob(chip, buf, ops, len); buf = nand_transfer_oob(mtd, buf, ops, len);
if (chip->options & NAND_NEED_READRDY) { if (chip->options & NAND_NEED_READRDY) {
/* Apply delay or wait for ready/busy pin */ /* Apply delay or wait for ready/busy pin */
...@@ -2239,19 +2230,20 @@ static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -2239,19 +2230,20 @@ static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required, const uint8_t *buf, int oob_required,
int page) int page)
{ {
int i, eccsize = chip->ecc.size; int i, eccsize = chip->ecc.size, ret;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
int eccsteps = chip->ecc.steps; int eccsteps = chip->ecc.steps;
uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_calc = chip->buffers->ecccalc;
const uint8_t *p = buf; const uint8_t *p = buf;
uint32_t *eccpos = chip->ecc.layout->eccpos;
/* Software ECC calculation */ /* Software ECC calculation */
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
chip->ecc.calculate(mtd, p, &ecc_calc[i]); chip->ecc.calculate(mtd, p, &ecc_calc[i]);
for (i = 0; i < chip->ecc.total; i++) ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0,
chip->oob_poi[eccpos[i]] = ecc_calc[i]; chip->ecc.total);
if (ret)
return ret;
return chip->ecc.write_page_raw(mtd, chip, buf, 1, page); return chip->ecc.write_page_raw(mtd, chip, buf, 1, page);
} }
...@@ -2268,12 +2260,11 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -2268,12 +2260,11 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required, const uint8_t *buf, int oob_required,
int page) int page)
{ {
int i, eccsize = chip->ecc.size; int i, eccsize = chip->ecc.size, ret;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
int eccsteps = chip->ecc.steps; int eccsteps = chip->ecc.steps;
uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_calc = chip->buffers->ecccalc;
const uint8_t *p = buf; const uint8_t *p = buf;
uint32_t *eccpos = chip->ecc.layout->eccpos;
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
chip->ecc.hwctl(mtd, NAND_ECC_WRITE); chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
...@@ -2281,8 +2272,10 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -2281,8 +2272,10 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
chip->ecc.calculate(mtd, p, &ecc_calc[i]); chip->ecc.calculate(mtd, p, &ecc_calc[i]);
} }
for (i = 0; i < chip->ecc.total; i++) ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0,
chip->oob_poi[eccpos[i]] = ecc_calc[i]; chip->ecc.total);
if (ret)
return ret;
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
...@@ -2310,11 +2303,10 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd, ...@@ -2310,11 +2303,10 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
int ecc_size = chip->ecc.size; int ecc_size = chip->ecc.size;
int ecc_bytes = chip->ecc.bytes; int ecc_bytes = chip->ecc.bytes;
int ecc_steps = chip->ecc.steps; int ecc_steps = chip->ecc.steps;
uint32_t *eccpos = chip->ecc.layout->eccpos;
uint32_t start_step = offset / ecc_size; uint32_t start_step = offset / ecc_size;
uint32_t end_step = (offset + data_len - 1) / ecc_size; uint32_t end_step = (offset + data_len - 1) / ecc_size;
int oob_bytes = mtd->oobsize / ecc_steps; int oob_bytes = mtd->oobsize / ecc_steps;
int step, i; int step, ret;
for (step = 0; step < ecc_steps; step++) { for (step = 0; step < ecc_steps; step++) {
/* configure controller for WRITE access */ /* configure controller for WRITE access */
...@@ -2342,8 +2334,10 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd, ...@@ -2342,8 +2334,10 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
/* copy calculated ECC for whole page to chip->buffer->oob */ /* copy calculated ECC for whole page to chip->buffer->oob */
/* this include masked-value(0xFF) for unwritten subpages */ /* this include masked-value(0xFF) for unwritten subpages */
ecc_calc = chip->buffers->ecccalc; ecc_calc = chip->buffers->ecccalc;
for (i = 0; i < chip->ecc.total; i++) ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0,
chip->oob_poi[eccpos[i]] = ecc_calc[i]; chip->ecc.total);
if (ret)
return ret;
/* write OOB buffer to NAND device */ /* write OOB buffer to NAND device */
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
...@@ -2480,6 +2474,7 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len, ...@@ -2480,6 +2474,7 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
struct mtd_oob_ops *ops) struct mtd_oob_ops *ops)
{ {
struct nand_chip *chip = mtd_to_nand(mtd); struct nand_chip *chip = mtd_to_nand(mtd);
int ret;
/* /*
* Initialise to all 0xFF, to avoid the possibility of left over OOB * Initialise to all 0xFF, to avoid the possibility of left over OOB
...@@ -2494,31 +2489,12 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len, ...@@ -2494,31 +2489,12 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
memcpy(chip->oob_poi + ops->ooboffs, oob, len); memcpy(chip->oob_poi + ops->ooboffs, oob, len);
return oob + len; return oob + len;
case MTD_OPS_AUTO_OOB: { case MTD_OPS_AUTO_OOB:
struct nand_oobfree *free = chip->ecc.layout->oobfree; ret = mtd_ooblayout_set_databytes(mtd, oob, chip->oob_poi,
uint32_t boffs = 0, woffs = ops->ooboffs; ops->ooboffs, len);
size_t bytes = 0; BUG_ON(ret);
return oob + len;
for (; free->length && len; free++, len -= bytes) {
/* Write request not from offset 0? */
if (unlikely(woffs)) {
if (woffs >= free->length) {
woffs -= free->length;
continue;
}
boffs = free->offset + woffs;
bytes = min_t(size_t, len,
(free->length - woffs));
woffs = 0;
} else {
bytes = min_t(size_t, len, free->length);
boffs = free->offset;
}
memcpy(chip->oob_poi + boffs, oob, bytes);
oob += bytes;
}
return oob;
}
default: default:
BUG(); BUG();
} }
...@@ -4105,7 +4081,6 @@ static bool nand_ecc_strength_good(struct mtd_info *mtd) ...@@ -4105,7 +4081,6 @@ static bool nand_ecc_strength_good(struct mtd_info *mtd)
*/ */
int nand_scan_tail(struct mtd_info *mtd) int nand_scan_tail(struct mtd_info *mtd)
{ {
int i;
struct nand_chip *chip = mtd_to_nand(mtd); struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_ecc_ctrl *ecc = &chip->ecc; struct nand_ecc_ctrl *ecc = &chip->ecc;
struct nand_buffers *nbuf; struct nand_buffers *nbuf;
...@@ -4309,20 +4284,10 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -4309,20 +4284,10 @@ int nand_scan_tail(struct mtd_info *mtd)
if (!ecc->write_oob_raw) if (!ecc->write_oob_raw)
ecc->write_oob_raw = ecc->write_oob; ecc->write_oob_raw = ecc->write_oob;
/* /* propagate ecc info to mtd_info */
* The number of bytes available for a client to place data into mtd->ecclayout = ecc->layout;
* the out of band area. mtd->ecc_strength = ecc->strength;
*/ mtd->ecc_step_size = ecc->size;
mtd->oobavail = 0;
if (ecc->layout) {
for (i = 0; ecc->layout->oobfree[i].length; i++)
mtd->oobavail += ecc->layout->oobfree[i].length;
}
/* ECC sanity check: warn if it's too weak */
if (!nand_ecc_strength_good(mtd))
pr_warn("WARNING: %s: the ECC used on your system is too weak compared to the one required by the NAND chip\n",
mtd->name);
/* /*
* Set the number of read / write steps for one page depending on ECC * Set the number of read / write steps for one page depending on ECC
...@@ -4336,6 +4301,21 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -4336,6 +4301,21 @@ int nand_scan_tail(struct mtd_info *mtd)
} }
ecc->total = ecc->steps * ecc->bytes; ecc->total = ecc->steps * ecc->bytes;
/*
* The number of bytes available for a client to place data into
* the out of band area.
*/
ret = mtd_ooblayout_count_freebytes(mtd);
if (ret < 0)
ret = 0;
mtd->oobavail = ret;
/* ECC sanity check: warn if it's too weak */
if (!nand_ecc_strength_good(mtd))
pr_warn("WARNING: %s: the ECC used on your system is too weak compared to the one required by the NAND chip\n",
mtd->name);
/* Allow subpage writes up to ecc.steps. Not possible for MLC flash */ /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */
if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) { if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) {
switch (ecc->steps) { switch (ecc->steps) {
...@@ -4392,10 +4372,6 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -4392,10 +4372,6 @@ int nand_scan_tail(struct mtd_info *mtd)
mtd->_block_markbad = nand_block_markbad; mtd->_block_markbad = nand_block_markbad;
mtd->writebufsize = mtd->writesize; mtd->writebufsize = mtd->writesize;
/* propagate ecc info to mtd_info */
mtd->ecclayout = ecc->layout;
mtd->ecc_strength = ecc->strength;
mtd->ecc_step_size = ecc->size;
/* /*
* Initialize bitflip_threshold to its default prior scan_bbt() call. * Initialize bitflip_threshold to its default prior scan_bbt() call.
* scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be * scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be
......
...@@ -196,7 +196,18 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd) ...@@ -196,7 +196,18 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
printk(KERN_WARNING "eccsize %u is too large\n", eccsize); printk(KERN_WARNING "eccsize %u is too large\n", eccsize);
goto fail; goto fail;
} }
if (layout->eccbytes != (eccsteps*eccbytes)) {
/*
* ecc->steps and ecc->total might be used by mtd->ooblayout->ecc(),
* which is called by mtd_ooblayout_count_eccbytes().
* Make sure they are properly initialized before calling
* mtd_ooblayout_count_eccbytes().
* FIXME: we should probaly rework the sequencing in nand_scan_tail()
* to avoid setting those fields twice.
*/
nand->ecc.steps = eccsteps;
nand->ecc.total = eccsteps * eccbytes;
if (mtd_ooblayout_count_eccbytes(mtd) != (eccsteps*eccbytes)) {
printk(KERN_WARNING "invalid ecc layout\n"); printk(KERN_WARNING "invalid ecc layout\n");
goto fail; goto fail;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment