OpenSSD Cosmos+ Platform Firmware  0.0.2
The firmware of Cosmos+ OpenSSD Platform for TOSHIBA nand flash module.
garbage_collection.c File Reference
#include "xil_printf.h"
#include <assert.h>
#include "memory_map.h"
Include dependency graph for garbage_collection.c:

Go to the source code of this file.

Functions

void InitGcVictimMap ()
 
void GarbageCollection (unsigned int dieNo)
 
void PutToGcVictimList (unsigned int dieNo, unsigned int blockNo, unsigned int invalidSliceCnt)
 
unsigned int GetFromGcVictimList (unsigned int dieNo)
 
void SelectiveGetFromGcVictimList (unsigned int dieNo, unsigned int blockNo)
 

Variables

P_GC_VICTIM_MAP gcVictimMapPtr
 

Function Documentation

◆ GarbageCollection()

void GarbageCollection ( unsigned int  dieNo)

Definition at line 70 of file garbage_collection.c.

71{
72 unsigned int victimBlockNo, pageNo, virtualSliceAddr, logicalSliceAddr, dieNoForGcCopy, reqSlotTag;
73
74 victimBlockNo = GetFromGcVictimList(dieNo);
75 dieNoForGcCopy = dieNo;
76
77 if (virtualBlockMapPtr->block[dieNo][victimBlockNo].invalidSliceCnt != SLICES_PER_BLOCK)
78 {
79 for (pageNo = 0; pageNo < USER_PAGES_PER_BLOCK; pageNo++)
80 {
81 virtualSliceAddr = Vorg2VsaTranslation(dieNo, victimBlockNo, pageNo);
82 logicalSliceAddr = virtualSliceMapPtr->virtualSlice[virtualSliceAddr].logicalSliceAddr;
83
84 if (logicalSliceAddr != LSA_NONE)
85 if (logicalSliceMapPtr->logicalSlice[logicalSliceAddr].virtualSliceAddr ==
86 virtualSliceAddr) // valid data
87 {
88 // read
89 reqSlotTag = GetFromFreeReqQ();
90
93 reqPoolPtr->reqPool[reqSlotTag].logicalSliceAddr = logicalSliceAddr;
103 reqSlotTag);
104 reqPoolPtr->reqPool[reqSlotTag].nandInfo.virtualSliceAddr = virtualSliceAddr;
105
106 SelectLowLevelReqQ(reqSlotTag);
107
108 // write
109 reqSlotTag = GetFromFreeReqQ();
110
113 reqPoolPtr->reqPool[reqSlotTag].logicalSliceAddr = logicalSliceAddr;
123 reqSlotTag);
125 FindFreeVirtualSliceForGc(dieNoForGcCopy, victimBlockNo);
126
130 .logicalSliceAddr = logicalSliceAddr;
131
132 SelectLowLevelReqQ(reqSlotTag);
133 }
134 }
135 }
136
137 EraseBlock(dieNo, victimBlockNo);
138}
P_LOGICAL_SLICE_MAP logicalSliceMapPtr
void EraseBlock(unsigned int dieNo, unsigned int blockNo)
Erase the specified block of the specified die and discard its LSAs.
unsigned int FindFreeVirtualSliceForGc(unsigned int copyTargetDieNo, unsigned int victimBlockNo)
P_VIRTUAL_SLICE_MAP virtualSliceMapPtr
P_VIRTUAL_BLOCK_MAP virtualBlockMapPtr
#define Vorg2VsaTranslation(dieNo, blockNo, pageNo)
Translate virtual NAND organization (location vector) into VSA.
#define LSA_NONE
void UpdateTempDataBufEntryInfoBlockingReq(unsigned int bufEntry, unsigned int reqSlotTag)
Append the request to the blocking queue specified by given temp buffer entry.
Definition: data_buffer.c:298
unsigned int AllocateTempDataBuf(unsigned int dieNo)
Retrieve the index of temp buffer entry of the target die.
Definition: data_buffer.c:288
#define SLICES_PER_BLOCK
Definition: ftl_config.h:227
#define USER_PAGES_PER_BLOCK
Definition: ftl_config.h:221
unsigned int GetFromGcVictimList(unsigned int dieNo)
unsigned int GetFromFreeReqQ()
Get a free request from the free request queue.
P_REQ_POOL reqPoolPtr
#define REQ_OPT_BLOCK_SPACE_MAIN
for the 1 bit flag REQ_OPTION::blockSpace.
#define REQ_OPT_DATA_BUF_TEMP_ENTRY
#define REQ_OPT_NAND_ECC_WARNING_OFF
#define REQ_CODE_WRITE
#define REQ_OPT_ROW_ADDR_DEPENDENCY_CHECK
#define REQ_OPT_NAND_ADDR_VSA
#define REQ_CODE_READ
#define REQ_TYPE_NAND
#define REQ_OPT_NAND_ECC_ON
void SelectLowLevelReqQ(unsigned int reqSlotTag)
Dispatch given NVMe/NAND request to corresponding request queue.
unsigned int entry
unsigned int virtualSliceAddr
LOGICAL_SLICE_ENTRY logicalSlice[SLICES_PER_SSD]
unsigned int virtualSliceAddr
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 blockSpace
unsigned int rowAddrDependencyCheck
unsigned int nandEcc
SSD_REQ_FORMAT reqPool[AVAILABLE_OUNTSTANDING_REQ_COUNT]
REQ_OPTION reqOpt
DATA_BUF_INFO dataBufInfo
unsigned int reqCode
unsigned int logicalSliceAddr
NAND_INFO nandInfo
unsigned int reqType
unsigned int invalidSliceCnt
VIRTUAL_BLOCK_ENTRY block[USER_DIES][USER_BLOCKS_PER_DIE]
unsigned int logicalSliceAddr
VIRTUAL_SLICE_ENTRY virtualSlice[SLICES_PER_SSD]
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetFromGcVictimList()

unsigned int GetFromGcVictimList ( unsigned int  dieNo)

Definition at line 160 of file garbage_collection.c.

161{
162 unsigned int evictedBlockNo;
163 int invalidSliceCnt;
164
165 for (invalidSliceCnt = SLICES_PER_BLOCK; invalidSliceCnt > 0; invalidSliceCnt--)
166 {
167 if (gcVictimMapPtr->gcVictimList[dieNo][invalidSliceCnt].headBlock != BLOCK_NONE)
168 {
169 evictedBlockNo = gcVictimMapPtr->gcVictimList[dieNo][invalidSliceCnt].headBlock;
170
171 if (virtualBlockMapPtr->block[dieNo][evictedBlockNo].nextBlock != BLOCK_NONE)
172 {
173 virtualBlockMapPtr->block[dieNo][virtualBlockMapPtr->block[dieNo][evictedBlockNo].nextBlock]
175 gcVictimMapPtr->gcVictimList[dieNo][invalidSliceCnt].headBlock =
176 virtualBlockMapPtr->block[dieNo][evictedBlockNo].nextBlock;
177 }
178 else
179 {
180 gcVictimMapPtr->gcVictimList[dieNo][invalidSliceCnt].headBlock = BLOCK_NONE;
181 gcVictimMapPtr->gcVictimList[dieNo][invalidSliceCnt].tailBlock = BLOCK_NONE;
182 }
183 return evictedBlockNo;
184 }
185 }
186
187 assert(!"[WARNING] There are no free blocks. Abort terminate this ssd. [WARNING]");
188 return BLOCK_FAIL;
189}
#define BLOCK_NONE
#define BLOCK_FAIL
P_GC_VICTIM_MAP gcVictimMapPtr
unsigned int tailBlock
unsigned int headBlock
GC_VICTIM_LIST_ENTRY gcVictimList[USER_DIES][SLICES_PER_BLOCK+1]
unsigned int prevBlock
unsigned int nextBlock
Here is the caller graph for this function:

◆ InitGcVictimMap()

void InitGcVictimMap ( )

Definition at line 54 of file garbage_collection.c.

55{
56 int dieNo, invalidSliceCnt;
57
59
60 for (dieNo = 0; dieNo < USER_DIES; dieNo++)
61 {
62 for (invalidSliceCnt = 0; invalidSliceCnt < SLICES_PER_BLOCK + 1; invalidSliceCnt++)
63 {
64 gcVictimMapPtr->gcVictimList[dieNo][invalidSliceCnt].headBlock = BLOCK_NONE;
65 gcVictimMapPtr->gcVictimList[dieNo][invalidSliceCnt].tailBlock = BLOCK_NONE;
66 }
67 }
68}
#define USER_DIES
Definition: ftl_config.h:219
struct _GC_VICTIM_MAP * P_GC_VICTIM_MAP
#define GC_VICTIM_MAP_ADDR
Definition: memory_map.h:106
Here is the caller graph for this function:

◆ PutToGcVictimList()

void PutToGcVictimList ( unsigned int  dieNo,
unsigned int  blockNo,
unsigned int  invalidSliceCnt 
)

Definition at line 140 of file garbage_collection.c.

141{
142 if (gcVictimMapPtr->gcVictimList[dieNo][invalidSliceCnt].tailBlock != BLOCK_NONE)
143 {
144 virtualBlockMapPtr->block[dieNo][blockNo].prevBlock =
145 gcVictimMapPtr->gcVictimList[dieNo][invalidSliceCnt].tailBlock;
146 virtualBlockMapPtr->block[dieNo][blockNo].nextBlock = BLOCK_NONE;
147 virtualBlockMapPtr->block[dieNo][gcVictimMapPtr->gcVictimList[dieNo][invalidSliceCnt].tailBlock]
148 .nextBlock = blockNo;
149 gcVictimMapPtr->gcVictimList[dieNo][invalidSliceCnt].tailBlock = blockNo;
150 }
151 else
152 {
153 virtualBlockMapPtr->block[dieNo][blockNo].prevBlock = BLOCK_NONE;
154 virtualBlockMapPtr->block[dieNo][blockNo].nextBlock = BLOCK_NONE;
155 gcVictimMapPtr->gcVictimList[dieNo][invalidSliceCnt].headBlock = blockNo;
156 gcVictimMapPtr->gcVictimList[dieNo][invalidSliceCnt].tailBlock = blockNo;
157 }
158}
Here is the caller graph for this function:

◆ SelectiveGetFromGcVictimList()

void SelectiveGetFromGcVictimList ( unsigned int  dieNo,
unsigned int  blockNo 
)

Definition at line 191 of file garbage_collection.c.

192{
193 unsigned int nextBlock, prevBlock, invalidSliceCnt;
194
195 nextBlock = virtualBlockMapPtr->block[dieNo][blockNo].nextBlock;
196 prevBlock = virtualBlockMapPtr->block[dieNo][blockNo].prevBlock;
197 invalidSliceCnt = virtualBlockMapPtr->block[dieNo][blockNo].invalidSliceCnt;
198
199 if ((nextBlock != BLOCK_NONE) && (prevBlock != BLOCK_NONE))
200 {
201 virtualBlockMapPtr->block[dieNo][prevBlock].nextBlock = nextBlock;
202 virtualBlockMapPtr->block[dieNo][nextBlock].prevBlock = prevBlock;
203 }
204 else if ((nextBlock == BLOCK_NONE) && (prevBlock != BLOCK_NONE))
205 {
206 virtualBlockMapPtr->block[dieNo][prevBlock].nextBlock = BLOCK_NONE;
207 gcVictimMapPtr->gcVictimList[dieNo][invalidSliceCnt].tailBlock = prevBlock;
208 }
209 else if ((nextBlock != BLOCK_NONE) && (prevBlock == BLOCK_NONE))
210 {
211 virtualBlockMapPtr->block[dieNo][nextBlock].prevBlock = BLOCK_NONE;
212 gcVictimMapPtr->gcVictimList[dieNo][invalidSliceCnt].headBlock = nextBlock;
213 }
214 else
215 {
216 gcVictimMapPtr->gcVictimList[dieNo][invalidSliceCnt].headBlock = BLOCK_NONE;
217 gcVictimMapPtr->gcVictimList[dieNo][invalidSliceCnt].tailBlock = BLOCK_NONE;
218 }
219}
Here is the caller graph for this function:

Variable Documentation

◆ gcVictimMapPtr

P_GC_VICTIM_MAP gcVictimMapPtr

Definition at line 52 of file garbage_collection.c.