You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/01/09 12:38:42 UTC

[incubator-nuttx] 05/07: drivers: mtd: smart: Check CRC of duplicate sectors

This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch pr66
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit d15e755335cbb100c0ca3af722ede1c4d2c20c9b
Author: Alin Jerpelea <al...@sony.com>
AuthorDate: Thu Jan 9 12:57:52 2020 +0100

    drivers: mtd: smart: Check CRC of duplicate sectors
    
    In the illegal case by power-loss, when the multiple logical sectors are
    duplicated, we compare the sequence number of each sector and select the newer
    sector. Just in case, add CRC check for the newer sector. If the newer sector
    has CRC error, then we use the older sector.
    
    Signed-off-by: Alin Jerpelea <al...@sony.com>
---
 drivers/mtd/smart.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 58 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/smart.c b/drivers/mtd/smart.c
index d5cd676..e011195 100644
--- a/drivers/mtd/smart.c
+++ b/drivers/mtd/smart.c
@@ -391,6 +391,9 @@ static inline int smart_allocsector(FAR struct smart_struct_s *dev,
 #endif
 static int smart_readsector(FAR struct smart_struct_s *dev, unsigned long arg);
 
+#ifdef CONFIG_MTD_SMART_ENABLE_CRC
+static int smart_validate_crc(FAR struct smart_struct_s *dev);
+#endif
 #ifdef CONFIG_MTD_SMART_WEAR_LEVEL
 static int smart_read_wearstatus(FAR struct smart_struct_s *dev);
 static int smart_relocate_static_data(FAR struct smart_struct_s *dev, uint16_t block);
@@ -1865,6 +1868,7 @@ static int smart_scan(FAR struct smart_struct_s *dev)
   uint16_t  totalsectors;
   uint16_t  sectorsize, prerelease;
   uint16_t  logicalsector;
+  uint16_t  winner;
   uint16_t  loser;
   uint32_t  readaddress;
   uint32_t  offset;
@@ -1999,6 +2003,8 @@ static int smart_scan(FAR struct smart_struct_s *dev)
     {
       finfo("Scan sector %d\n", sector);
 
+      winner = sector;
+
       /* Calculate the read address for this sector */
 
       readaddress = sector * dev->mtdblkspersector * dev->geo.blocksize;
@@ -2278,9 +2284,9 @@ static int smart_scan(FAR struct smart_struct_s *dev)
             {
               /* Seq 2 is the winner ... bigger or it wrapped */
 
+              winner = sector;
 #ifndef CONFIG_MTD_SMART_MINIMIZE_RAM
               loser = dev->smap[logicalsector];
-              dev->smap[logicalsector] = sector;
 #else
               loser = dupsector;
 #endif
@@ -2290,7 +2296,56 @@ static int smart_scan(FAR struct smart_struct_s *dev)
               /* We keep the original mapping and seq2 is the loser */
 
               loser = sector;
+#ifndef CONFIG_MTD_SMART_MINIMIZE_RAM
+              winner = dev->smap[logicalsector];
+#else
+              winner = smart_cache_lookup(dev, logicalsector);
+#endif
+            }
+
+          finfo("Duplicate Sector winner=%d, loser=%d\n", winner, loser);
+
+#ifdef CONFIG_MTD_SMART_ENABLE_CRC
+          /* Check CRC of the winner sector just in case */
+
+          ret = MTD_BREAD(dev->mtd, winner * dev->mtdblkspersector,
+                          dev->mtdblkspersector, (FAR uint8_t *) dev->rwbuffer);
+          if (ret == dev->mtdblkspersector)
+            {
+              /* Validate the CRC of the read-back data */
+
+              ret = smart_validate_crc(dev);
+            }
+
+          if (ret != OK)
+            {
+              /* The winner sector has CRC error, so we select the loser sector.
+               * After swapping the winner and the loser sector, we will release
+               * the loser sector with CRC error.
+               */
+
+              if (sector == winner)
+                {
+                  /* winner: sector(CRC error) -> origin
+                   * loser : origin            -> sector(CRC error)
+                   */
+
+                  winner = loser;
+                  loser = sector;
+                }
+              else
+                {
+                  /* winner: origin(CRC error) -> sector
+                   * loser : sector            -> origin(CRC error)
+                   */
+
+                  loser = winner;
+                  winner = sector;
+                }
+
+              finfo("Duplicate Sector winner=%d, loser=%d\n", winner, loser);
             }
+#endif  /* CONFIG_MTD_SMART_ENABLE_CRC */
 
           /* Now release the loser sector */
 
@@ -2326,7 +2381,7 @@ static int smart_scan(FAR struct smart_struct_s *dev)
 #ifndef CONFIG_MTD_SMART_MINIMIZE_RAM
       /* Update the logical to physical sector map */
 
-      dev->smap[logicalsector] = sector;
+      dev->smap[logicalsector] = winner;
 #else
       /* Mark the logical sector as used in the bitmap */
 
@@ -2334,7 +2389,7 @@ static int smart_scan(FAR struct smart_struct_s *dev)
 
       if (logicalsector < SMART_FIRST_ALLOC_SECTOR)
         {
-          smart_add_sector_to_cache(dev, logicalsector, sector, __LINE__);
+          smart_add_sector_to_cache(dev, logicalsector, winner, __LINE__);
         }
 #endif
     }