mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-22 15:11:33 +00:00
mtd: add mtd_ooblayout_xxx() helper functions
In order to make the ecclayout definition completely dynamic we need to rework the way the OOB layout are defined and iterated. Create a few mtd_ooblayout_xxx() helpers to ease OOB bytes manipulation and hide ecclayout internals to their users. Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> [Linux commit: 75eb2cec251fda33c9bb716ecc372819abb9278a] [masahiro: cherry-pick more code from adbbc3bc827eb1f43a932d783f09ba55c8ec8379] Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
This commit is contained in:
parent
1fb87de83d
commit
13f3b04f61
2 changed files with 417 additions and 0 deletions
|
@ -1005,6 +1005,366 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mtd_read_oob);
|
EXPORT_SYMBOL_GPL(mtd_read_oob);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mtd_ooblayout_ecc - Get the OOB region definition of a specific ECC section
|
||||||
|
* @mtd: MTD device structure
|
||||||
|
* @section: ECC section. Depending on the layout you may have all the ECC
|
||||||
|
* bytes stored in a single contiguous section, or one section
|
||||||
|
* per ECC chunk (and sometime several sections for a single ECC
|
||||||
|
* ECC chunk)
|
||||||
|
* @oobecc: OOB region struct filled with the appropriate ECC position
|
||||||
|
* information
|
||||||
|
*
|
||||||
|
* This function returns ECC section information in the OOB area. If you want
|
||||||
|
* to get all the ECC bytes information, then you should call
|
||||||
|
* mtd_ooblayout_ecc(mtd, section++, oobecc) until it returns -ERANGE.
|
||||||
|
*
|
||||||
|
* Returns zero on success, a negative error code otherwise.
|
||||||
|
*/
|
||||||
|
int mtd_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||||
|
struct mtd_oob_region *oobecc)
|
||||||
|
{
|
||||||
|
memset(oobecc, 0, sizeof(*oobecc));
|
||||||
|
|
||||||
|
if (!mtd || section < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!mtd->ooblayout || !mtd->ooblayout->ecc)
|
||||||
|
return -ENOTSUPP;
|
||||||
|
|
||||||
|
return mtd->ooblayout->ecc(mtd, section, oobecc);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mtd_ooblayout_ecc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mtd_ooblayout_free - Get the OOB region definition of a specific free
|
||||||
|
* section
|
||||||
|
* @mtd: MTD device structure
|
||||||
|
* @section: Free section you are interested in. Depending on the layout
|
||||||
|
* you may have all the free bytes stored in a single contiguous
|
||||||
|
* section, or one section per ECC chunk plus an extra section
|
||||||
|
* for the remaining bytes (or other funky layout).
|
||||||
|
* @oobfree: OOB region struct filled with the appropriate free position
|
||||||
|
* information
|
||||||
|
*
|
||||||
|
* This function returns free bytes position in the OOB area. If you want
|
||||||
|
* to get all the free bytes information, then you should call
|
||||||
|
* mtd_ooblayout_free(mtd, section++, oobfree) until it returns -ERANGE.
|
||||||
|
*
|
||||||
|
* Returns zero on success, a negative error code otherwise.
|
||||||
|
*/
|
||||||
|
int mtd_ooblayout_free(struct mtd_info *mtd, int section,
|
||||||
|
struct mtd_oob_region *oobfree)
|
||||||
|
{
|
||||||
|
memset(oobfree, 0, sizeof(*oobfree));
|
||||||
|
|
||||||
|
if (!mtd || section < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!mtd->ooblayout || !mtd->ooblayout->free)
|
||||||
|
return -ENOTSUPP;
|
||||||
|
|
||||||
|
return mtd->ooblayout->free(mtd, section, oobfree);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mtd_ooblayout_free);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mtd_ooblayout_find_region - Find the region attached to a specific byte
|
||||||
|
* @mtd: mtd info structure
|
||||||
|
* @byte: the byte we are searching for
|
||||||
|
* @sectionp: pointer where the section id will be stored
|
||||||
|
* @oobregion: used to retrieve the ECC position
|
||||||
|
* @iter: iterator function. Should be either mtd_ooblayout_free or
|
||||||
|
* mtd_ooblayout_ecc depending on the region type you're searching for
|
||||||
|
*
|
||||||
|
* This function returns the section id and oobregion information of a
|
||||||
|
* specific byte. For example, say you want to know where the 4th ECC byte is
|
||||||
|
* stored, you'll use:
|
||||||
|
*
|
||||||
|
* mtd_ooblayout_find_region(mtd, 3, §ion, &oobregion, mtd_ooblayout_ecc);
|
||||||
|
*
|
||||||
|
* Returns zero on success, a negative error code otherwise.
|
||||||
|
*/
|
||||||
|
static int mtd_ooblayout_find_region(struct mtd_info *mtd, int byte,
|
||||||
|
int *sectionp, struct mtd_oob_region *oobregion,
|
||||||
|
int (*iter)(struct mtd_info *,
|
||||||
|
int section,
|
||||||
|
struct mtd_oob_region *oobregion))
|
||||||
|
{
|
||||||
|
int pos = 0, ret, section = 0;
|
||||||
|
|
||||||
|
memset(oobregion, 0, sizeof(*oobregion));
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
ret = iter(mtd, section, oobregion);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (pos + oobregion->length > byte)
|
||||||
|
break;
|
||||||
|
|
||||||
|
pos += oobregion->length;
|
||||||
|
section++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adjust region info to make it start at the beginning at the
|
||||||
|
* 'start' ECC byte.
|
||||||
|
*/
|
||||||
|
oobregion->offset += byte - pos;
|
||||||
|
oobregion->length -= byte - pos;
|
||||||
|
*sectionp = section;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mtd_ooblayout_find_eccregion - Find the ECC region attached to a specific
|
||||||
|
* ECC byte
|
||||||
|
* @mtd: mtd info structure
|
||||||
|
* @eccbyte: the byte we are searching for
|
||||||
|
* @sectionp: pointer where the section id will be stored
|
||||||
|
* @oobregion: OOB region information
|
||||||
|
*
|
||||||
|
* Works like mtd_ooblayout_find_region() except it searches for a specific ECC
|
||||||
|
* byte.
|
||||||
|
*
|
||||||
|
* Returns zero on success, a negative error code otherwise.
|
||||||
|
*/
|
||||||
|
int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte,
|
||||||
|
int *section,
|
||||||
|
struct mtd_oob_region *oobregion)
|
||||||
|
{
|
||||||
|
return mtd_ooblayout_find_region(mtd, eccbyte, section, oobregion,
|
||||||
|
mtd_ooblayout_ecc);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mtd_ooblayout_find_eccregion);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mtd_ooblayout_get_bytes - Extract OOB bytes from the oob buffer
|
||||||
|
* @mtd: mtd info structure
|
||||||
|
* @buf: destination buffer to store OOB bytes
|
||||||
|
* @oobbuf: OOB buffer
|
||||||
|
* @start: first byte to retrieve
|
||||||
|
* @nbytes: number of bytes to retrieve
|
||||||
|
* @iter: section iterator
|
||||||
|
*
|
||||||
|
* Extract bytes attached to a specific category (ECC or free)
|
||||||
|
* from the OOB buffer and copy them into buf.
|
||||||
|
*
|
||||||
|
* Returns zero on success, a negative error code otherwise.
|
||||||
|
*/
|
||||||
|
static int mtd_ooblayout_get_bytes(struct mtd_info *mtd, u8 *buf,
|
||||||
|
const u8 *oobbuf, int start, int nbytes,
|
||||||
|
int (*iter)(struct mtd_info *,
|
||||||
|
int section,
|
||||||
|
struct mtd_oob_region *oobregion))
|
||||||
|
{
|
||||||
|
struct mtd_oob_region oobregion;
|
||||||
|
int section, ret;
|
||||||
|
|
||||||
|
ret = mtd_ooblayout_find_region(mtd, start, §ion,
|
||||||
|
&oobregion, iter);
|
||||||
|
|
||||||
|
while (!ret) {
|
||||||
|
int cnt;
|
||||||
|
|
||||||
|
cnt = min_t(int, nbytes, oobregion.length);
|
||||||
|
memcpy(buf, oobbuf + oobregion.offset, cnt);
|
||||||
|
buf += cnt;
|
||||||
|
nbytes -= cnt;
|
||||||
|
|
||||||
|
if (!nbytes)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = iter(mtd, ++section, &oobregion);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mtd_ooblayout_set_bytes - put OOB bytes into the oob buffer
|
||||||
|
* @mtd: mtd info structure
|
||||||
|
* @buf: source buffer to get OOB bytes from
|
||||||
|
* @oobbuf: OOB buffer
|
||||||
|
* @start: first OOB byte to set
|
||||||
|
* @nbytes: number of OOB bytes to set
|
||||||
|
* @iter: section iterator
|
||||||
|
*
|
||||||
|
* Fill the OOB buffer with data provided in buf. The category (ECC or free)
|
||||||
|
* is selected by passing the appropriate iterator.
|
||||||
|
*
|
||||||
|
* Returns zero on success, a negative error code otherwise.
|
||||||
|
*/
|
||||||
|
static int mtd_ooblayout_set_bytes(struct mtd_info *mtd, const u8 *buf,
|
||||||
|
u8 *oobbuf, int start, int nbytes,
|
||||||
|
int (*iter)(struct mtd_info *,
|
||||||
|
int section,
|
||||||
|
struct mtd_oob_region *oobregion))
|
||||||
|
{
|
||||||
|
struct mtd_oob_region oobregion;
|
||||||
|
int section, ret;
|
||||||
|
|
||||||
|
ret = mtd_ooblayout_find_region(mtd, start, §ion,
|
||||||
|
&oobregion, iter);
|
||||||
|
|
||||||
|
while (!ret) {
|
||||||
|
int cnt;
|
||||||
|
|
||||||
|
cnt = min_t(int, nbytes, oobregion.length);
|
||||||
|
memcpy(oobbuf + oobregion.offset, buf, cnt);
|
||||||
|
buf += cnt;
|
||||||
|
nbytes -= cnt;
|
||||||
|
|
||||||
|
if (!nbytes)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = iter(mtd, ++section, &oobregion);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mtd_ooblayout_count_bytes - count the number of bytes in a OOB category
|
||||||
|
* @mtd: mtd info structure
|
||||||
|
* @iter: category iterator
|
||||||
|
*
|
||||||
|
* Count the number of bytes in a given category.
|
||||||
|
*
|
||||||
|
* Returns a positive value on success, a negative error code otherwise.
|
||||||
|
*/
|
||||||
|
static int mtd_ooblayout_count_bytes(struct mtd_info *mtd,
|
||||||
|
int (*iter)(struct mtd_info *,
|
||||||
|
int section,
|
||||||
|
struct mtd_oob_region *oobregion))
|
||||||
|
{
|
||||||
|
struct mtd_oob_region oobregion;
|
||||||
|
int section = 0, ret, nbytes = 0;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
ret = iter(mtd, section++, &oobregion);
|
||||||
|
if (ret) {
|
||||||
|
if (ret == -ERANGE)
|
||||||
|
ret = nbytes;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nbytes += oobregion.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mtd_ooblayout_get_eccbytes - extract ECC bytes from the oob buffer
|
||||||
|
* @mtd: mtd info structure
|
||||||
|
* @eccbuf: destination buffer to store ECC bytes
|
||||||
|
* @oobbuf: OOB buffer
|
||||||
|
* @start: first ECC byte to retrieve
|
||||||
|
* @nbytes: number of ECC bytes to retrieve
|
||||||
|
*
|
||||||
|
* Works like mtd_ooblayout_get_bytes(), except it acts on ECC bytes.
|
||||||
|
*
|
||||||
|
* Returns zero on success, a negative error code otherwise.
|
||||||
|
*/
|
||||||
|
int mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf,
|
||||||
|
const u8 *oobbuf, int start, int nbytes)
|
||||||
|
{
|
||||||
|
return mtd_ooblayout_get_bytes(mtd, eccbuf, oobbuf, start, nbytes,
|
||||||
|
mtd_ooblayout_ecc);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mtd_ooblayout_get_eccbytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mtd_ooblayout_set_eccbytes - set ECC bytes into the oob buffer
|
||||||
|
* @mtd: mtd info structure
|
||||||
|
* @eccbuf: source buffer to get ECC bytes from
|
||||||
|
* @oobbuf: OOB buffer
|
||||||
|
* @start: first ECC byte to set
|
||||||
|
* @nbytes: number of ECC bytes to set
|
||||||
|
*
|
||||||
|
* Works like mtd_ooblayout_set_bytes(), except it acts on ECC bytes.
|
||||||
|
*
|
||||||
|
* Returns zero on success, a negative error code otherwise.
|
||||||
|
*/
|
||||||
|
int mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf,
|
||||||
|
u8 *oobbuf, int start, int nbytes)
|
||||||
|
{
|
||||||
|
return mtd_ooblayout_set_bytes(mtd, eccbuf, oobbuf, start, nbytes,
|
||||||
|
mtd_ooblayout_ecc);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mtd_ooblayout_set_eccbytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mtd_ooblayout_get_databytes - extract data bytes from the oob buffer
|
||||||
|
* @mtd: mtd info structure
|
||||||
|
* @databuf: destination buffer to store ECC bytes
|
||||||
|
* @oobbuf: OOB buffer
|
||||||
|
* @start: first ECC byte to retrieve
|
||||||
|
* @nbytes: number of ECC bytes to retrieve
|
||||||
|
*
|
||||||
|
* Works like mtd_ooblayout_get_bytes(), except it acts on free bytes.
|
||||||
|
*
|
||||||
|
* Returns zero on success, a negative error code otherwise.
|
||||||
|
*/
|
||||||
|
int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf,
|
||||||
|
const u8 *oobbuf, int start, int nbytes)
|
||||||
|
{
|
||||||
|
return mtd_ooblayout_get_bytes(mtd, databuf, oobbuf, start, nbytes,
|
||||||
|
mtd_ooblayout_free);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mtd_ooblayout_get_databytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mtd_ooblayout_get_eccbytes - set data bytes into the oob buffer
|
||||||
|
* @mtd: mtd info structure
|
||||||
|
* @eccbuf: source buffer to get data bytes from
|
||||||
|
* @oobbuf: OOB buffer
|
||||||
|
* @start: first ECC byte to set
|
||||||
|
* @nbytes: number of ECC bytes to set
|
||||||
|
*
|
||||||
|
* Works like mtd_ooblayout_get_bytes(), except it acts on free bytes.
|
||||||
|
*
|
||||||
|
* Returns zero on success, a negative error code otherwise.
|
||||||
|
*/
|
||||||
|
int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf,
|
||||||
|
u8 *oobbuf, int start, int nbytes)
|
||||||
|
{
|
||||||
|
return mtd_ooblayout_set_bytes(mtd, databuf, oobbuf, start, nbytes,
|
||||||
|
mtd_ooblayout_free);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mtd_ooblayout_set_databytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mtd_ooblayout_count_freebytes - count the number of free bytes in OOB
|
||||||
|
* @mtd: mtd info structure
|
||||||
|
*
|
||||||
|
* Works like mtd_ooblayout_count_bytes(), except it count free bytes.
|
||||||
|
*
|
||||||
|
* Returns zero on success, a negative error code otherwise.
|
||||||
|
*/
|
||||||
|
int mtd_ooblayout_count_freebytes(struct mtd_info *mtd)
|
||||||
|
{
|
||||||
|
return mtd_ooblayout_count_bytes(mtd, mtd_ooblayout_free);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mtd_ooblayout_count_freebytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mtd_ooblayout_count_freebytes - count the number of ECC bytes in OOB
|
||||||
|
* @mtd: mtd info structure
|
||||||
|
*
|
||||||
|
* Works like mtd_ooblayout_count_bytes(), except it count ECC bytes.
|
||||||
|
*
|
||||||
|
* Returns zero on success, a negative error code otherwise.
|
||||||
|
*/
|
||||||
|
int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd)
|
||||||
|
{
|
||||||
|
return mtd_ooblayout_count_bytes(mtd, mtd_ooblayout_ecc);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mtd_ooblayout_count_eccbytes);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Method to access the protection register area, present in some flash
|
* Method to access the protection register area, present in some flash
|
||||||
* devices. The user data is one time programmable but the factory data is read
|
* devices. The user data is one time programmable but the factory data is read
|
||||||
|
|
|
@ -103,6 +103,36 @@ struct mtd_oob_ops {
|
||||||
#else
|
#else
|
||||||
#define MTD_MAX_ECCPOS_ENTRIES_LARGE 680
|
#define MTD_MAX_ECCPOS_ENTRIES_LARGE 680
|
||||||
#endif
|
#endif
|
||||||
|
/**
|
||||||
|
* struct mtd_oob_region - oob region definition
|
||||||
|
* @offset: region offset
|
||||||
|
* @length: region length
|
||||||
|
*
|
||||||
|
* This structure describes a region of the OOB area, and is used
|
||||||
|
* to retrieve ECC or free bytes sections.
|
||||||
|
* Each section is defined by an offset within the OOB area and a
|
||||||
|
* length.
|
||||||
|
*/
|
||||||
|
struct mtd_oob_region {
|
||||||
|
u32 offset;
|
||||||
|
u32 length;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* struct mtd_ooblayout_ops - NAND OOB layout operations
|
||||||
|
* @ecc: function returning an ECC region in the OOB area.
|
||||||
|
* Should return -ERANGE if %section exceeds the total number of
|
||||||
|
* ECC sections.
|
||||||
|
* @free: function returning a free region in the OOB area.
|
||||||
|
* Should return -ERANGE if %section exceeds the total number of
|
||||||
|
* free sections.
|
||||||
|
*/
|
||||||
|
struct mtd_ooblayout_ops {
|
||||||
|
int (*ecc)(struct mtd_info *mtd, int section,
|
||||||
|
struct mtd_oob_region *oobecc);
|
||||||
|
int (*free)(struct mtd_info *mtd, int section,
|
||||||
|
struct mtd_oob_region *oobfree);
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internal ECC layout control structure. For historical reasons, there is a
|
* Internal ECC layout control structure. For historical reasons, there is a
|
||||||
|
@ -179,6 +209,9 @@ struct mtd_info {
|
||||||
#endif
|
#endif
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
|
/* OOB layout description */
|
||||||
|
const struct mtd_ooblayout_ops *ooblayout;
|
||||||
|
|
||||||
/* ECC layout structure pointer - read only! */
|
/* ECC layout structure pointer - read only! */
|
||||||
struct nand_ecclayout *ecclayout;
|
struct nand_ecclayout *ecclayout;
|
||||||
|
|
||||||
|
@ -278,6 +311,30 @@ struct mtd_info {
|
||||||
int usecount;
|
int usecount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int mtd_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||||
|
struct mtd_oob_region *oobecc);
|
||||||
|
int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte,
|
||||||
|
int *section,
|
||||||
|
struct mtd_oob_region *oobregion);
|
||||||
|
int mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf,
|
||||||
|
const u8 *oobbuf, int start, int nbytes);
|
||||||
|
int mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf,
|
||||||
|
u8 *oobbuf, int start, int nbytes);
|
||||||
|
int mtd_ooblayout_free(struct mtd_info *mtd, int section,
|
||||||
|
struct mtd_oob_region *oobfree);
|
||||||
|
int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf,
|
||||||
|
const u8 *oobbuf, int start, int nbytes);
|
||||||
|
int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf,
|
||||||
|
u8 *oobbuf, int start, int nbytes);
|
||||||
|
int mtd_ooblayout_count_freebytes(struct mtd_info *mtd);
|
||||||
|
int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd);
|
||||||
|
|
||||||
|
static inline void mtd_set_ooblayout(struct mtd_info *mtd,
|
||||||
|
const struct mtd_ooblayout_ops *ooblayout)
|
||||||
|
{
|
||||||
|
mtd->ooblayout = ooblayout;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
|
static inline int mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
|
||||||
{
|
{
|
||||||
return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
|
return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
|
||||||
|
|
Loading…
Add table
Reference in a new issue