This is an automated email from the ASF dual-hosted git repository. davids5 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 73723dd31c58ffe3ca002d6788b82db7a74700f8 Author: Xiang Xiao <xiaoxi...@xiaomi.com> AuthorDate: Wed Aug 12 22:46:38 2020 +0800 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 <xiaoxi...@xiaomi.com> Change-Id: I6d7904aafab93a7886a594319d65826b81cd3cd1 3Change-Id: I88276149cc7826e7416929ca60b06314e96079a6 --- drivers/mtd/ftl.c | 17 +++++------ drivers/rwbuffer.c | 62 ++++++++++++++++++++++++++-------------- include/nuttx/drivers/rwbuffer.h | 3 ++ 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index c2860bd..7d20667 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c @@ -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); diff --git a/drivers/rwbuffer.c b/drivers/rwbuffer.c index bd05adb..970e6a7 100644 --- a/drivers/rwbuffer.c +++ b/drivers/rwbuffer.c @@ -56,6 +56,13 @@ #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; } /**************************************************************************** diff --git a/include/nuttx/drivers/rwbuffer.h b/include/nuttx/drivers/rwbuffer.h index 9515926..d66dbec 100644 --- a/include/nuttx/drivers/rwbuffer.h +++ b/include/nuttx/drivers/rwbuffer.h @@ -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 */