forked from Minki/linux
mtd: rawnand: Reorganize code to avoid forward declarations
Avoid forward declaration of nand_get_device(), nand_do_write_oob() and nand_update_bbt() by moving functions around. Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com> Tested-by: Janusz Krzysztofik <jmkrzyszt@gmail.com> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
This commit is contained in:
parent
0813621ba8
commit
99f3351a6d
@ -49,11 +49,6 @@
|
|||||||
|
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
|
|
||||||
static int nand_get_device(struct nand_chip *chip, int new_state);
|
|
||||||
|
|
||||||
static int nand_do_write_oob(struct nand_chip *chip, loff_t to,
|
|
||||||
struct mtd_oob_ops *ops);
|
|
||||||
|
|
||||||
/* Define default oob placement schemes for large and small page devices */
|
/* Define default oob placement schemes for large and small page devices */
|
||||||
static int nand_ooblayout_ecc_sp(struct mtd_info *mtd, int section,
|
static int nand_ooblayout_ecc_sp(struct mtd_info *mtd, int section,
|
||||||
struct mtd_oob_region *oobregion)
|
struct mtd_oob_region *oobregion)
|
||||||
@ -286,6 +281,197 @@ static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs)
|
||||||
|
{
|
||||||
|
if (chip->legacy.block_bad)
|
||||||
|
return chip->legacy.block_bad(chip, ofs);
|
||||||
|
|
||||||
|
return nand_block_bad(chip, ofs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* panic_nand_get_device - [GENERIC] Get chip for selected access
|
||||||
|
* @chip: the nand chip descriptor
|
||||||
|
* @new_state: the state which is requested
|
||||||
|
*
|
||||||
|
* Used when in panic, no locks are taken.
|
||||||
|
*/
|
||||||
|
static void panic_nand_get_device(struct nand_chip *chip, int new_state)
|
||||||
|
{
|
||||||
|
/* Hardware controller shared among independent devices */
|
||||||
|
chip->controller->active = chip;
|
||||||
|
chip->state = new_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nand_get_device - [GENERIC] Get chip for selected access
|
||||||
|
* @chip: NAND chip structure
|
||||||
|
* @new_state: the state which is requested
|
||||||
|
*
|
||||||
|
* Get the device and lock it for exclusive access
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
nand_get_device(struct nand_chip *chip, int new_state)
|
||||||
|
{
|
||||||
|
spinlock_t *lock = &chip->controller->lock;
|
||||||
|
wait_queue_head_t *wq = &chip->controller->wq;
|
||||||
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
|
retry:
|
||||||
|
spin_lock(lock);
|
||||||
|
|
||||||
|
/* Hardware controller shared among independent devices */
|
||||||
|
if (!chip->controller->active)
|
||||||
|
chip->controller->active = chip;
|
||||||
|
|
||||||
|
if (chip->controller->active == chip && chip->state == FL_READY) {
|
||||||
|
chip->state = new_state;
|
||||||
|
spin_unlock(lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (new_state == FL_PM_SUSPENDED) {
|
||||||
|
if (chip->controller->active->state == FL_PM_SUSPENDED) {
|
||||||
|
chip->state = FL_PM_SUSPENDED;
|
||||||
|
spin_unlock(lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||||
|
add_wait_queue(wq, &wait);
|
||||||
|
spin_unlock(lock);
|
||||||
|
schedule();
|
||||||
|
remove_wait_queue(wq, &wait);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nand_check_wp - [GENERIC] check if the chip is write protected
|
||||||
|
* @chip: NAND chip object
|
||||||
|
*
|
||||||
|
* Check, if the device is write protected. The function expects, that the
|
||||||
|
* device is already selected.
|
||||||
|
*/
|
||||||
|
static int nand_check_wp(struct nand_chip *chip)
|
||||||
|
{
|
||||||
|
u8 status;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Broken xD cards report WP despite being writable */
|
||||||
|
if (chip->options & NAND_BROKEN_XD)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Check the WP bit */
|
||||||
|
ret = nand_status_op(chip, &status);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return status & NAND_STATUS_WP ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nand_fill_oob - [INTERN] Transfer client buffer to oob
|
||||||
|
* @oob: oob data buffer
|
||||||
|
* @len: oob data write length
|
||||||
|
* @ops: oob ops structure
|
||||||
|
*/
|
||||||
|
static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len,
|
||||||
|
struct mtd_oob_ops *ops)
|
||||||
|
{
|
||||||
|
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialise to all 0xFF, to avoid the possibility of left over OOB
|
||||||
|
* data from a previous OOB read.
|
||||||
|
*/
|
||||||
|
memset(chip->oob_poi, 0xff, mtd->oobsize);
|
||||||
|
|
||||||
|
switch (ops->mode) {
|
||||||
|
|
||||||
|
case MTD_OPS_PLACE_OOB:
|
||||||
|
case MTD_OPS_RAW:
|
||||||
|
memcpy(chip->oob_poi + ops->ooboffs, oob, len);
|
||||||
|
return oob + len;
|
||||||
|
|
||||||
|
case MTD_OPS_AUTO_OOB:
|
||||||
|
ret = mtd_ooblayout_set_databytes(mtd, oob, chip->oob_poi,
|
||||||
|
ops->ooboffs, len);
|
||||||
|
BUG_ON(ret);
|
||||||
|
return oob + len;
|
||||||
|
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nand_do_write_oob - [MTD Interface] NAND write out-of-band
|
||||||
|
* @chip: NAND chip object
|
||||||
|
* @to: offset to write to
|
||||||
|
* @ops: oob operation description structure
|
||||||
|
*
|
||||||
|
* NAND write out-of-band.
|
||||||
|
*/
|
||||||
|
static int nand_do_write_oob(struct nand_chip *chip, loff_t to,
|
||||||
|
struct mtd_oob_ops *ops)
|
||||||
|
{
|
||||||
|
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||||
|
int chipnr, page, status, len;
|
||||||
|
|
||||||
|
pr_debug("%s: to = 0x%08x, len = %i\n",
|
||||||
|
__func__, (unsigned int)to, (int)ops->ooblen);
|
||||||
|
|
||||||
|
len = mtd_oobavail(mtd, ops);
|
||||||
|
|
||||||
|
/* Do not allow write past end of page */
|
||||||
|
if ((ops->ooboffs + ops->ooblen) > len) {
|
||||||
|
pr_debug("%s: attempt to write past end of page\n",
|
||||||
|
__func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
chipnr = (int)(to >> chip->chip_shift);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset the chip. Some chips (like the Toshiba TC5832DC found in one
|
||||||
|
* of my DiskOnChip 2000 test units) will clear the whole data page too
|
||||||
|
* if we don't do this. I have no clue why, but I seem to have 'fixed'
|
||||||
|
* it in the doc2000 driver in August 1999. dwmw2.
|
||||||
|
*/
|
||||||
|
nand_reset(chip, chipnr);
|
||||||
|
|
||||||
|
chip->select_chip(chip, chipnr);
|
||||||
|
|
||||||
|
/* Shift to get page */
|
||||||
|
page = (int)(to >> chip->page_shift);
|
||||||
|
|
||||||
|
/* Check, if it is write protected */
|
||||||
|
if (nand_check_wp(chip)) {
|
||||||
|
chip->select_chip(chip, -1);
|
||||||
|
return -EROFS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invalidate the page cache, if we write to the cached page */
|
||||||
|
if (page == chip->pagebuf)
|
||||||
|
chip->pagebuf = -1;
|
||||||
|
|
||||||
|
nand_fill_oob(chip, ops->oobbuf, ops->ooblen, ops);
|
||||||
|
|
||||||
|
if (ops->mode == MTD_OPS_RAW)
|
||||||
|
status = chip->ecc.write_oob_raw(chip, page & chip->pagemask);
|
||||||
|
else
|
||||||
|
status = chip->ecc.write_oob(chip, page & chip->pagemask);
|
||||||
|
|
||||||
|
chip->select_chip(chip, -1);
|
||||||
|
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
ops->oobretlen = ops->ooblen;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nand_default_block_markbad - [DEFAULT] mark a block bad via bad block marker
|
* nand_default_block_markbad - [DEFAULT] mark a block bad via bad block marker
|
||||||
* @chip: NAND chip object
|
* @chip: NAND chip object
|
||||||
@ -341,14 +527,6 @@ int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs)
|
|||||||
return nand_default_block_markbad(chip, ofs);
|
return nand_default_block_markbad(chip, ofs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs)
|
|
||||||
{
|
|
||||||
if (chip->legacy.block_bad)
|
|
||||||
return chip->legacy.block_bad(chip, ofs);
|
|
||||||
|
|
||||||
return nand_block_bad(chip, ofs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nand_block_markbad_lowlevel - mark a block bad
|
* nand_block_markbad_lowlevel - mark a block bad
|
||||||
* @chip: NAND chip object
|
* @chip: NAND chip object
|
||||||
@ -401,30 +579,6 @@ static int nand_block_markbad_lowlevel(struct nand_chip *chip, loff_t ofs)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* nand_check_wp - [GENERIC] check if the chip is write protected
|
|
||||||
* @chip: NAND chip object
|
|
||||||
*
|
|
||||||
* Check, if the device is write protected. The function expects, that the
|
|
||||||
* device is already selected.
|
|
||||||
*/
|
|
||||||
static int nand_check_wp(struct nand_chip *chip)
|
|
||||||
{
|
|
||||||
u8 status;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* Broken xD cards report WP despite being writable */
|
|
||||||
if (chip->options & NAND_BROKEN_XD)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Check the WP bit */
|
|
||||||
ret = nand_status_op(chip, &status);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return status & NAND_STATUS_WP ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nand_block_isreserved - [GENERIC] Check if a block is marked reserved.
|
* nand_block_isreserved - [GENERIC] Check if a block is marked reserved.
|
||||||
* @mtd: MTD device structure
|
* @mtd: MTD device structure
|
||||||
@ -555,60 +709,6 @@ int nand_gpio_waitrdy(struct nand_chip *chip, struct gpio_desc *gpiod,
|
|||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(nand_gpio_waitrdy);
|
EXPORT_SYMBOL_GPL(nand_gpio_waitrdy);
|
||||||
|
|
||||||
/**
|
|
||||||
* panic_nand_get_device - [GENERIC] Get chip for selected access
|
|
||||||
* @chip: the nand chip descriptor
|
|
||||||
* @new_state: the state which is requested
|
|
||||||
*
|
|
||||||
* Used when in panic, no locks are taken.
|
|
||||||
*/
|
|
||||||
static void panic_nand_get_device(struct nand_chip *chip, int new_state)
|
|
||||||
{
|
|
||||||
/* Hardware controller shared among independent devices */
|
|
||||||
chip->controller->active = chip;
|
|
||||||
chip->state = new_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* nand_get_device - [GENERIC] Get chip for selected access
|
|
||||||
* @chip: NAND chip structure
|
|
||||||
* @new_state: the state which is requested
|
|
||||||
*
|
|
||||||
* Get the device and lock it for exclusive access
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
nand_get_device(struct nand_chip *chip, int new_state)
|
|
||||||
{
|
|
||||||
spinlock_t *lock = &chip->controller->lock;
|
|
||||||
wait_queue_head_t *wq = &chip->controller->wq;
|
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
|
||||||
retry:
|
|
||||||
spin_lock(lock);
|
|
||||||
|
|
||||||
/* Hardware controller shared among independent devices */
|
|
||||||
if (!chip->controller->active)
|
|
||||||
chip->controller->active = chip;
|
|
||||||
|
|
||||||
if (chip->controller->active == chip && chip->state == FL_READY) {
|
|
||||||
chip->state = new_state;
|
|
||||||
spin_unlock(lock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (new_state == FL_PM_SUSPENDED) {
|
|
||||||
if (chip->controller->active->state == FL_PM_SUSPENDED) {
|
|
||||||
chip->state = FL_PM_SUSPENDED;
|
|
||||||
spin_unlock(lock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
|
||||||
add_wait_queue(wq, &wait);
|
|
||||||
spin_unlock(lock);
|
|
||||||
schedule();
|
|
||||||
remove_wait_queue(wq, &wait);
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* panic_nand_wait - [GENERIC] wait until the command is done
|
* panic_nand_wait - [GENERIC] wait until the command is done
|
||||||
* @chip: NAND chip structure
|
* @chip: NAND chip structure
|
||||||
@ -3807,44 +3907,6 @@ static int nand_write_page(struct nand_chip *chip, uint32_t offset,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* nand_fill_oob - [INTERN] Transfer client buffer to oob
|
|
||||||
* @chip: NAND chip object
|
|
||||||
* @oob: oob data buffer
|
|
||||||
* @len: oob data write length
|
|
||||||
* @ops: oob ops structure
|
|
||||||
*/
|
|
||||||
static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len,
|
|
||||||
struct mtd_oob_ops *ops)
|
|
||||||
{
|
|
||||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialise to all 0xFF, to avoid the possibility of left over OOB
|
|
||||||
* data from a previous OOB read.
|
|
||||||
*/
|
|
||||||
memset(chip->oob_poi, 0xff, mtd->oobsize);
|
|
||||||
|
|
||||||
switch (ops->mode) {
|
|
||||||
|
|
||||||
case MTD_OPS_PLACE_OOB:
|
|
||||||
case MTD_OPS_RAW:
|
|
||||||
memcpy(chip->oob_poi + ops->ooboffs, oob, len);
|
|
||||||
return oob + len;
|
|
||||||
|
|
||||||
case MTD_OPS_AUTO_OOB:
|
|
||||||
ret = mtd_ooblayout_set_databytes(mtd, oob, chip->oob_poi,
|
|
||||||
ops->ooboffs, len);
|
|
||||||
BUG_ON(ret);
|
|
||||||
return oob + len;
|
|
||||||
|
|
||||||
default:
|
|
||||||
BUG();
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define NOTALIGNED(x) ((x & (chip->subpagesize - 1)) != 0)
|
#define NOTALIGNED(x) ((x & (chip->subpagesize - 1)) != 0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4012,74 +4074,6 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* nand_do_write_oob - [MTD Interface] NAND write out-of-band
|
|
||||||
* @chip: NAND chip object
|
|
||||||
* @to: offset to write to
|
|
||||||
* @ops: oob operation description structure
|
|
||||||
*
|
|
||||||
* NAND write out-of-band.
|
|
||||||
*/
|
|
||||||
static int nand_do_write_oob(struct nand_chip *chip, loff_t to,
|
|
||||||
struct mtd_oob_ops *ops)
|
|
||||||
{
|
|
||||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
|
||||||
int chipnr, page, status, len;
|
|
||||||
|
|
||||||
pr_debug("%s: to = 0x%08x, len = %i\n",
|
|
||||||
__func__, (unsigned int)to, (int)ops->ooblen);
|
|
||||||
|
|
||||||
len = mtd_oobavail(mtd, ops);
|
|
||||||
|
|
||||||
/* Do not allow write past end of page */
|
|
||||||
if ((ops->ooboffs + ops->ooblen) > len) {
|
|
||||||
pr_debug("%s: attempt to write past end of page\n",
|
|
||||||
__func__);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
chipnr = (int)(to >> chip->chip_shift);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reset the chip. Some chips (like the Toshiba TC5832DC found in one
|
|
||||||
* of my DiskOnChip 2000 test units) will clear the whole data page too
|
|
||||||
* if we don't do this. I have no clue why, but I seem to have 'fixed'
|
|
||||||
* it in the doc2000 driver in August 1999. dwmw2.
|
|
||||||
*/
|
|
||||||
nand_reset(chip, chipnr);
|
|
||||||
|
|
||||||
chip->select_chip(chip, chipnr);
|
|
||||||
|
|
||||||
/* Shift to get page */
|
|
||||||
page = (int)(to >> chip->page_shift);
|
|
||||||
|
|
||||||
/* Check, if it is write protected */
|
|
||||||
if (nand_check_wp(chip)) {
|
|
||||||
chip->select_chip(chip, -1);
|
|
||||||
return -EROFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Invalidate the page cache, if we write to the cached page */
|
|
||||||
if (page == chip->pagebuf)
|
|
||||||
chip->pagebuf = -1;
|
|
||||||
|
|
||||||
nand_fill_oob(chip, ops->oobbuf, ops->ooblen, ops);
|
|
||||||
|
|
||||||
if (ops->mode == MTD_OPS_RAW)
|
|
||||||
status = chip->ecc.write_oob_raw(chip, page & chip->pagemask);
|
|
||||||
else
|
|
||||||
status = chip->ecc.write_oob(chip, page & chip->pagemask);
|
|
||||||
|
|
||||||
chip->select_chip(chip, -1);
|
|
||||||
|
|
||||||
if (status)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
ops->oobretlen = ops->ooblen;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nand_write_oob - [MTD Interface] NAND write data and/or out-of-band
|
* nand_write_oob - [MTD Interface] NAND write data and/or out-of-band
|
||||||
* @mtd: MTD device structure
|
* @mtd: MTD device structure
|
||||||
|
@ -77,8 +77,6 @@
|
|||||||
#define BBT_ENTRY_MASK 0x03
|
#define BBT_ENTRY_MASK 0x03
|
||||||
#define BBT_ENTRY_SHIFT 2
|
#define BBT_ENTRY_SHIFT 2
|
||||||
|
|
||||||
static int nand_update_bbt(struct nand_chip *chip, loff_t offs);
|
|
||||||
|
|
||||||
static inline uint8_t bbt_get_entry(struct nand_chip *chip, int block)
|
static inline uint8_t bbt_get_entry(struct nand_chip *chip, int block)
|
||||||
{
|
{
|
||||||
uint8_t entry = chip->bbt[block >> BBT_ENTRY_SHIFT];
|
uint8_t entry = chip->bbt[block >> BBT_ENTRY_SHIFT];
|
||||||
@ -1034,6 +1032,61 @@ static int check_create(struct nand_chip *this, uint8_t *buf,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nand_update_bbt - update bad block table(s)
|
||||||
|
* @this: the NAND device
|
||||||
|
* @offs: the offset of the newly marked block
|
||||||
|
*
|
||||||
|
* The function updates the bad block table(s).
|
||||||
|
*/
|
||||||
|
static int nand_update_bbt(struct nand_chip *this, loff_t offs)
|
||||||
|
{
|
||||||
|
struct mtd_info *mtd = nand_to_mtd(this);
|
||||||
|
int len, res = 0;
|
||||||
|
int chip, chipsel;
|
||||||
|
uint8_t *buf;
|
||||||
|
struct nand_bbt_descr *td = this->bbt_td;
|
||||||
|
struct nand_bbt_descr *md = this->bbt_md;
|
||||||
|
|
||||||
|
if (!this->bbt || !td)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Allocate a temporary buffer for one eraseblock incl. oob */
|
||||||
|
len = (1 << this->bbt_erase_shift);
|
||||||
|
len += (len >> this->page_shift) * mtd->oobsize;
|
||||||
|
buf = kmalloc(len, GFP_KERNEL);
|
||||||
|
if (!buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* Do we have a bbt per chip? */
|
||||||
|
if (td->options & NAND_BBT_PERCHIP) {
|
||||||
|
chip = (int)(offs >> this->chip_shift);
|
||||||
|
chipsel = chip;
|
||||||
|
} else {
|
||||||
|
chip = 0;
|
||||||
|
chipsel = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
td->version[chip]++;
|
||||||
|
if (md)
|
||||||
|
md->version[chip]++;
|
||||||
|
|
||||||
|
/* Write the bad block table to the device? */
|
||||||
|
if (td->options & NAND_BBT_WRITE) {
|
||||||
|
res = write_bbt(this, buf, td, md, chipsel);
|
||||||
|
if (res < 0)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/* Write the mirror bad block table to the device? */
|
||||||
|
if (md && (md->options & NAND_BBT_WRITE)) {
|
||||||
|
res = write_bbt(this, buf, md, td, chipsel);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
kfree(buf);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mark_bbt_regions - [GENERIC] mark the bad block table regions
|
* mark_bbt_regions - [GENERIC] mark the bad block table regions
|
||||||
* @this: the NAND device
|
* @this: the NAND device
|
||||||
@ -1220,61 +1273,6 @@ err:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* nand_update_bbt - update bad block table(s)
|
|
||||||
* @this: the NAND device
|
|
||||||
* @offs: the offset of the newly marked block
|
|
||||||
*
|
|
||||||
* The function updates the bad block table(s).
|
|
||||||
*/
|
|
||||||
static int nand_update_bbt(struct nand_chip *this, loff_t offs)
|
|
||||||
{
|
|
||||||
struct mtd_info *mtd = nand_to_mtd(this);
|
|
||||||
int len, res = 0;
|
|
||||||
int chip, chipsel;
|
|
||||||
uint8_t *buf;
|
|
||||||
struct nand_bbt_descr *td = this->bbt_td;
|
|
||||||
struct nand_bbt_descr *md = this->bbt_md;
|
|
||||||
|
|
||||||
if (!this->bbt || !td)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* Allocate a temporary buffer for one eraseblock incl. oob */
|
|
||||||
len = (1 << this->bbt_erase_shift);
|
|
||||||
len += (len >> this->page_shift) * mtd->oobsize;
|
|
||||||
buf = kmalloc(len, GFP_KERNEL);
|
|
||||||
if (!buf)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
/* Do we have a bbt per chip? */
|
|
||||||
if (td->options & NAND_BBT_PERCHIP) {
|
|
||||||
chip = (int)(offs >> this->chip_shift);
|
|
||||||
chipsel = chip;
|
|
||||||
} else {
|
|
||||||
chip = 0;
|
|
||||||
chipsel = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
td->version[chip]++;
|
|
||||||
if (md)
|
|
||||||
md->version[chip]++;
|
|
||||||
|
|
||||||
/* Write the bad block table to the device? */
|
|
||||||
if (td->options & NAND_BBT_WRITE) {
|
|
||||||
res = write_bbt(this, buf, td, md, chipsel);
|
|
||||||
if (res < 0)
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
/* Write the mirror bad block table to the device? */
|
|
||||||
if (md && (md->options & NAND_BBT_WRITE)) {
|
|
||||||
res = write_bbt(this, buf, md, td, chipsel);
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
kfree(buf);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define some generic bad / good block scan pattern which are used
|
* Define some generic bad / good block scan pattern which are used
|
||||||
* while scanning a device for factory marked good / bad blocks.
|
* while scanning a device for factory marked good / bad blocks.
|
||||||
|
Loading…
Reference in New Issue
Block a user