[RFC/PATCH 2/3] NAND multiple plane feature
Thomas Gleixner
tglx at linutronix.de
Thu Jun 5 16:03:25 EDT 2008
On Wed, 28 May 2008, Alexey Korolev wrote:
> As NAND multiple plane architecture assumes simultaneous write/erase of
> several pages/blocks at the same time, we have to modify page/eraseblock
> sizes and report modified size to upper layers. In other words physical
> erase block size/ page size != reported erase block size/ page size.
>
> For example if we have dual plane device we have to extend erase block
> size and page size in 2 times.
And why the heck do you have to do all those phys_erase_shift changes ?
mtd->erase_size is completely independent of the nand internal
information already. All it needs is to adjust the erase_size which is
reported to the mtd layer.
> Also this patch keep track on bad block management. NAND datasheets
> alows us combine only pair of neibour blocks into dual/multiple plane
> operations. So if we have multiple plane device and one block is bad,
> reported extended block should be considered as bad.
Please do this in a separate patch if it's even necessary at all.
> @@ -2269,13 +2269,13 @@ static struct nand_flash_dev *nand_get_f
> /* Number of planes*/
> chip->numplanes = 1 << ((planeid >> 2) & 0x03);
planeid is magically declared and initialized, right ?
> /* Calc pagesize */
> - mtd->writesize = 1024 << (extid & 0x3);
> + mtd->writesize = (1024 << (extid & 0x3)) * chip->numplanes;
> extid >>= 2;
> /* Calc oobsize */
> mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
> extid >>= 2;
> /* Calc blocksize. Blocksize is multiples of 64KiB */
> - mtd->erasesize = (64 * 1024) << (extid & 0x03);
> + mtd->erasesize = ((64 * 1024) << (extid & 0x03)) * chip->numplanes;
> extid >>= 2;
> /* Get buswidth information */
> busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
> @@ -2290,6 +2290,8 @@ static struct nand_flash_dev *nand_get_f
> busw = type->options & NAND_BUSWIDTH_16;
> }
>
> + chip->oob_phys_size = mtd->oobsize / chip->numplanes;
What the heck initializes chip->numplanes in the else path of
if (!type->pagesize) {
> int nand_scan_tail(struct mtd_info *mtd)
> {
> - int i;
> + int i, j;
> + int oobfree_len;
One line
>
> - if (!chip->write_page)
> - chip->write_page = nand_write_page;
> -
1) Change has nothing to do with the patch description
2) removing this will break existing code
> + if (chip->numplanes > 1) {
Introduce new feature in a separate patch
> + for (oobfree_len = 0; chip->ecc.layout->oobfree[oobfree_len].length; oobfree_len++)
> + ;
> + i = 0;
> + while (i < chip->numplanes) {
> + for (j = 0; j < oobfree_len ; j++) {
> + chip->ecc.layout->oobfree[j + i * oobfree_len].length = chip->ecc.layout->oobfree[j].length;
> + chip->ecc.layout->oobfree[j + i * oobfree_len].offset = chip->ecc.layout->oobfree[j].offset + chip->oob_phys_size * i;
> + }
> + for (j = 0; j < chip->ecc.layout->eccbytes; j++)
> + chip->ecc.layout->eccpos[j + i * chip->ecc.layout->eccbytes] = chip->ecc.layout->eccpos[j] + chip->oob_phys_size * i;
Screenwidth 280 characters ?
> + i++;
> + }
> + chip->ecc.layout->eccbytes *= chip->numplanes;
> + }
>
> */
> -static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
> +static int check_pattern(struct mtd_info *mtd, uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
> {
> int i, end = 0;
> + struct nand_chip *this = mtd->priv;
> + int plane_num = 0;
>
> uint8_t *p = buf;
>
> - end = paglen + td->offs;
> + do {
> + end = this->page_phys_size + td->offs;
> if (td->options & NAND_BBT_SCANEMPTY) {
> for (i = 0; i < end; i++) {
> if (p[i] != 0xff)
> @@ -103,6 +106,10 @@ static int check_pattern(uint8_t *buf, i
> return -1;
> }
> }
> + p += len - end;
> + plane_num++;
> + }
> + while (plane_num < this->numplanes);
> return 0;
> }
This change is completely useless. If you have to scan a buffer double
the size, then the code can be called twice. Create an inline function
which does the numplanes magic and call that.
> @@ -116,16 +123,22 @@ static int check_pattern(uint8_t *buf, i
> * no optional empty check
> *
> */
> -static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
> +static int check_short_pattern(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
> {
> int i;
> uint8_t *p = buf;
>
> + struct nand_chip *this = mtd->priv;
> + int plane_num = 0;
> /* Compare the pattern */
> + do {
> for (i = 0; i < td->len; i++) {
> - if (p[td->offs + i] != td->pattern[i])
> + if (p[this->oob_phys_size * plane_num + td->offs + i] != td->pattern[i])
> return -1;
> }
> + plane_num++;
> + }
> + while (plane_num < this->numplanes);
> return 0;
> }
Same here
> @@ -318,7 +331,7 @@ static int scan_block_full(struct mtd_in
> return ret;
>
> for (j = 0; j < len; j++, buf += scanlen) {
> - if (check_pattern(buf, scanlen, mtd->writesize, bd))
> + if (check_pattern(mtd, buf, scanlen, mtd->writesize, bd))
> return 1;
> }
> return 0;
> @@ -349,7 +362,7 @@ static int scan_block_fast(struct mtd_in
> if (ret)
> return ret;
>
> - if (check_short_pattern(buf, bd))
> + if (check_short_pattern(mtd, buf, bd))
> return 1;
>
> offs += mtd->writesize;
> @@ -501,7 +514,7 @@ static int search_bbt(struct mtd_info *m
>
> /* Read first page */
> scan_read_raw(mtd, buf, offs, mtd->writesize);
> - if (!check_pattern(buf, scanlen, mtd->writesize, td)) {
> + if (!check_pattern(mtd, buf, scanlen, mtd->writesize, td)) {
And what puts the BBT magic pattern into both erase blocks ?
Thanks,
tglx
More information about the linux-mtd
mailing list