Commit aa6d01fa authored by Mike Dunn's avatar Mike Dunn Committed by David Woodhouse

mtd: docg4: fix oob reads

This patch does two closely related things:

(1) Currently the ecc.read_page() method does not fill the nand->oob_poi buffer
with the oob data, but instead reads oob into a local buffer.  Fix this by
filling the oob_poi buffer instead of a local buffer.  The 'oob_required'
argument is quietly ignored; the device must always read oob after the page
data, and it is presumed that there's no harm in filling oob_poi, even when not
explicitly requested.

(2) Always read oob from the device in ecc.read_oob(), instead of copying it
from a local buffer under some circumstances.
Signed-off-by: default avatarMike Dunn <mikedunn@newsguy.com>
Signed-off-by: default avatarArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 036a1ac1
...@@ -378,9 +378,9 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page) ...@@ -378,9 +378,9 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page)
* bit flips(s) are not reported in stats. * bit flips(s) are not reported in stats.
*/ */
if (doc->oob_buf[15]) { if (nand->oob_poi[15]) {
int bit, numsetbits = 0; int bit, numsetbits = 0;
unsigned long written_flag = doc->oob_buf[15]; unsigned long written_flag = nand->oob_poi[15];
for_each_set_bit(bit, &written_flag, 8) for_each_set_bit(bit, &written_flag, 8)
numsetbits++; numsetbits++;
if (numsetbits > 4) { /* assume blank */ if (numsetbits > 4) { /* assume blank */
...@@ -428,7 +428,7 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page) ...@@ -428,7 +428,7 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page)
/* if error within oob area preceeding ecc bytes... */ /* if error within oob area preceeding ecc bytes... */
if (errpos[i] > DOCG4_PAGE_SIZE * 8) if (errpos[i] > DOCG4_PAGE_SIZE * 8)
change_bit(errpos[i] - DOCG4_PAGE_SIZE * 8, change_bit(errpos[i] - DOCG4_PAGE_SIZE * 8,
(unsigned long *)doc->oob_buf); (unsigned long *)nand->oob_poi);
else /* error in page data */ else /* error in page data */
change_bit(errpos[i], (unsigned long *)buf); change_bit(errpos[i], (unsigned long *)buf);
...@@ -748,18 +748,12 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand, ...@@ -748,18 +748,12 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand,
docg4_read_buf(mtd, buf, DOCG4_PAGE_SIZE); /* read the page data */ docg4_read_buf(mtd, buf, DOCG4_PAGE_SIZE); /* read the page data */
/* /* this device always reads oob after page data */
* Diskonchips read oob immediately after a page read. Mtd
* infrastructure issues a separate command for reading oob after the
* page is read. So we save the oob bytes in a local buffer and just
* copy it if the next command reads oob from the same page.
*/
/* first 14 oob bytes read from I/O reg */ /* first 14 oob bytes read from I/O reg */
docg4_read_buf(mtd, doc->oob_buf, 14); docg4_read_buf(mtd, nand->oob_poi, 14);
/* last 2 read from another reg */ /* last 2 read from another reg */
buf16 = (uint16_t *)(doc->oob_buf + 14); buf16 = (uint16_t *)(nand->oob_poi + 14);
*buf16 = readw(docptr + DOCG4_MYSTERY_REG); *buf16 = readw(docptr + DOCG4_MYSTERY_REG);
write_nop(docptr); write_nop(docptr);
...@@ -807,21 +801,6 @@ static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand, ...@@ -807,21 +801,6 @@ static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
dev_dbg(doc->dev, "%s: page %x\n", __func__, page); dev_dbg(doc->dev, "%s: page %x\n", __func__, page);
/*
* Oob bytes are read as part of a normal page read. If the previous
* nand command was a read of the page whose oob is now being read, just
* copy the oob bytes that we saved in a local buffer and avoid a
* separate oob read.
*/
if (doc->last_command.command == NAND_CMD_READ0 &&
doc->last_command.page == page) {
memcpy(nand->oob_poi, doc->oob_buf, 16);
return 0;
}
/*
* Separate read of oob data only.
*/
docg4_command(mtd, NAND_CMD_READ0, nand->ecc.size, page); docg4_command(mtd, NAND_CMD_READ0, nand->ecc.size, page);
writew(DOC_ECCCONF0_READ_MODE | DOCG4_OOB_SIZE, docptr + DOC_ECCCONF0); writew(DOC_ECCCONF0_READ_MODE | DOCG4_OOB_SIZE, docptr + DOC_ECCCONF0);
......
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