mirror of
https://github.com/torvalds/linux.git
synced 2026-05-29 09:33:31 +02:00
mtd: nand: Introduce a block iterator
In order to be able to iterate easily across eraseblocks rather than pages, let's introduce a block iterator inspired from the page iterator. The main usage of this iterator will be for continuous/sequential reads, where it is interesting to use a single request rather than split the requests in smaller chunks (ie. pages) that can be hardly optimized. So a "continuous" boolean get's added for this purpose. Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Link: https://lore.kernel.org/linux-mtd/20240826101412.20644-3-miquel.raynal@bootlin.com
This commit is contained in:
parent
3f4c0ad490
commit
8adf1ac24b
|
|
@ -103,6 +103,8 @@ enum nand_page_io_req_type {
|
|||
* @ooblen: the number of OOB bytes to read from/write to this page
|
||||
* @oobbuf: buffer to store OOB data in or get OOB data from
|
||||
* @mode: one of the %MTD_OPS_XXX mode
|
||||
* @continuous: no need to start over the operation at the end of each page, the
|
||||
* NAND device will automatically prepare the next one
|
||||
*
|
||||
* This object is used to pass per-page I/O requests to NAND sub-layers. This
|
||||
* way all useful information are already formatted in a useful way and
|
||||
|
|
@ -125,6 +127,7 @@ struct nand_page_io_req {
|
|||
void *in;
|
||||
} oobbuf;
|
||||
int mode;
|
||||
bool continuous;
|
||||
};
|
||||
|
||||
const struct mtd_ooblayout_ops *nand_get_small_page_ooblayout(void);
|
||||
|
|
@ -937,6 +940,43 @@ static inline void nanddev_io_page_iter_init(struct nand_device *nand,
|
|||
iter->req.ooblen = min_t(unsigned int,
|
||||
iter->oobbytes_per_page - iter->req.ooboffs,
|
||||
iter->oobleft);
|
||||
iter->req.continuous = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* nand_io_block_iter_init - Initialize a NAND I/O iterator
|
||||
* @nand: NAND device
|
||||
* @offs: absolute offset
|
||||
* @req: MTD request
|
||||
* @iter: NAND I/O iterator
|
||||
*
|
||||
* Initializes a NAND iterator based on the information passed by the MTD
|
||||
* layer for block jumps (no OOB)
|
||||
*
|
||||
* In practice only reads may leverage this iterator.
|
||||
*/
|
||||
static inline void nanddev_io_block_iter_init(struct nand_device *nand,
|
||||
enum nand_page_io_req_type reqtype,
|
||||
loff_t offs, struct mtd_oob_ops *req,
|
||||
struct nand_io_iter *iter)
|
||||
{
|
||||
unsigned int offs_in_eb;
|
||||
|
||||
iter->req.type = reqtype;
|
||||
iter->req.mode = req->mode;
|
||||
iter->req.dataoffs = nanddev_offs_to_pos(nand, offs, &iter->req.pos);
|
||||
iter->req.ooboffs = 0;
|
||||
iter->oobbytes_per_page = 0;
|
||||
iter->dataleft = req->len;
|
||||
iter->oobleft = 0;
|
||||
iter->req.databuf.in = req->datbuf;
|
||||
offs_in_eb = (nand->memorg.pagesize * iter->req.pos.page) + iter->req.dataoffs;
|
||||
iter->req.datalen = min_t(unsigned int,
|
||||
nanddev_eraseblock_size(nand) - offs_in_eb,
|
||||
iter->dataleft);
|
||||
iter->req.oobbuf.in = NULL;
|
||||
iter->req.ooblen = 0;
|
||||
iter->req.continuous = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -962,6 +1002,25 @@ static inline void nanddev_io_iter_next_page(struct nand_device *nand,
|
|||
iter->oobleft);
|
||||
}
|
||||
|
||||
/**
|
||||
* nand_io_iter_next_block - Move to the next block
|
||||
* @nand: NAND device
|
||||
* @iter: NAND I/O iterator
|
||||
*
|
||||
* Updates the @iter to point to the next block.
|
||||
* No OOB handling available.
|
||||
*/
|
||||
static inline void nanddev_io_iter_next_block(struct nand_device *nand,
|
||||
struct nand_io_iter *iter)
|
||||
{
|
||||
nanddev_pos_next_eraseblock(nand, &iter->req.pos);
|
||||
iter->dataleft -= iter->req.datalen;
|
||||
iter->req.databuf.in += iter->req.datalen;
|
||||
iter->req.dataoffs = 0;
|
||||
iter->req.datalen = min_t(unsigned int, nanddev_eraseblock_size(nand),
|
||||
iter->dataleft);
|
||||
}
|
||||
|
||||
/**
|
||||
* nand_io_iter_end - Should end iteration or not
|
||||
* @nand: NAND device
|
||||
|
|
@ -997,6 +1056,21 @@ static inline bool nanddev_io_iter_end(struct nand_device *nand,
|
|||
!nanddev_io_iter_end(nand, iter); \
|
||||
nanddev_io_iter_next_page(nand, iter))
|
||||
|
||||
/**
|
||||
* nand_io_for_each_block - Iterate over all NAND pages contained in an MTD I/O
|
||||
* request, one block at a time
|
||||
* @nand: NAND device
|
||||
* @start: start address to read/write from
|
||||
* @req: MTD I/O request
|
||||
* @iter: NAND I/O iterator
|
||||
*
|
||||
* Should be used for iterating over blocks that are contained in an MTD request.
|
||||
*/
|
||||
#define nanddev_io_for_each_block(nand, type, start, req, iter) \
|
||||
for (nanddev_io_block_iter_init(nand, type, start, req, iter); \
|
||||
!nanddev_io_iter_end(nand, iter); \
|
||||
nanddev_io_iter_next_block(nand, iter))
|
||||
|
||||
bool nanddev_isbad(struct nand_device *nand, const struct nand_pos *pos);
|
||||
bool nanddev_isreserved(struct nand_device *nand, const struct nand_pos *pos);
|
||||
int nanddev_markbad(struct nand_device *nand, const struct nand_pos *pos);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user