Skip to content

Commit

Permalink
mtd: nand: add 'oob_required' argument to NAND {read,write}_page inte…
Browse files Browse the repository at this point in the history
…rfaces

New NAND controllers can perform read/write via HW engines which don't expose
OOB data in their DMA mode. To reflect this, we should rework the nand_chip /
nand_ecc_ctrl interfaces that assume that drivers will always read/write OOB
data in the nand_chip.oob_poi buffer. A better interface includes a boolean
argument that explicitly tells the callee when OOB data is requested by the
calling layer (for reading/writing to/from nand_chip.oob_poi).

This patch adds the 'oob_required' parameter to each relevant {read,write}_page
interface; all 'oob_required' parameters are left unused for now. The next
patch will set the parameter properly in the nand_base.c callers, and follow-up
patches will make use of 'oob_required' in some of the callee functions.

Note that currently, there is no harm in ignoring the 'oob_required' parameter
and *always* utilizing nand_chip.oob_poi, but there can be
performance/complexity/design benefits from avoiding filling oob_poi in the
common case. I will try to implement this for some drivers which can be ported
easily.

Note: I couldn't compile-test all of these easily, as some had ARCH
dependencies.

[dwmw2: Merge later 1/0 vs. true/false cleanup]
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Reviewed-by: Shmulik Ladkani <shmulik.ladkani@gmail.com>
Acked-by: Jiandong Zheng <jdzheng@broadcom.com>
Acked-by: Mike Dunn <mikedunn@newsguy.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
  • Loading branch information
Brian Norris authored and David Woodhouse committed May 14, 2012
1 parent b4f7aa8 commit 1fbb938
Show file tree
Hide file tree
Showing 15 changed files with 90 additions and 72 deletions.
5 changes: 3 additions & 2 deletions drivers/mtd/nand/atmel_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,10 @@ static int atmel_nand_calculate(struct mtd_info *mtd,
* mtd: mtd info structure
* chip: nand chip info structure
* buf: buffer to store read data
* oob_required: caller expects OOB data read to chip->oob_poi
*/
static int atmel_nand_read_page(struct mtd_info *mtd,
struct nand_chip *chip, uint8_t *buf, int page)
static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
{
int eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
Expand Down
10 changes: 6 additions & 4 deletions drivers/mtd/nand/bcm_umi_bch.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@

/* ---- Private Function Prototypes -------------------------------------- */
static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, uint8_t *buf, int page);
struct nand_chip *chip, uint8_t *buf, int oob_required, int page);
static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf);
struct nand_chip *chip, const uint8_t *buf, int oob_required);

/* ---- Private Variables ------------------------------------------------ */

Expand Down Expand Up @@ -103,11 +103,12 @@ static struct nand_ecclayout nand_hw_eccoob_4096 = {
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: buffer to store read data
* @oob_required: caller expects OOB data read to chip->oob_poi
*
***************************************************************************/
static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, uint8_t * buf,
int page)
int oob_required, int page)
{
int sectorIdx = 0;
int eccsize = chip->ecc.size;
Expand Down Expand Up @@ -190,10 +191,11 @@ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd,
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
*
***************************************************************************/
static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf)
struct nand_chip *chip, const uint8_t *buf, int oob_required)
{
int sectorIdx = 0;
int eccsize = chip->ecc.size;
Expand Down
2 changes: 1 addition & 1 deletion drivers/mtd/nand/bcm_umi_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ static int bcm_umi_nand_verify_buf(struct mtd_info *mtd, const u_char * buf,
* for MLC parts which may have permanently stuck bits.
*/
struct nand_chip *chip = mtd->priv;
int ret = chip->ecc.read_page(mtd, chip, readbackbuf, 0);
int ret = chip->ecc.read_page(mtd, chip, readbackbuf, 0, 0);
if (ret < 0)
return -EFAULT;
else {
Expand Down
4 changes: 2 additions & 2 deletions drivers/mtd/nand/bf5xx_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd,
}

static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page)
uint8_t *buf, int oob_required, int page)
{
bf5xx_nand_read_buf(mtd, buf, mtd->writesize);
bf5xx_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize);
Expand All @@ -567,7 +567,7 @@ static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip
}

static void bf5xx_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf)
const uint8_t *buf, int oob_required)
{
bf5xx_nand_write_buf(mtd, buf, mtd->writesize);
bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
Expand Down
13 changes: 8 additions & 5 deletions drivers/mtd/nand/cafe_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,12 +375,13 @@ static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: buffer to store read data
* @oob_required: caller expects OOB data read to chip->oob_poi
*
* The hw generator calculates the error syndrome automatically. Therefor
* we need a special oob layout and handling.
*/
static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page)
uint8_t *buf, int oob_required, int page)
{
struct cafe_priv *cafe = mtd->priv;
unsigned int max_bitflips = 0;
Expand Down Expand Up @@ -520,7 +521,8 @@ static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = {


static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf)
struct nand_chip *chip,
const uint8_t *buf, int oob_required)
{
struct cafe_priv *cafe = mtd->priv;

Expand All @@ -532,16 +534,17 @@ static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
}

static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int page, int cached, int raw)
const uint8_t *buf, int oob_required, int page,
int cached, int raw)
{
int status;

chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);

if (unlikely(raw))
chip->ecc.write_page_raw(mtd, chip, buf);
chip->ecc.write_page_raw(mtd, chip, buf, oob_required);
else
chip->ecc.write_page(mtd, chip, buf);
chip->ecc.write_page(mtd, chip, buf, oob_required);

/*
* Cached progamming disabled for now, Not sure if its worth the
Expand Down
8 changes: 4 additions & 4 deletions drivers/mtd/nand/denali.c
Original file line number Diff line number Diff line change
Expand Up @@ -1087,7 +1087,7 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
* by write_page above.
* */
static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf)
const uint8_t *buf, int oob_required)
{
/* for regular page writes, we let HW handle all the ECC
* data written to the device. */
Expand All @@ -1099,7 +1099,7 @@ static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip,
* write_page() function above.
*/
static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf)
const uint8_t *buf, int oob_required)
{
/* for raw page writes, we want to disable ECC and simply write
whatever data is in the buffer. */
Expand All @@ -1122,7 +1122,7 @@ static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
}

static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page)
uint8_t *buf, int oob_required, int page)
{
unsigned int max_bitflips;
struct denali_nand_info *denali = mtd_to_denali(mtd);
Expand Down Expand Up @@ -1175,7 +1175,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
}

static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page)
uint8_t *buf, int oob_required, int page)
{
struct denali_nand_info *denali = mtd_to_denali(mtd);

Expand Down
12 changes: 6 additions & 6 deletions drivers/mtd/nand/docg4.c
Original file line number Diff line number Diff line change
Expand Up @@ -787,13 +787,13 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand,


static int docg4_read_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
uint8_t *buf, int page)
uint8_t *buf, int oob_required, int page)
{
return read_page(mtd, nand, buf, page, false);
}

static int docg4_read_page(struct mtd_info *mtd, struct nand_chip *nand,
uint8_t *buf, int page)
uint8_t *buf, int oob_required, int page)
{
return read_page(mtd, nand, buf, page, true);
}
Expand Down Expand Up @@ -953,13 +953,13 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *nand,
}

static void docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
const uint8_t *buf)
const uint8_t *buf, int oob_required)
{
return write_page(mtd, nand, buf, false);
}

static void docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand,
const uint8_t *buf)
const uint8_t *buf, int oob_required)
{
return write_page(mtd, nand, buf, true);
}
Expand Down Expand Up @@ -1003,7 +1003,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd)
return -ENOMEM;

read_page_prologue(mtd, g4_addr);
status = docg4_read_page(mtd, nand, buf, DOCG4_FACTORY_BBT_PAGE);
status = docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE);
if (status)
goto exit;

Expand Down Expand Up @@ -1080,7 +1080,7 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs)

/* write first page of block */
write_page_prologue(mtd, g4_addr);
docg4_write_page(mtd, nand, buf);
docg4_write_page(mtd, nand, buf, 1);
ret = pageprog(mtd);
if (!ret)
mtd->ecc_stats.badblocks++;
Expand Down
11 changes: 4 additions & 7 deletions drivers/mtd/nand/fsl_elbc_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -746,10 +746,8 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
return 0;
}

static int fsl_elbc_read_page(struct mtd_info *mtd,
struct nand_chip *chip,
uint8_t *buf,
int page)
static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
{
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_lbc_ctrl *ctrl = priv->ctrl;
Expand All @@ -767,9 +765,8 @@ static int fsl_elbc_read_page(struct mtd_info *mtd,
/* ECC will be calculated automatically, and errors will be detected in
* waitfunc.
*/
static void fsl_elbc_write_page(struct mtd_info *mtd,
struct nand_chip *chip,
const uint8_t *buf)
static void fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required)
{
fsl_elbc_write_buf(mtd, buf, mtd->writesize);
fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
Expand Down
10 changes: 4 additions & 6 deletions drivers/mtd/nand/fsl_ifc_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -698,9 +698,8 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
return nand_fsr | NAND_STATUS_WP;
}

static int fsl_ifc_read_page(struct mtd_info *mtd,
struct nand_chip *chip,
uint8_t *buf, int page)
static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
{
struct fsl_ifc_mtd *priv = chip->priv;
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Expand All @@ -721,9 +720,8 @@ static int fsl_ifc_read_page(struct mtd_info *mtd,
/* ECC will be calculated automatically, and errors will be detected in
* waitfunc.
*/
static void fsl_ifc_write_page(struct mtd_info *mtd,
struct nand_chip *chip,
const uint8_t *buf)
static void fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required)
{
fsl_ifc_write_buf(mtd, buf, mtd->writesize);
fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
Expand Down
3 changes: 2 additions & 1 deletion drivers/mtd/nand/fsmc_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,7 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf,
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: buffer to store read data
* @oob_required: caller expects OOB data read to chip->oob_poi
* @page: page number to read
*
* This routine is needed for fsmc version 8 as reading from NAND chip has to be
Expand All @@ -701,7 +702,7 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf,
* max of 8 bits)
*/
static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page)
uint8_t *buf, int oob_required, int page)
{
struct fsmc_nand_data *host = container_of(mtd,
struct fsmc_nand_data, mtd);
Expand Down
8 changes: 4 additions & 4 deletions drivers/mtd/nand/gpmi-nand/gpmi-nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -842,7 +842,7 @@ static void block_mark_swapping(struct gpmi_nand_data *this,
}

static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page)
uint8_t *buf, int oob_required, int page)
{
struct gpmi_nand_data *this = chip->priv;
struct bch_geometry *nfc_geo = &this->bch_geometry;
Expand Down Expand Up @@ -928,8 +928,8 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
return ret;
}

static void gpmi_ecc_write_page(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf)
static void gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required)
{
struct gpmi_nand_data *this = chip->priv;
struct bch_geometry *nfc_geo = &this->bch_geometry;
Expand Down Expand Up @@ -1309,7 +1309,7 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
/* Write the first page of the current stride. */
dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page);
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
chip->ecc.write_page_raw(mtd, chip, buffer);
chip->ecc.write_page_raw(mtd, chip, buffer, 0);
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);

/* Wait for the write to finish. */
Expand Down
Loading

0 comments on commit 1fbb938

Please sign in to comment.