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

Go to the source code of this file.

Functions

void InitReqPool ()
 Initialize the request pool and the request queues. More...
 
void PutToFreeReqQ (unsigned int reqSlotTag)
 Add the given request to the free request queue. More...
 
unsigned int GetFromFreeReqQ ()
 Get a free request from the free request queue. More...
 
void PutToSliceReqQ (unsigned int reqSlotTag)
 Add the given request to the slice request queue. More...
 
unsigned int GetFromSliceReqQ ()
 Get a slice request from the slice request queue. More...
 
void PutToBlockedByBufDepReqQ (unsigned int reqSlotTag)
 Add the given request to blockedByBufDepReqQ. More...
 
void SelectiveGetFromBlockedByBufDepReqQ (unsigned int reqSlotTag)
 Remove the given request from the blockedByBufDepReqQ. More...
 
void PutToBlockedByRowAddrDepReqQ (unsigned int reqSlotTag, unsigned int chNo, unsigned int wayNo)
 Add the given request to blockedByRowAddrDepReqQ. More...
 
void SelectiveGetFromBlockedByRowAddrDepReqQ (unsigned int reqSlotTag, unsigned int chNo, unsigned int wayNo)
 Remove the given request from the blockedByRowAddrDepReqQ. More...
 
void PutToNvmeDmaReqQ (unsigned int reqSlotTag)
 Add the given request to the NVMe DMA request queue and update its status. More...
 
void SelectiveGetFromNvmeDmaReqQ (unsigned int reqSlotTag)
 Move the specified entry from the nvmeDmaReqQ to the freeReqQ. More...
 
void PutToNandReqQ (unsigned int reqSlotTag, unsigned chNo, unsigned wayNo)
 Add the given request to nandReqQ of the specified die. More...
 
void GetFromNandReqQ (unsigned int chNo, unsigned int wayNo, unsigned int reqStatus, unsigned int reqCode)
 Move the head request of the specified nandReqQ queue to freeReqQ. More...
 

Variables

P_REQ_POOL reqPoolPtr
 
FREE_REQUEST_QUEUE freeReqQ
 
SLICE_REQUEST_QUEUE sliceReqQ
 
BLOCKED_BY_BUFFER_DEPENDENCY_REQUEST_QUEUE blockedByBufDepReqQ
 
BLOCKED_BY_ROW_ADDR_DEPENDENCY_REQUEST_QUEUE blockedByRowAddrDepReqQ [USER_CHANNELS][USER_WAYS]
 
NVME_DMA_REQUEST_QUEUE nvmeDmaReqQ
 
NAND_REQUEST_QUEUE nandReqQ [USER_CHANNELS][USER_WAYS]
 
unsigned int notCompletedNandReqCnt
 
unsigned int blockedReqCnt
 

Function Documentation

◆ GetFromFreeReqQ()

unsigned int GetFromFreeReqQ ( )

Get a free request from the free request queue.

Try to get the first entry (FIFO) from the free queue. If the freeReqQ is empty, use the function SyncAvailFreeReq() to release some requests and recycle the request pool entries occupied by them.

Returns
unsigned int the request pool entry index of the free request queue entry

Definition at line 172 of file request_allocation.c.

173{
174 unsigned int reqSlotTag;
175
176 reqSlotTag = freeReqQ.headReq;
177
178 // try to release some request entries by doing scheduling
179 if (reqSlotTag == REQ_SLOT_TAG_NONE)
180 {
182 reqSlotTag = freeReqQ.headReq;
183 }
184
185 // if the free queue becomes empty, don't forget to update its tail pointer
186 if (reqPoolPtr->reqPool[reqSlotTag].nextReq != REQ_SLOT_TAG_NONE)
187 {
190 }
191 else
192 {
195 }
196
199
200 return reqSlotTag;
201}
P_REQ_POOL reqPoolPtr
FREE_REQUEST_QUEUE freeReqQ
#define REQ_SLOT_TAG_NONE
#define REQ_QUEUE_TYPE_NONE
void SyncAvailFreeReq()
Try release request entries by doing scheduling (both NVMe and NAND).
unsigned int reqCnt
Definition: request_queue.h:54
unsigned int headReq
Definition: request_queue.h:52
unsigned int tailReq
Definition: request_queue.h:53
SSD_REQ_FORMAT reqPool[AVAILABLE_OUNTSTANDING_REQ_COUNT]
unsigned int nextReq
unsigned int reqQueueType
unsigned int prevReq
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetFromNandReqQ()

void GetFromNandReqQ ( unsigned int  chNo,
unsigned int  wayNo,
unsigned int  reqStatus,
unsigned int  reqCode 
)

Move the head request of the specified nandReqQ queue to freeReqQ.

Similar to GetFromSliceReqQ() and SelectiveGetFromNvmeDmaReqQ().

Warning
currently just simply choose and remove the head request
reqStatus and reqCode not used
Parameters
chNothe target channel
wayNothe target way
reqStatusthe status of the previous request executed on the specified die.
reqCodethe command code of the request attempt to execute on the specified die.

Definition at line 548 of file request_allocation.c.

549{
550 unsigned int reqSlotTag;
551
552 reqSlotTag = nandReqQ[chNo][wayNo].headReq;
553 if (reqSlotTag == REQ_SLOT_TAG_NONE)
554 assert(!"[WARNING] there is no request in Nand-req-queue[WARNING]");
555
556 if (reqPoolPtr->reqPool[reqSlotTag].nextReq != REQ_SLOT_TAG_NONE)
557 {
558 nandReqQ[chNo][wayNo].headReq = reqPoolPtr->reqPool[reqSlotTag].nextReq;
560 }
561 else
562 {
563 nandReqQ[chNo][wayNo].headReq = REQ_SLOT_TAG_NONE;
564 nandReqQ[chNo][wayNo].tailReq = REQ_SLOT_TAG_NONE;
565 }
566
568 nandReqQ[chNo][wayNo].reqCnt--;
570
571 PutToFreeReqQ(reqSlotTag);
572 ReleaseBlockedByBufDepReq(reqSlotTag);
573}
void PutToFreeReqQ(unsigned int reqSlotTag)
Add the given request to the free request queue.
unsigned int notCompletedNandReqCnt
NAND_REQUEST_QUEUE nandReqQ[USER_CHANNELS][USER_WAYS]
void ReleaseBlockedByBufDepReq(unsigned int reqSlotTag)
Pop the specified request from the buffer dependency queue.
unsigned int tailReq
Definition: request_queue.h:93
unsigned int headReq
Definition: request_queue.h:92
unsigned int reqCnt
Definition: request_queue.h:94
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetFromSliceReqQ()

unsigned int GetFromSliceReqQ ( )

Get a slice request from the slice request queue.

Try to pop the first request of the slice request queue.

Note
fail if the request queue is empty.
Returns
unsigned int the entry index of chosen slice request, or REQ_SLOT_TAG_FAIL if the slice request queue is empty.

Definition at line 241 of file request_allocation.c.

242{
243 unsigned int reqSlotTag;
244
245 reqSlotTag = sliceReqQ.headReq;
246
247 if (reqSlotTag == REQ_SLOT_TAG_NONE)
248 return REQ_SLOT_TAG_FAIL;
249
250 if (reqPoolPtr->reqPool[reqSlotTag].nextReq != REQ_SLOT_TAG_NONE)
251 {
254 }
255 else
256 {
259 }
260
263
264 return reqSlotTag;
265}
SLICE_REQUEST_QUEUE sliceReqQ
#define REQ_SLOT_TAG_FAIL
unsigned int headReq
Definition: request_queue.h:60
unsigned int reqCnt
Definition: request_queue.h:62
unsigned int tailReq
Definition: request_queue.h:61
Here is the caller graph for this function:

◆ InitReqPool()

void InitReqPool ( )

Initialize the request pool and the request queues.

At the beginning, all the requests are stored in the freeReqQ, therefore the size of freeReqQ should equal to the size of request pool, and the others request queue will be initialized to be empty.

After all the queues are initialized, we next have to initialize the request pool:

  • all the entries should belongs to freeReqQ by default
  • all the entries should be connected in serial order
  • no request exists at the beginning, therefore:
    • the number of not completed NAND request is zero
    • the number of blocking requests is zero
    • both prevBlockingReq and nextBlockingReq should be NONE

Definition at line 77 of file request_allocation.c.

78{
79 int chNo, wayNo, reqSlotTag;
80
81 reqPoolPtr = (P_REQ_POOL)REQ_POOL_ADDR; // revise address
82
83 freeReqQ.headReq = 0;
85
88 sliceReqQ.reqCnt = 0;
89
93
97
98 for (chNo = 0; chNo < USER_CHANNELS; chNo++)
99 for (wayNo = 0; wayNo < USER_WAYS; wayNo++)
100 {
103 blockedByRowAddrDepReqQ[chNo][wayNo].reqCnt = 0;
104
105 nandReqQ[chNo][wayNo].headReq = REQ_SLOT_TAG_NONE;
106 nandReqQ[chNo][wayNo].tailReq = REQ_SLOT_TAG_NONE;
107 nandReqQ[chNo][wayNo].reqCnt = 0;
108 }
109
110 for (reqSlotTag = 0; reqSlotTag < AVAILABLE_OUNTSTANDING_REQ_COUNT; reqSlotTag++)
111 {
115 reqPoolPtr->reqPool[reqSlotTag].prevReq = reqSlotTag - 1;
116 reqPoolPtr->reqPool[reqSlotTag].nextReq = reqSlotTag + 1;
117 }
118
121 freeReqQ.reqCnt = AVAILABLE_OUNTSTANDING_REQ_COUNT; // TODO: move this up ?
122
124 blockedReqCnt = 0;
125}
#define USER_CHANNELS
Definition: ftl_config.h:207
#define USER_WAYS
Definition: ftl_config.h:208
#define REQ_POOL_ADDR
Definition: memory_map.h:109
unsigned int blockedReqCnt
NVME_DMA_REQUEST_QUEUE nvmeDmaReqQ
BLOCKED_BY_BUFFER_DEPENDENCY_REQUEST_QUEUE blockedByBufDepReqQ
BLOCKED_BY_ROW_ADDR_DEPENDENCY_REQUEST_QUEUE blockedByRowAddrDepReqQ[USER_CHANNELS][USER_WAYS]
#define AVAILABLE_OUNTSTANDING_REQ_COUNT
struct _REQ_POOL * P_REQ_POOL
#define REQ_QUEUE_TYPE_FREE
unsigned int nextBlockingReq
unsigned int prevBlockingReq
Here is the caller graph for this function:

◆ PutToBlockedByBufDepReqQ()

void PutToBlockedByBufDepReqQ ( unsigned int  reqSlotTag)

Add the given request to blockedByBufDepReqQ.

Similar to PutToFreeReqQ().

Note
the request blocked by buffer dependency is also a blocked request, therefore the blockedReqCnt should also be increased.
Parameters
reqSlotTagthe request pool entry index of the request to be added

Definition at line 277 of file request_allocation.c.

278{
280 {
284 blockedByBufDepReqQ.tailReq = reqSlotTag;
285 }
286 else
287 {
290 blockedByBufDepReqQ.headReq = reqSlotTag;
291 blockedByBufDepReqQ.tailReq = reqSlotTag;
292 }
293
297}
#define REQ_QUEUE_TYPE_BLOCKED_BY_BUF_DEP
Here is the caller graph for this function:

◆ PutToBlockedByRowAddrDepReqQ()

void PutToBlockedByRowAddrDepReqQ ( unsigned int  reqSlotTag,
unsigned int  chNo,
unsigned int  wayNo 
)

Add the given request to blockedByRowAddrDepReqQ.

Similar to PutToBlockedByBufDepReqQ().

Note
the request blocked by row address dependency is also a blocked request, the blockedReqCnt thus should also be increased.
Parameters
reqSlotTagthe request pool entry index of the request to be added.
chNothe channel number of the specified queue.
wayNothe die number of the specified queue.

Definition at line 357 of file request_allocation.c.

358{
359 if (blockedByRowAddrDepReqQ[chNo][wayNo].tailReq != REQ_SLOT_TAG_NONE)
360 {
361 reqPoolPtr->reqPool[reqSlotTag].prevReq = blockedByRowAddrDepReqQ[chNo][wayNo].tailReq;
363 reqPoolPtr->reqPool[blockedByRowAddrDepReqQ[chNo][wayNo].tailReq].nextReq = reqSlotTag;
364 blockedByRowAddrDepReqQ[chNo][wayNo].tailReq = reqSlotTag;
365 }
366 else
367 {
370 blockedByRowAddrDepReqQ[chNo][wayNo].headReq = reqSlotTag;
371 blockedByRowAddrDepReqQ[chNo][wayNo].tailReq = reqSlotTag;
372 }
373
375 blockedByRowAddrDepReqQ[chNo][wayNo].reqCnt++;
377}
#define REQ_QUEUE_TYPE_BLOCKED_BY_ROW_ADDR_DEP
Here is the caller graph for this function:

◆ PutToFreeReqQ()

void PutToFreeReqQ ( unsigned int  reqSlotTag)

Add the given request to the free request queue.

Insert the given request into the tail of the free queue and update the corresponding field of the given request.

Note
this function will not modify the prevReq of the next request in the original request queue. That is, the prev request entry index of the original next request may still be reqSlotTag.
also, this function will not modify the prevBlockingReq and nextBlockingReq of the original request.
Parameters
reqSlotTagthe request pool entry index of the request to be added.

Definition at line 142 of file request_allocation.c.

143{
145 {
149 freeReqQ.tailReq = reqSlotTag;
150 }
151 else
152 {
155 freeReqQ.headReq = reqSlotTag;
156 freeReqQ.tailReq = reqSlotTag;
157 }
158
161}
Here is the caller graph for this function:

◆ PutToNandReqQ()

void PutToNandReqQ ( unsigned int  reqSlotTag,
unsigned  chNo,
unsigned  wayNo 
)

Add the given request to nandReqQ of the specified die.

Similar to PutToFreeReqQ().

Note
we should not only increase the size of the specified request queue, but also increase the number of uncompleted nand request.
Parameters
reqSlotTagthe request pool entry index of the request to be added.
chNothe channel number of the specified queue.
wayNothe die number of the specified queue.

Definition at line 512 of file request_allocation.c.

513{
514 if (nandReqQ[chNo][wayNo].tailReq != REQ_SLOT_TAG_NONE)
515 {
516 reqPoolPtr->reqPool[reqSlotTag].prevReq = nandReqQ[chNo][wayNo].tailReq;
518 reqPoolPtr->reqPool[nandReqQ[chNo][wayNo].tailReq].nextReq = reqSlotTag;
519 nandReqQ[chNo][wayNo].tailReq = reqSlotTag;
520 }
521 else
522 {
525 nandReqQ[chNo][wayNo].headReq = reqSlotTag;
526 nandReqQ[chNo][wayNo].tailReq = reqSlotTag;
527 }
528
530 nandReqQ[chNo][wayNo].reqCnt++;
532}
#define REQ_QUEUE_TYPE_NAND
Here is the caller graph for this function:

◆ PutToNvmeDmaReqQ()

void PutToNvmeDmaReqQ ( unsigned int  reqSlotTag)

Add the given request to the NVMe DMA request queue and update its status.

Similar to PutToFreeReqQ().

Parameters
reqSlotTagthe request pool entry index of the request to be added

Definition at line 431 of file request_allocation.c.

432{
434 {
438 nvmeDmaReqQ.tailReq = reqSlotTag;
439 }
440 else
441 {
444 nvmeDmaReqQ.headReq = reqSlotTag;
445 nvmeDmaReqQ.tailReq = reqSlotTag;
446 }
447
450}
#define REQ_QUEUE_TYPE_NVME_DMA
Here is the caller graph for this function:

◆ PutToSliceReqQ()

void PutToSliceReqQ ( unsigned int  reqSlotTag)

Add the given request to the slice request queue.

Similar to PutToFreeReqQ().

Parameters
reqSlotTagthe request pool entry index of the request to be added

Definition at line 210 of file request_allocation.c.

211{
213 {
217 sliceReqQ.tailReq = reqSlotTag;
218 }
219 else
220 {
223 sliceReqQ.headReq = reqSlotTag;
224 sliceReqQ.tailReq = reqSlotTag;
225 }
226
229}
#define REQ_QUEUE_TYPE_SLICE
Here is the caller graph for this function:

◆ SelectiveGetFromBlockedByBufDepReqQ()

void SelectiveGetFromBlockedByBufDepReqQ ( unsigned int  reqSlotTag)

Remove the given request from the blockedByBufDepReqQ.

Similar to GetFromSliceReqQ(), but the entry to be removed is specified by the param reqSlotTag.

Note
don't forget to decrease blockedReqCnt
Parameters
reqSlotTagthe request pool entry index of the request to be removed

Definition at line 309 of file request_allocation.c.

310{
311 unsigned int prevReq, nextReq;
312
313 if (reqSlotTag == REQ_SLOT_TAG_NONE)
314 assert(!"[WARNING] Wrong reqSlotTag [WARNING]");
315
316 prevReq = reqPoolPtr->reqPool[reqSlotTag].prevReq;
317 nextReq = reqPoolPtr->reqPool[reqSlotTag].nextReq;
318
319 if ((nextReq != REQ_SLOT_TAG_NONE) && (prevReq != REQ_SLOT_TAG_NONE))
320 {
321 reqPoolPtr->reqPool[prevReq].nextReq = nextReq;
322 reqPoolPtr->reqPool[nextReq].prevReq = prevReq;
323 }
324 else if ((nextReq == REQ_SLOT_TAG_NONE) && (prevReq != REQ_SLOT_TAG_NONE))
325 {
328 }
329 else if ((nextReq != REQ_SLOT_TAG_NONE) && (prevReq == REQ_SLOT_TAG_NONE))
330 {
333 }
334 else
335 {
338 }
339
343}
Here is the caller graph for this function:

◆ SelectiveGetFromBlockedByRowAddrDepReqQ()

void SelectiveGetFromBlockedByRowAddrDepReqQ ( unsigned int  reqSlotTag,
unsigned int  chNo,
unsigned int  wayNo 
)

Remove the given request from the blockedByRowAddrDepReqQ.

Similar to SelectiveGetFromBlockedByBufDepReqQ().

Parameters
reqSlotTagthe request pool entry index of the request to be removed.
chNothe channel number of the specified queue.
wayNothe die number of the specified queue.

Definition at line 388 of file request_allocation.c.

389{
390 unsigned int prevReq, nextReq;
391
392 if (reqSlotTag == REQ_SLOT_TAG_NONE)
393 assert(!"[WARNING] Wrong reqSlotTag [WARNING]");
394
395 prevReq = reqPoolPtr->reqPool[reqSlotTag].prevReq;
396 nextReq = reqPoolPtr->reqPool[reqSlotTag].nextReq;
397
398 if ((nextReq != REQ_SLOT_TAG_NONE) && (prevReq != REQ_SLOT_TAG_NONE))
399 {
400 reqPoolPtr->reqPool[prevReq].nextReq = nextReq;
401 reqPoolPtr->reqPool[nextReq].prevReq = prevReq;
402 }
403 else if ((nextReq == REQ_SLOT_TAG_NONE) && (prevReq != REQ_SLOT_TAG_NONE))
404 {
406 blockedByRowAddrDepReqQ[chNo][wayNo].tailReq = prevReq;
407 }
408 else if ((nextReq != REQ_SLOT_TAG_NONE) && (prevReq == REQ_SLOT_TAG_NONE))
409 {
411 blockedByRowAddrDepReqQ[chNo][wayNo].headReq = nextReq;
412 }
413 else
414 {
417 }
418
420 blockedByRowAddrDepReqQ[chNo][wayNo].reqCnt--;
422}
Here is the caller graph for this function:

◆ SelectiveGetFromNvmeDmaReqQ()

void SelectiveGetFromNvmeDmaReqQ ( unsigned int  reqSlotTag)

Move the specified entry from the nvmeDmaReqQ to the freeReqQ.

Remove the given request entry from the NVMe DMA request queue, and then insert into the free request queue.

Note
the function PutToFreeReqQ() and its friends won't modify the prevBlockingReq and the nextBlockingReq of the specified request entry, therefore after request being added to free request queue, we should also try to remove the specified request from the blocking request by calling the function ReleaseBlockedByBufDepReq(). // FIXME
Parameters
reqSlotTagthe request pool entry index of the request to be removed

Definition at line 465 of file request_allocation.c.

466{
467 unsigned int prevReq, nextReq;
468
469 prevReq = reqPoolPtr->reqPool[reqSlotTag].prevReq;
470 nextReq = reqPoolPtr->reqPool[reqSlotTag].nextReq;
471
472 if ((nextReq != REQ_SLOT_TAG_NONE) && (prevReq != REQ_SLOT_TAG_NONE))
473 {
474 reqPoolPtr->reqPool[prevReq].nextReq = nextReq;
475 reqPoolPtr->reqPool[nextReq].prevReq = prevReq;
476 }
477 else if ((nextReq == REQ_SLOT_TAG_NONE) && (prevReq != REQ_SLOT_TAG_NONE))
478 {
480 nvmeDmaReqQ.tailReq = prevReq;
481 }
482 else if ((nextReq != REQ_SLOT_TAG_NONE) && (prevReq == REQ_SLOT_TAG_NONE))
483 {
485 nvmeDmaReqQ.headReq = nextReq;
486 }
487 else
488 {
491 }
492
495
496 PutToFreeReqQ(reqSlotTag);
497 ReleaseBlockedByBufDepReq(reqSlotTag); // release the request from blocking request if needed
498}
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ blockedByBufDepReqQ

Definition at line 53 of file request_allocation.c.

◆ blockedByRowAddrDepReqQ

Definition at line 54 of file request_allocation.c.

◆ blockedReqCnt

unsigned int blockedReqCnt

Definition at line 59 of file request_allocation.c.

◆ freeReqQ

Definition at line 51 of file request_allocation.c.

◆ nandReqQ

Definition at line 56 of file request_allocation.c.

◆ notCompletedNandReqCnt

unsigned int notCompletedNandReqCnt

Definition at line 58 of file request_allocation.c.

◆ nvmeDmaReqQ

Definition at line 55 of file request_allocation.c.

◆ reqPoolPtr

P_REQ_POOL reqPoolPtr

Definition at line 50 of file request_allocation.c.

◆ sliceReqQ

Definition at line 52 of file request_allocation.c.