84 unsigned int blockNo, dieNo;
94 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
141 unsigned int blockNo, dieNo, remapFlag, maxBadBlockCount;
142 unsigned int reservedBlockOfLun0[
USER_DIES];
143 unsigned int reservedBlockOfLun1[
USER_DIES];
146 xil_printf(
"Bad block remapping start...\r\n");
149 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
153 badBlockCount[dieNo] = 0;
158 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
169 reservedBlockOfLun0[dieNo]++;
183 reservedBlockOfLun0[dieNo]++;
187 xil_printf(
"No reserved block - Ch %d Way %d virtualBlock %d is bad block \r\n",
189 badBlockCount[dieNo]++;
194 xil_printf(
"No reserved block - Ch %d Way %d virtualBlock %d is bad block \r\n",
196 badBlockCount[dieNo]++;
210 reservedBlockOfLun1[dieNo]++;
221 reservedBlockOfLun1[dieNo];
222 reservedBlockOfLun1[dieNo]++;
226 xil_printf(
"No reserved block - Ch %x Way %x virtualBlock %d is bad block \r\n",
229 badBlockCount[dieNo]++;
234 xil_printf(
"No reserved block - Ch %x Way %x virtualBlock %d is bad block \r\n",
237 badBlockCount[dieNo]++;
244 xil_printf(
"Bad block remapping end\r\n");
246 maxBadBlockCount = 0;
247 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
249 xil_printf(
"[WARNING!!!] There are %d bad blocks on Ch %d Way %d.\r\n", badBlockCount[dieNo],
251 if (maxBadBlockCount < badBlockCount[dieNo])
252 maxBadBlockCount = badBlockCount[dieNo];
269 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
302 unsigned int dieNo, phyBlockNo, virtualBlockNo, remappedPhyBlock;
304 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
335 unsigned int dieNo, chNo, wayNo;
337 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
345 xil_printf(
"[WARNING] There is no free block on Ch %d Way %d (Die %d)!\r\n", chNo, wayNo, dieNo);
367 unsigned int tempPage, reqSlotTag, dieNo;
376 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
404 xil_printf(
"[INFO] %s: bbt size: %d pages per die.\r\n", __FUNCTION__, loop);
433void FindBadBlock(
unsigned char dieState[],
unsigned int tempBbtBufAddr[],
unsigned int tempBbtBufEntrySize,
434 unsigned int tempReadBufAddr[],
unsigned int tempReadBufEntrySize)
436 unsigned int phyBlockNo, chNo, wayNo, dieNo, reqSlotTag;
438 unsigned char *markPointer0;
439 unsigned char *markPointer1;
440 unsigned char *bbtUpdater;
450 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
451 if (!dieState[dieNo])
478 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
483 if (!dieState[dieNo])
513 pr_info(
"C/W[%u/%u]: bad block at PBlk %u (0x%x)", chNo, wayNo, phyBlockNo, phyBlockNo);
523 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
528 if (!dieState[dieNo])
537 pr_info(
"C/W[%u/%u]: bad block at PBlk %u (0x%x)", chNo, wayNo, phyBlockNo, phyBlockNo);
542 bbtUpdater = (
unsigned char *)(tempBbtBufAddr[dieNo] + phyBlockNo);
543 *bbtUpdater = blockChecker[dieNo];
563void SaveBadBlockTable(
unsigned char dieState[],
unsigned int tempBbtBufAddr[],
unsigned int tempBbtBufEntrySize)
565 unsigned int dieNo, reqSlotTag;
566 int loop, dataSize, tempPage;
575 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
613 tempBbtBufAddr[dieNo] + loop * tempBbtBufEntrySize;
630 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
632 xil_printf(
"[ bad block table of Ch %d Way %d is saved. ]\r\n", dieNo %
USER_CHANNELS,
666 unsigned int chNo, wayNo, dieNo, phyBlockNo;
667 unsigned int bbtMaker, tempBbtBufBaseAddr, tempBbtBufEntrySize, tempReadBufBaseAddr, tempReadBufEntrySize;
671 unsigned char *bbtTableChecker;
674 tempBbtBufBaseAddr = tempBufAddr;
676 tempReadBufBaseAddr =
679 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
681 tempBbtBufAddr[dieNo] =
683 tempReadBufAddr[dieNo] = tempReadBufBaseAddr + dieNo * tempReadBufEntrySize;
691 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
695 bbtTableChecker = (
unsigned char *)(tempBbtBufAddr[dieNo]);
710 bbtTableChecker = (
unsigned char *)(tempBbtBufAddr[dieNo] + phyBlockNo);
714 pr_info(
"C/W[%u/%u]: bad block at PBlk %u (0x%x)", chNo, wayNo, phyBlockNo, phyBlockNo);
722 xil_printf(
"[ bad block table of ch %d way %d does not exist.]\r\n",
Vdie2PchTranslation(dieNo),
732 FindBadBlock(dieState, tempBbtBufAddr, tempBbtBufEntrySize, tempReadBufAddr, tempReadBufEntrySize);
737 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
746 unsigned int blockNo, dieNo, reqSlotTag;
748 xil_printf(
"Erase total block space...wait for a minute...\r\n");
751 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
771 xil_printf(
"Done.\r\n");
779 unsigned int blockNo, dieNo, reqSlotTag;
781 xil_printf(
"Erase User block space...wait for a minute...\r\n");
784 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
802 xil_printf(
"Done.\r\n");
818 unsigned char eraseFlag = 1;
820 xil_printf(
"Press 'X' to re-make the bad block table.\r\n");
825 xil_printf(
"[WARNING!!!] Start re-making bad block table\r\n");
831 xil_printf(
"[WARNING!!!] Skip re-making bad block table\r\n");
848 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
873 unsigned int virtualSliceAddr;
880 return virtualSliceAddr;
885 assert(!
"[WARNING] Logical address is larger than maximum logical address served by SSD [WARNING]");
905 unsigned int virtualSliceAddr;
916 return virtualSliceAddr;
919 assert(!
"[WARNING] Logical address is larger than maximum logical address served by SSD [WARNING]");
967 unsigned int currentBlock, virtualSliceAddr, dieNo;
991 assert(!
"[WARNING] There is no available block [WARNING]");
994 assert(!
"[WARNING] Current page management fail [WARNING]");
998 assert(!
"[WARNING] Current page management fail [WARNING]");
1005 return virtualSliceAddr;
1010 unsigned int currentBlock, virtualSliceAddr, dieNo;
1012 dieNo = copyTargetDieNo;
1017 assert(!
"[WARNING] There is no available block [WARNING]");
1029 assert(!
"[WARNING] There is no available block [WARNING]");
1032 assert(!
"[WARNING] Current page management fail [WARNING]");
1037 return virtualSliceAddr;
1053 static unsigned char targetCh = 0;
1054 static unsigned char targetWay = 0;
1055 unsigned int targetDie;
1060 targetCh = targetCh + 1;
1064 targetWay = (targetWay + 1) %
USER_WAYS;
1085 unsigned int virtualSliceAddr, dieNo, blockNo;
1124 unsigned int pageNo, virtualSliceAddr, reqSlotTag;
1196 unsigned int evictedBlockNo;
1211 assert(!
"[WARNING] Wrong getFreeBlockOption [WARNING]");
1231 return evictedBlockNo;
1256 unsigned int dieNo, phyBlockNo, tempBbtBufBaseAddr, tempBbtBufEntrySize;
1259 unsigned char *bbtUpdater;
1262 tempBbtBufBaseAddr = tempBufAddr;
1264 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
1265 tempBbtBufAddr[dieNo] =
1269 for (dieNo = 0; dieNo <
USER_DIES; dieNo++)
1275 bbtUpdater = (
unsigned char *)(tempBbtBufAddr[dieNo] + phyBlockNo);
unsigned char sliceAllocationTargetDie
unsigned int AddrTransRead(unsigned int logicalSliceAddr)
Get the virtual slice address of the given logical slice.
unsigned int FindDieForFreeSliceAllocation()
Update and get the die number to serve the next write request.
unsigned int GetFromFbList(unsigned int dieNo, unsigned int getFreeBlockOption)
Pop the first block in the free block list of the specified die.
void FindBadBlock(unsigned char dieState[], unsigned int tempBbtBufAddr[], unsigned int tempBbtBufEntrySize, unsigned int tempReadBufAddr[], unsigned int tempReadBufEntrySize)
Build the bbt for those dies whose bbt doesn't exist.
void InitSliceMap()
Initialize Logical and Virtual Slick Map.
void InitDieMap()
Reset the free block list of each die.
void InitAddressMap()
Initialize the translation related maps.
void SaveBadBlockTable(unsigned char dieState[], unsigned int tempBbtBufAddr[], unsigned int tempBbtBufEntrySize)
Persist the newly created bbt for those dies whose bbt not exists.
P_BAD_BLOCK_TABLE_INFO_MAP bbtInfoMapPtr
void UpdatePhyBlockMapForGrownBadBlock(unsigned int dieNo, unsigned int phyBlockNo)
Mark the given physical block bad block and update the bbt later.
void ReadBadBlockTable(unsigned int tempBbtBufAddr[], unsigned int tempBbtBufEntrySize)
Read the pages that should contain the bad block table.
P_LOGICAL_SLICE_MAP logicalSliceMapPtr
void EraseUserBlockSpace()
Erase all the non-bad main blocks on user dies and wait until done.
unsigned int FindFreeVirtualSlice()
Select a free physical page (virtual slice).
void InitBlockMap()
Create V2P table and free block list.
void EraseBlock(unsigned int dieNo, unsigned int blockNo)
Erase the specified block of the specified die and discard its LSAs.
P_VIRTUAL_DIE_MAP virtualDieMapPtr
void PutToFbList(unsigned int dieNo, unsigned int blockNo)
Append the given virtual block to the free block list of its die.
void UpdateBadBlockTableForGrownBadBlock(unsigned int tempBufAddr)
Update the bad block table and persist to the specified block.
void EraseTotalBlockSpace()
Erase all the blocks on user dies and wait until done.
void InitCurrentBlockOfDieMap()
Get a default free block for each die.
P_PHY_BLOCK_MAP phyBlockMapPtr
unsigned int FindFreeVirtualSliceForGc(unsigned int copyTargetDieNo, unsigned int victimBlockNo)
void InvalidateOldVsa(unsigned int logicalSliceAddr)
Invalidate the specified virtual page.
P_VIRTUAL_SLICE_MAP virtualSliceMapPtr
void RecoverBadBlockTable(unsigned int tempBufAddr)
Read the bbt from flash and re-create if not exists.
void RemapBadBlock()
Try to remap the bad blocks in the main block space.
void InitBlockDieMap()
Build the bad block table and V2P block mapping of each user die.
P_VIRTUAL_BLOCK_MAP virtualBlockMapPtr
unsigned int mbPerbadBlockSpace
unsigned int AddrTransWrite(unsigned int logicalSliceAddr)
Assign a new virtual (physical) page to the specified logical page.
struct _PHY_BLOCK_MAP * P_PHY_BLOCK_MAP
#define Vpage2PlsbPageTranslation(pageNo)
Map the virtual page to the physical LSB page in SLC mode.
#define GET_FREE_BLOCK_NORMAL
#define BLOCK_STATE_NORMAL
struct _BAD_BLOCK_TABLE_INFO_MAP * P_BAD_BLOCK_TABLE_INFO_MAP
#define BBT_INFO_GROWN_BAD_UPDATE_NONE
#define DATA_SIZE_OF_BAD_BLOCK_TABLE_PER_DIE
#define Vdie2PchTranslation(dieNo)
#define DIE_STATE_BAD_BLOCK_TABLE_EXIST
#define DIE_STATE_BAD_BLOCK_TABLE_NOT_EXIST
#define Vorg2VsaTranslation(dieNo, blockNo, pageNo)
Translate virtual NAND organization (location vector) into VSA.
#define USED_PAGES_FOR_BAD_BLOCK_TABLE_PER_DIE
#define Pcw2VdieTranslation(chNo, wayNo)
Get die number from physical channel number and way number.
#define RESERVED_FREE_BLOCK_COUNT
#define GET_FREE_BLOCK_GC
#define Vsa2VdieTranslation(virtualSliceAddr)
#define CLEAN_DATA_IN_BYTE
#define PlsbPage2VpageTranslation(pageNo)
Get the corresponding virtual page number of the given LSB page number.
#define BAD_BLOCK_TABLE_MAKER_IDLE
struct _VIRTUAL_SLICE_MAP * P_VIRTUAL_SLICE_MAP
#define Vblock2PblockOfTbsTranslation(blockNo)
Get the PBA (in total block space) of the given VBN.
#define DIE_STATE_BAD_BLOCK_TABLE_UPDATE
struct _VIRTUAL_BLOCK_MAP * P_VIRTUAL_BLOCK_MAP
struct _LOGICAL_SLICE_MAP * P_LOGICAL_SLICE_MAP
#define Vsa2VblockTranslation(virtualSliceAddr)
#define BAD_BLOCK_TABLE_MAKER_TRIGGER
#define Vdie2PwayTranslation(dieNo)
#define START_PAGE_NO_OF_BAD_BLOCK_TABLE_BLOCK
The start physical page number that stored the bbt of this die.
#define DIE_STATE_BAD_BLOCK_TABLE_HOLD
struct _VIRTUAL_DIE_MAP * P_VIRTUAL_DIE_MAP
#define BBT_INFO_GROWN_BAD_UPDATE_BOOKED
#define BYTES_PER_DATA_REGION_OF_PAGE
#define TOTAL_BLOCKS_PER_LUN
#define BYTES_PER_NAND_ROW
#define BYTES_PER_SPARE_REGION_OF_PAGE
#define BAD_BLOCK_MARK_BYTE1
#define USER_BLOCKS_PER_LUN
#define BAD_BLOCK_MARK_BYTE0
#define USER_BLOCKS_PER_DIE
#define BAD_BLOCK_MARK_PAGE0
#define BAD_BLOCK_MARK_PAGE1
#define USER_PAGES_PER_BLOCK
#define TOTAL_BLOCKS_PER_DIE
void PutToGcVictimList(unsigned int dieNo, unsigned int blockNo, unsigned int invalidSliceCnt)
void GarbageCollection(unsigned int dieNo)
void SelectiveGetFromGcVictimList(unsigned int dieNo, unsigned int blockNo)
#define RESERVED_DATA_BUFFER_BASE_ADDR
#define VIRTUAL_BLOCK_MAP_ADDR
#define PHY_BLOCK_MAP_ADDR
#define BAD_BLOCK_TABLE_INFO_MAP_ADDR
#define VIRTUAL_SLICE_MAP_ADDR
#define VIRTUAL_DIE_MAP_ADDR
#define LOGICAL_SLICE_MAP_ADDR
unsigned int GetFromFreeReqQ()
Get a free request from the free request queue.
void SyncAllLowLevelReqDone()
Do schedule until all the requests are done.
unsigned int grownBadUpdate
BAD_BLOCK_TABLE_INFO_ENTRY bbtInfo[USER_DIES]
unsigned int virtualSliceAddr
The Logical -> Virtual Slice Address mapping table.
LOGICAL_SLICE_ENTRY logicalSlice[SLICES_PER_SSD]
unsigned int physicalBlock
unsigned int programmedPageCnt
unsigned int physicalPage
unsigned int virtualSliceAddr
unsigned int remappedPhyBlock
The metadata table for all the physical blocks.
PHY_BLOCK_ENTRY phyBlock[USER_DIES][TOTAL_BLOCKS_PER_DIE]
unsigned int nandEccWarning
unsigned int dataBufFormat
Type of address stored in the SSD_REQ_FORMAT::dataBufInfo.
unsigned int nandAddr
Type of address stored in the SSD_REQ_FORMAT::nandInfo.
unsigned int rowAddrDependencyCheck
SSD_REQ_FORMAT reqPool[AVAILABLE_OUNTSTANDING_REQ_COUNT]
unsigned int invalidSliceCnt
The block metadata table for all the blocks.
VIRTUAL_BLOCK_ENTRY block[USER_DIES][USER_BLOCKS_PER_DIE]
unsigned int headFreeBlock
unsigned int currentBlock
unsigned int freeBlockCnt
unsigned int tailFreeBlock
The metadata table for all user dies.
VIRTUAL_DIE_ENTRY die[USER_DIES]
unsigned int logicalSliceAddr
The Virtual -> Logical Slice mapping table.
VIRTUAL_SLICE_ENTRY virtualSlice[SLICES_PER_SSD]