driver/mtd: get mtd_geometry_s.model for mtd partition and optimize code

Signed-off-by: dongjiuzhu1 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
dongjiuzhu1 2023-10-09 18:28:27 +08:00 committed by Xiang Xiao
parent a2be27ef7d
commit ed6fb11de6

View File

@ -73,10 +73,8 @@ struct mtd_partition_s
* entire FLASH */
off_t firstblock; /* Offset to the first block of the managed
* sub-region */
off_t neraseblocks; /* The number of erase blocks in the managed
* sub-region */
off_t blocksize; /* The size of one read/write block */
uint16_t blkpererase; /* Number of R/W blocks in one erase block */
struct mtd_geometry_s geo; /* The geometry for the partition */
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_PROCFS_EXCLUDE_PARTITIONS)
struct mtd_partition_s *pnext; /* Pointer to next partition struct */
@ -181,7 +179,7 @@ static bool part_blockcheck(FAR struct mtd_partition_s *priv, off_t block)
{
off_t partsize;
partsize = priv->neraseblocks * priv->blkpererase;
partsize = priv->geo.neraseblocks * priv->blkpererase;
return block < partsize;
}
@ -195,12 +193,10 @@ static bool part_blockcheck(FAR struct mtd_partition_s *priv, off_t block)
static bool part_bytecheck(FAR struct mtd_partition_s *priv, off_t byoff)
{
off_t erasesize;
off_t readend;
erasesize = priv->blocksize * priv->blkpererase;
readend = (byoff + erasesize - 1) / erasesize;
return readend <= priv->neraseblocks;
readend = (byoff + priv->geo.erasesize - 1) / priv->geo.erasesize;
return readend <= priv->geo.neraseblocks;
}
/****************************************************************************
@ -337,7 +333,7 @@ static ssize_t part_read(FAR struct mtd_dev_s *dev, off_t offset,
* underlying MTD driver perform the read.
*/
newoffset = offset + priv->firstblock * priv->blocksize;
newoffset = offset + priv->firstblock * priv->geo.blocksize;
return priv->parent->read(priv->parent, newoffset, nbytes, buffer);
}
@ -377,7 +373,7 @@ static ssize_t part_write(FAR struct mtd_dev_s *dev, off_t offset,
* underlying MTD driver perform the write.
*/
newoffset = offset + priv->firstblock * priv->blocksize;
newoffset = offset + priv->firstblock * priv->geo.blocksize;
return priv->parent->write(priv->parent, newoffset, nbytes, buffer);
}
@ -403,19 +399,11 @@ static int part_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
case MTDIOC_GEOMETRY:
{
FAR struct mtd_geometry_s *geo = (FAR struct mtd_geometry_s *)arg;
if (geo)
if (geo != NULL)
{
memset(geo, 0, sizeof(*geo));
/* Populate the geometry structure with information needed to
* know the capacity and how to access the device.
*/
geo->blocksize = priv->blocksize;
geo->erasesize = priv->blocksize * priv->blkpererase;
geo->neraseblocks = priv->neraseblocks;
memcpy(geo, &priv->geo, sizeof(*geo));
ret = OK;
}
}
}
break;
@ -425,8 +413,8 @@ static int part_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
(FAR struct partition_info_s *)arg;
if (info != NULL)
{
info->numsectors = priv->neraseblocks * priv->blkpererase;
info->sectorsize = priv->blocksize;
info->numsectors = priv->geo.neraseblocks * priv->blkpererase;
info->sectorsize = priv->geo.blocksize;
info->startsector = priv->firstblock;
strlcpy(info->parent, priv->parent->name,
@ -455,7 +443,7 @@ static int part_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
*/
*ppv = (FAR void *)(uintptr_t)
(base + priv->firstblock * priv->blocksize);
(base + priv->firstblock * priv->geo.blocksize);
}
}
}
@ -467,7 +455,7 @@ static int part_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
ret = priv->parent->erase(priv->parent,
priv->firstblock / priv->blkpererase,
priv->neraseblocks);
priv->geo.neraseblocks);
}
break;
@ -709,12 +697,12 @@ static ssize_t part_procfs_read(FAR struct file *filep, FAR char *buffer,
"%s%7ju %7ju %s\n",
partname,
(uintmax_t)attr->nextpart->firstblock / blkpererase,
(uintmax_t)attr->nextpart->neraseblocks,
(uintmax_t)attr->nextpart->geo.neraseblocks,
attr->nextpart->parent->name);
#else
ret = snprintf(&buffer[total], buflen - total, "%7ju %7ju %s\n",
(uintmax_t)attr->nextpart->firstblock / blkpererase,
(uintmax_t)attr->nextpart->neraseblocks,
(uintmax_t)attr->nextpart->geo.neraseblocks,
attr->nextpart->parent->name);
#endif
@ -846,53 +834,12 @@ FAR struct mtd_dev_s *mtd_partition(FAR struct mtd_dev_s *mtd,
off_t nblocks)
{
FAR struct mtd_partition_s *part;
FAR struct mtd_geometry_s geo;
unsigned int blkpererase;
off_t erasestart;
off_t eraseend;
int ret;
DEBUGASSERT(mtd);
/* Get the geometry of the FLASH device */
ret = mtd->ioctl(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&geo));
if (ret < 0)
{
ferr("ERROR: mtd->ioctl failed: %d\n", ret);
return NULL;
}
/* Get the number of blocks per erase. There must be an even number of
* blocks in one erase blocks.
*/
blkpererase = geo.erasesize / geo.blocksize;
DEBUGASSERT(blkpererase * geo.blocksize == geo.erasesize);
/* Adjust the offset and size if necessary so that they are multiples of
* the erase block size (making sure that we do not go outside of the
* requested sub-region). NOTE that 'eraseend' is the first erase block
* beyond the sub-region.
*/
erasestart = (firstblock + blkpererase - 1) / blkpererase;
eraseend = (firstblock + nblocks) / blkpererase;
if (erasestart >= eraseend)
{
ferr("ERROR: sub-region too small\n");
return NULL;
}
/* Verify that the sub-region is valid for this geometry */
if (eraseend > geo.neraseblocks)
{
ferr("ERROR: sub-region too big\n");
return NULL;
}
/* Allocate a partition device structure */
part = (FAR struct mtd_partition_s *)
@ -903,6 +850,50 @@ FAR struct mtd_dev_s *mtd_partition(FAR struct mtd_dev_s *mtd,
return NULL;
}
/* Get the geometry of the FLASH device */
ret = mtd->ioctl(mtd, MTDIOC_GEOMETRY,
(unsigned long)((uintptr_t)&part->geo));
if (ret < 0)
{
ferr("ERROR: mtd->ioctl failed: %d\n", ret);
kmm_free(part);
return NULL;
}
/* Get the number of blocks per erase. There must be an even number of
* blocks in one erase blocks.
*/
part->blkpererase = part->geo.erasesize / part->geo.blocksize;
DEBUGASSERT(part->blkpererase * part->geo.blocksize ==
part->geo.erasesize);
/* Adjust the offset and size if necessary so that they are multiples of
* the erase block size (making sure that we do not go outside of the
* requested sub-region). NOTE that 'eraseend' is the first erase block
* beyond the sub-region.
*/
erasestart = (firstblock + part->blkpererase - 1) / part->blkpererase;
eraseend = (firstblock + nblocks) / part->blkpererase;
if (erasestart >= eraseend)
{
ferr("ERROR: sub-region too small\n");
kmm_free(part);
return NULL;
}
/* Verify that the sub-region is valid for this geometry */
if (eraseend > part->geo.neraseblocks)
{
ferr("ERROR: sub-region too big\n");
kmm_free(part);
return NULL;
}
/* Initialize the partition device structure. (unsupported methods were
* nullified by kmm_zalloc).
*/
@ -920,10 +911,8 @@ FAR struct mtd_dev_s *mtd_partition(FAR struct mtd_dev_s *mtd,
part->child.name = "part";
part->parent = mtd;
part->firstblock = erasestart * blkpererase;
part->neraseblocks = eraseend - erasestart;
part->blocksize = geo.blocksize;
part->blkpererase = blkpererase;
part->firstblock = erasestart * part->blkpererase;
part->geo.neraseblocks = eraseend - erasestart;
#ifdef CONFIG_MTD_PARTITION_NAMES
strlcpy(part->name, "(noname)", sizeof(part->name));