Mercurial > nand-ecoscentric
changeset 2975:7050b2f79b6e
NAND bbt: fix internal race
| author | Ross Younger <wry@ecoscentric.com> |
|---|---|
| date | Tue, 10 Nov 2009 15:44:43 +0000 |
| parents | 54682dd5e6fe |
| children | 758f9d488949 |
| files | packages/io/nand/current/ChangeLog packages/io/nand/current/src/nand.c packages/io/nand/current/src/nand_bbt.c packages/io/nand/current/src/nand_bbt.h |
| diffstat | 4 files changed, 28 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/io/nand/current/ChangeLog +++ b/packages/io/nand/current/ChangeLog @@ -10,7 +10,7 @@ 2009-11-09 Ross Younger <wry@eCosCentr * tests: Update for interface tweak. * nand_bbt.c: Rationalise BBT finding into one place and fix to better cope with the situation where only one BBT block had - been written. + been written. Cure an internal race. * nand_ecc_mtd_fast.c: Speed up checking phase. 2009-11-06 Ross Younger <wry@eCosCentric.com>
--- a/packages/io/nand/current/src/nand.c +++ b/packages/io/nand/current/src/nand.c @@ -262,7 +262,7 @@ static int valid_page_addr(cyg_nand_part int cyg_nand_read_page(cyg_nand_partition *prt, cyg_nand_page_addr page, void * dest, void * spare, size_t spare_size) { - int rv; + int rv, locked=0; PARTITION_CHECK(prt); cyg_nand_device *dev = prt->dev; DEV_INIT_CHECK(dev); @@ -279,9 +279,12 @@ int cyg_nand_read_page(cyg_nand_partitio } #endif + LOCK_DEV(dev); + locked = 1; EG(nandi_read_whole_page_raw(dev, page, dest, spare, spare_size, 1)); err_exit: + if (locked) UNLOCK_DEV(dev); return rv; } @@ -297,7 +300,7 @@ int cyg_nand_read_part_page(cyg_nand_par cyg_nand_device *dev = prt->dev; DEV_INIT_CHECK(dev); CYG_BYTE *pagebuffer; - int got_pagebuf = 0; + int got_pagebuf = 0, locked = 0; if (offset + length > NAND_BYTES_PER_PAGE(dev)) return -EFBIG; @@ -311,6 +314,9 @@ int cyg_nand_read_part_page(cyg_nand_par } #endif + LOCK_DEV(dev); + locked = 1; + if (dev->fns->read_part_page && !check_ecc) { EG(dev->fns->read_part_page(dev, dest, page, offset, length)); } else { @@ -323,11 +329,13 @@ int cyg_nand_read_part_page(cyg_nand_par err_exit: if (got_pagebuf) nandi_release_pagebuf(); + if (locked) UNLOCK_DEV(dev); return rv; } -/* Internal, mostly-unchecked interface to read a page. */ +/* Internal, mostly-unchecked interface to read a page. + * Caller must hold the devlock! */ int nandi_read_whole_page_raw(cyg_nand_device *dev, cyg_nand_page_addr page, CYG_BYTE * dest, CYG_BYTE * spare, size_t spare_size, int check_ecc) @@ -353,8 +361,6 @@ int nandi_read_whole_page_raw(cyg_nand_d CYG_ASSERTC(NAND_BYTES_PER_PAGE(dev) % ecc_data_stride == 0); - LOCK_DEV(dev); - do { CYG_BYTE *data_dest = dest; CYG_BYTE *ecc_dest = ecc_calc; @@ -456,7 +462,6 @@ int nandi_read_whole_page_raw(cyg_nand_d break; } err_exit: - UNLOCK_DEV(dev); return rv; } @@ -465,7 +470,7 @@ err_exit: int cyg_nand_write_page(cyg_nand_partition *prt, cyg_nand_page_addr page, const void * src, const void * spare, size_t spare_size) { - int rv; + int rv, locked = 0; PARTITION_CHECK(prt); cyg_nand_device *dev = prt->dev; DEV_INIT_CHECK(dev); @@ -479,9 +484,12 @@ int cyg_nand_write_page(cyg_nand_partiti EG(-EINVAL); } #endif + LOCK_DEV(dev); + locked = 1; EG(nandi_write_page_raw(dev, page, src, spare, spare_size)); err_exit: + if (locked) UNLOCK_DEV(dev); return rv; } @@ -525,7 +533,6 @@ int nandi_write_page_raw(cyg_nand_device } } - LOCK_DEV(dev); EG(dev->fns->write_begin(dev, page)); if (src) { remain = NAND_BYTES_PER_PAGE(dev); @@ -553,7 +560,6 @@ int nandi_write_page_raw(cyg_nand_device * if ECC is being used. */ err_exit: - UNLOCK_DEV(dev); return rv; #endif }
--- a/packages/io/nand/current/src/nand_bbt.c +++ b/packages/io/nand/current/src/nand_bbt.c @@ -656,7 +656,8 @@ err_exit: } -/* Increments the BBT version, then writes out _both_ tables*/ +/* Increments the BBT version, then writes out _both_ tables. + * Caller must have the devlock. */ static int cyg_nand_bbti_write_tables(cyg_nand_device *dev, int is_initial) { int rv, retries=-1;
--- a/packages/io/nand/current/src/nand_bbt.h +++ b/packages/io/nand/current/src/nand_bbt.h @@ -80,16 +80,20 @@ typedef enum { * or -ve error code. */ int cyg_nand_bbti_query(cyg_nand_device *dev, cyg_nand_block_addr blk); -/* Marks a block as bad. Returns 0 for success, or -ve error code. */ +/* Marks a block as bad. Returns 0 for success, or -ve error code. + * Caller must have locked the devlock. */ int cyg_nand_bbti_markbad(cyg_nand_device *dev, cyg_nand_block_addr blk); /* Marks a block arbitrarily. Normal applications should never use this. - * Returns 0 for success, or -ve error code. */ + * Returns 0 for success, or -ve error code. + * Caller must have locked the devlock. */ int cyg_nand_bbti_markany(cyg_nand_device *dev, cyg_nand_block_addr blk, cyg_nand_bbt_status_t st); /* Looks to find the bad block table(s) on the chip and read them in. * Updates dev->bbt.* as appropriate. + * Caller must have locked the devlock or (more likely) the device not + * be accessible to callers yet (as we're running from nand_lookup). * * Returns: 0 if either or both were found; * -ENOENT if neither; @@ -99,6 +103,8 @@ int cyg_nand_bbti_find_tables(cyg_nand_d /* Creates the initial BBTs by running a scan for factory bad blocks. * Returns: 0 if OK, else a -ve error code. + * Caller must have locked the devlock or (more likely) the device not + * be accessible to callers yet (as we're running from nand_lookup). */ int cyg_nand_bbti_build_tables(cyg_nand_device *dev); @@ -116,11 +122,13 @@ int cyg_nand_bbti_build_tables(cyg_nand_ /* Raw unchecked NAND access, for use by the BBT ===================== */ +/* Caller must hold the devlock! */ int nandi_read_whole_page_raw(cyg_nand_device *dev, cyg_nand_page_addr page, CYG_BYTE * dest, CYG_BYTE * spare, size_t spare_size, int check_ecc); +/* Caller must hold the devlock! */ int nandi_write_page_raw(cyg_nand_device *dev, cyg_nand_page_addr page, const CYG_BYTE * src, const CYG_BYTE * spare, size_t spare_size);
