drivers/rwbuffer: Avoid ftl driver allocate the temporary erase buffer
If the buffer to be flushed isn't multipled by the erase size, let's pad the buffer proactively to avoid the allocation in ftl. Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com> Change-Id: I6d7904aafab93a7886a594319d65826b81cd3cd1 3Change-Id: I88276149cc7826e7416929ca60b06314e96079a6
This commit is contained in:
parent
ae6ae113eb
commit
73723dd31c
@ -519,7 +519,7 @@ static int ftl_ioctl(FAR struct inode *inode, int cmd, unsigned long arg)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Just change the BIOC_XIPBASE command to the MTDIOC_XIPBASE command. */
|
||||
/* Change the BIOC_XIPBASE command to the MTDIOC_XIPBASE command. */
|
||||
|
||||
cmd = MTDIOC_XIPBASE;
|
||||
}
|
||||
@ -638,18 +638,19 @@ int ftl_initialize_by_path(FAR const char *path, FAR struct mtd_dev_s *mtd)
|
||||
/* Configure read-ahead/write buffering */
|
||||
|
||||
#ifdef FTL_HAVE_RWBUFFER
|
||||
dev->rwb.blocksize = dev->geo.blocksize;
|
||||
dev->rwb.nblocks = dev->geo.neraseblocks * dev->blkper;
|
||||
dev->rwb.dev = (FAR void *)dev;
|
||||
dev->rwb.wrflush = ftl_flush;
|
||||
dev->rwb.rhreload = ftl_reload;
|
||||
dev->rwb.blocksize = dev->geo.blocksize;
|
||||
dev->rwb.nblocks = dev->geo.neraseblocks * dev->blkper;
|
||||
dev->rwb.dev = (FAR void *)dev;
|
||||
dev->rwb.wrflush = ftl_flush;
|
||||
dev->rwb.rhreload = ftl_reload;
|
||||
|
||||
#if defined(CONFIG_FTL_WRITEBUFFER)
|
||||
dev->rwb.wrmaxblocks = dev->blkper;
|
||||
dev->rwb.wrmaxblocks = dev->blkper;
|
||||
dev->rwb.wralignblocks = dev->blkper;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FTL_READAHEAD
|
||||
dev->rwb.rhmaxblocks = dev->blkper;
|
||||
dev->rwb.rhmaxblocks = dev->blkper;
|
||||
#endif
|
||||
|
||||
ret = rwb_initialize(&dev->rwb);
|
||||
|
@ -55,6 +55,13 @@
|
||||
# error "Worker thread support is required (CONFIG_SCHED_WORKQUEUE)"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t rwb_read_(FAR struct rwbuffer_s *rwb, off_t startblock,
|
||||
size_t nblocks, FAR uint8_t *rdbuffer);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
@ -134,8 +141,8 @@ static inline void rwb_resetwrbuffer(FAR struct rwbuffer_s *rwb)
|
||||
{
|
||||
/* We assume that the caller holds the wrsem */
|
||||
|
||||
rwb->wrnblocks = 0;
|
||||
rwb->wrblockstart = (off_t)-1;
|
||||
rwb->wrnblocks = 0;
|
||||
rwb->wrblockstart = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -154,8 +161,19 @@ static void rwb_wrflush(FAR struct rwbuffer_s *rwb)
|
||||
|
||||
if (rwb->wrnblocks > 0)
|
||||
{
|
||||
size_t padblocks;
|
||||
|
||||
finfo("Flushing: blockstart=0x%08lx nblocks=%d from buffer=%p\n",
|
||||
(long)rwb->wrblockstart, rwb->wrnblocks, rwb->wrbuffer);
|
||||
(long)rwb->wrblockstart, rwb->wrnblocks, rwb->wrbuffer);
|
||||
|
||||
padblocks = rwb->wrnblocks % rwb->wralignblocks;
|
||||
if (padblocks)
|
||||
{
|
||||
padblocks = rwb->wralignblocks - padblocks;
|
||||
rwb_read_(rwb, rwb->wrblockstart + rwb->wrnblocks, padblocks,
|
||||
&rwb->wrbuffer[rwb->wrnblocks * rwb->blocksize]);
|
||||
rwb->wrnblocks += padblocks;
|
||||
}
|
||||
|
||||
/* Flush cache. On success, the flush method will return the number
|
||||
* of blocks written. Anything other than the number requested is
|
||||
@ -370,15 +388,7 @@ static ssize_t rwb_writebuffer(FAR struct rwbuffer_s *rwb,
|
||||
{
|
||||
/* Flush the write buffer */
|
||||
|
||||
if (rwb->wrnblocks > 0)
|
||||
{
|
||||
ssize_t ret = rwb->wrflush(rwb->dev, rwb->wrbuffer,
|
||||
rwb->wrblockstart, rwb->wrnblocks);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
rwb_wrflush(rwb);
|
||||
|
||||
/* Buffer the data in the write buffer */
|
||||
|
||||
@ -406,7 +416,7 @@ static inline void rwb_resetrhbuffer(FAR struct rwbuffer_s *rwb)
|
||||
/* We assume that the caller holds the readAheadBufferSemphore */
|
||||
|
||||
rwb->rhnblocks = 0;
|
||||
rwb->rhblockstart = (off_t)-1;
|
||||
rwb->rhblockstart = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -800,6 +810,14 @@ int rwb_initialize(FAR struct rwbuffer_s *rwb)
|
||||
{
|
||||
finfo("Initialize the write buffer\n");
|
||||
|
||||
if (rwb->wralignblocks == 0)
|
||||
{
|
||||
rwb->wralignblocks = 1;
|
||||
}
|
||||
|
||||
DEBUGASSERT(rwb->wralignblocks <= rwb->wrmaxblocks &&
|
||||
rwb->wrmaxblocks % rwb->wralignblocks == 0);
|
||||
|
||||
/* Initialize the write buffer access semaphore */
|
||||
|
||||
nxsem_init(&rwb->wrsem, 0, 1);
|
||||
@ -907,7 +925,7 @@ static ssize_t rwb_read_(FAR struct rwbuffer_s *rwb, off_t startblock,
|
||||
ret = nxsem_wait(&rwb->rhsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (ssize_t)ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Loop until we have read all of the requested blocks */
|
||||
@ -952,7 +970,7 @@ static ssize_t rwb_read_(FAR struct rwbuffer_s *rwb, off_t startblock,
|
||||
ret);
|
||||
|
||||
rwb_semgive(&rwb->rhsem);
|
||||
return (ssize_t)ret;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -975,7 +993,7 @@ static ssize_t rwb_read_(FAR struct rwbuffer_s *rwb, off_t startblock,
|
||||
ret = rwb->rhreload(rwb->dev, rdbuffer, startblock, nblocks);
|
||||
}
|
||||
|
||||
return (ssize_t)ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -1001,7 +1019,7 @@ ssize_t rwb_read(FAR struct rwbuffer_s *rwb, off_t startblock,
|
||||
ret = nxsem_wait(&rwb->wrsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (ssize_t)ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If the write buffer overlaps the block(s) requested */
|
||||
@ -1019,7 +1037,7 @@ ssize_t rwb_read(FAR struct rwbuffer_s *rwb, off_t startblock,
|
||||
if (ret < 0)
|
||||
{
|
||||
rwb_semgive(&rwb->wrsem);
|
||||
return (ssize_t)ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
startblock += ret;
|
||||
@ -1078,7 +1096,7 @@ ssize_t rwb_write(FAR struct rwbuffer_s *rwb, off_t startblock,
|
||||
ret = nxsem_wait(&rwb->rhsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (ssize_t)ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (rwb_overlap(rwb->rhblockstart, rwb->rhnblocks, startblock,
|
||||
@ -1092,7 +1110,7 @@ ssize_t rwb_write(FAR struct rwbuffer_s *rwb, off_t startblock,
|
||||
{
|
||||
ferr("ERROR: rwb_invalidate_readahead failed: %d\n", ret);
|
||||
rwb_semgive(&rwb->rhsem);
|
||||
return (ssize_t)ret;
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
rwb_resetrhbuffer(rwb);
|
||||
@ -1111,7 +1129,7 @@ ssize_t rwb_write(FAR struct rwbuffer_s *rwb, off_t startblock,
|
||||
ret = nxsem_wait(&rwb->wrsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (ssize_t)ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rwb_writebuffer(rwb, startblock, nblocks, wrbuffer);
|
||||
@ -1132,7 +1150,7 @@ ssize_t rwb_write(FAR struct rwbuffer_s *rwb, off_t startblock,
|
||||
ret = rwb->wrflush(rwb->dev, wrbuffer, startblock, nblocks);
|
||||
}
|
||||
|
||||
return (ssize_t)ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -113,6 +113,9 @@ struct rwbuffer_s
|
||||
|
||||
#ifdef CONFIG_DRVR_WRITEBUFFER
|
||||
uint16_t wrmaxblocks; /* The number of blocks to buffer in memory */
|
||||
uint16_t wralignblocks; /* The buffer to be flash is always multiplied by this
|
||||
* number. It must be 0 or divisible by wrmaxblocks.
|
||||
*/
|
||||
#endif
|
||||
#ifdef CONFIG_DRVR_READAHEAD
|
||||
uint16_t rhmaxblocks; /* The number of blocks to buffer in memory */
|
||||
|
Loading…
Reference in New Issue
Block a user