Merge tag '4.9/mtd-pairing-scheme' of github.com:linux-nand/linux
Introduction of the MTD pairing scheme concept.
This commit is contained in:
@@ -375,6 +375,110 @@ static int mtd_reboot_notifier(struct notifier_block *n, unsigned long state,
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* mtd_wunit_to_pairing_info - get pairing information of a wunit
|
||||
* @mtd: pointer to new MTD device info structure
|
||||
* @wunit: write unit we are interested in
|
||||
* @info: returned pairing information
|
||||
*
|
||||
* Retrieve pairing information associated to the wunit.
|
||||
* This is mainly useful when dealing with MLC/TLC NANDs where pages can be
|
||||
* paired together, and where programming a page may influence the page it is
|
||||
* paired with.
|
||||
* The notion of page is replaced by the term wunit (write-unit) to stay
|
||||
* consistent with the ->writesize field.
|
||||
*
|
||||
* The @wunit argument can be extracted from an absolute offset using
|
||||
* mtd_offset_to_wunit(). @info is filled with the pairing information attached
|
||||
* to @wunit.
|
||||
*
|
||||
* From the pairing info the MTD user can find all the wunits paired with
|
||||
* @wunit using the following loop:
|
||||
*
|
||||
* for (i = 0; i < mtd_pairing_groups(mtd); i++) {
|
||||
* info.pair = i;
|
||||
* mtd_pairing_info_to_wunit(mtd, &info);
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit,
|
||||
struct mtd_pairing_info *info)
|
||||
{
|
||||
int npairs = mtd_wunit_per_eb(mtd) / mtd_pairing_groups(mtd);
|
||||
|
||||
if (wunit < 0 || wunit >= npairs)
|
||||
return -EINVAL;
|
||||
|
||||
if (mtd->pairing && mtd->pairing->get_info)
|
||||
return mtd->pairing->get_info(mtd, wunit, info);
|
||||
|
||||
info->group = 0;
|
||||
info->pair = wunit;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtd_wunit_to_pairing_info);
|
||||
|
||||
/**
|
||||
* mtd_wunit_to_pairing_info - get wunit from pairing information
|
||||
* @mtd: pointer to new MTD device info structure
|
||||
* @info: pairing information struct
|
||||
*
|
||||
* Returns a positive number representing the wunit associated to the info
|
||||
* struct, or a negative error code.
|
||||
*
|
||||
* This is the reverse of mtd_wunit_to_pairing_info(), and can help one to
|
||||
* iterate over all wunits of a given pair (see mtd_wunit_to_pairing_info()
|
||||
* doc).
|
||||
*
|
||||
* It can also be used to only program the first page of each pair (i.e.
|
||||
* page attached to group 0), which allows one to use an MLC NAND in
|
||||
* software-emulated SLC mode:
|
||||
*
|
||||
* info.group = 0;
|
||||
* npairs = mtd_wunit_per_eb(mtd) / mtd_pairing_groups(mtd);
|
||||
* for (info.pair = 0; info.pair < npairs; info.pair++) {
|
||||
* wunit = mtd_pairing_info_to_wunit(mtd, &info);
|
||||
* mtd_write(mtd, mtd_wunit_to_offset(mtd, blkoffs, wunit),
|
||||
* mtd->writesize, &retlen, buf + (i * mtd->writesize));
|
||||
* }
|
||||
*/
|
||||
int mtd_pairing_info_to_wunit(struct mtd_info *mtd,
|
||||
const struct mtd_pairing_info *info)
|
||||
{
|
||||
int ngroups = mtd_pairing_groups(mtd);
|
||||
int npairs = mtd_wunit_per_eb(mtd) / ngroups;
|
||||
|
||||
if (!info || info->pair < 0 || info->pair >= npairs ||
|
||||
info->group < 0 || info->group >= ngroups)
|
||||
return -EINVAL;
|
||||
|
||||
if (mtd->pairing && mtd->pairing->get_wunit)
|
||||
return mtd->pairing->get_wunit(mtd, info);
|
||||
|
||||
return info->pair;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtd_pairing_info_to_wunit);
|
||||
|
||||
/**
|
||||
* mtd_pairing_groups - get the number of pairing groups
|
||||
* @mtd: pointer to new MTD device info structure
|
||||
*
|
||||
* Returns the number of pairing groups.
|
||||
*
|
||||
* This number is usually equal to the number of bits exposed by a single
|
||||
* cell, and can be used in conjunction with mtd_pairing_info_to_wunit()
|
||||
* to iterate over all pages of a given pair.
|
||||
*/
|
||||
int mtd_pairing_groups(struct mtd_info *mtd)
|
||||
{
|
||||
if (!mtd->pairing || !mtd->pairing->ngroups)
|
||||
return 1;
|
||||
|
||||
return mtd->pairing->ngroups;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtd_pairing_groups);
|
||||
|
||||
/**
|
||||
* add_mtd_device - register an MTD device
|
||||
* @mtd: pointer to new MTD device info structure
|
||||
|
@@ -409,6 +409,7 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
|
||||
slave->mtd.oobsize = master->oobsize;
|
||||
slave->mtd.oobavail = master->oobavail;
|
||||
slave->mtd.subpage_sft = master->subpage_sft;
|
||||
slave->mtd.pairing = master->pairing;
|
||||
|
||||
slave->mtd.name = name;
|
||||
slave->mtd.owner = master->owner;
|
||||
|
Reference in New Issue
Block a user