OpenSSD Cosmos+ Platform Firmware
0.0.2
The firmware of Cosmos+ OpenSSD Platform for TOSHIBA nand flash module.
|
Go to the source code of this file.
Functions | |
void | InitReqScheduler () |
Initialize scheduling related tables. More... | |
void | SyncAllLowLevelReqDone () |
Do schedule until all the requests are done. More... | |
void | SyncAvailFreeReq () |
Try release request entries by doing scheduling (both NVMe and NAND). More... | |
void | SyncReleaseEraseReq (unsigned int chNo, unsigned int wayNo, unsigned int blockNo) |
Issuing requests until the specified block can be erased. More... | |
void | SchedulingNandReq () |
Iteratively do schedule on each channel by calling SchedulingNandReqPerCh . More... | |
void | SchedulingNandReqPerCh (unsigned int chNo) |
The main function to schedule NAND requests on the specified channel. More... | |
void | PutToNandWayPriorityTable (unsigned int reqSlotTag, unsigned int chNo, unsigned int wayNo) |
Append the specified die to a NAND state list based on the request type of the given request. More... | |
void | PutToNandIdleList (unsigned int chNo, unsigned int wayNo) |
Append the specified die to the tail of the idle list of its channel. More... | |
void | SelectivGetFromNandIdleList (unsigned int chNo, unsigned int wayNo) |
Remove the specified die from the idle list of its channel. More... | |
void | PutToNandStatusReportList (unsigned int chNo, unsigned int wayNo) |
Append the specified die to the tail of the status report list of its channel. More... | |
void | SelectivGetFromNandStatusReportList (unsigned int chNo, unsigned int wayNo) |
Remove the specified die from the status report list of its channel. More... | |
void | PutToNandReadTriggerList (unsigned int chNo, unsigned int wayNo) |
Append the specified die to the tail of the read trigger list of its channel. More... | |
void | SelectiveGetFromNandReadTriggerList (unsigned int chNo, unsigned int wayNo) |
Remove the specified die from the read trigger list of its channel. More... | |
void | PutToNandWriteList (unsigned int chNo, unsigned int wayNo) |
Append the specified die to the tail of the write list of its channel. More... | |
void | SelectiveGetFromNandWriteList (unsigned int chNo, unsigned int wayNo) |
Remove the specified die from the write list of its channel. More... | |
void | PutToNandReadTransferList (unsigned int chNo, unsigned int wayNo) |
Append the specified die to the tail of the read transfer list of its channel. More... | |
void | SelectiveGetFromNandReadTransferList (unsigned int chNo, unsigned int wayNo) |
Remove the specified die from the read transfer list of its channel. More... | |
void | PutToNandEraseList (unsigned int chNo, unsigned int wayNo) |
Append the specified die to the tail of the erase list of its channel. More... | |
void | SelectiveGetFromNandEraseList (unsigned int chNo, unsigned int wayNo) |
Remove the specified die from the erase list of its channel. More... | |
void | PutToNandStatusCheckList (unsigned int chNo, unsigned int wayNo) |
Append the specified die to the tail of the status check list of its channel. More... | |
void | SelectiveGetFromNandStatusCheckList (unsigned int chNo, unsigned int wayNo) |
Remove the specified die from the status check list of its channel. More... | |
void | IssueNandReq (unsigned int chNo, unsigned int wayNo) |
Issue a flash operations to the storage controller. More... | |
unsigned int | GenerateNandRowAddr (unsigned int reqSlotTag) |
Get the nand row (block) address of the given request. More... | |
unsigned int | GenerateDataBufAddr (unsigned int reqSlotTag) |
Get the corresponding data buffer entry address of the given request. More... | |
unsigned int | GenerateSpareDataBufAddr (unsigned int reqSlotTag) |
Get the corresponding sparse data buffer entry address of the given request. More... | |
unsigned int | CheckReqStatus (unsigned int chNo, unsigned int wayNo) |
Update the die status and return the request status. More... | |
unsigned int | CheckEccErrorInfo (unsigned int chNo, unsigned int wayNo) |
void | ExecuteNandReq (unsigned int chNo, unsigned int wayNo, unsigned int reqStatus) |
Update die state and issue new NAND requests if the die is in IDLE state. More... | |
unsigned int CheckEccErrorInfo | ( | unsigned int | chNo, |
unsigned int | wayNo | ||
) |
Definition at line 1321 of file request_schedule.c.
unsigned int CheckReqStatus | ( | unsigned int | chNo, |
unsigned int | wayNo | ||
) |
Update the die status and return the request status.
reqStatusCheckOpt
of this die may be updated from REQ_STATUS_CHECK_OPT_CHECK
, which means the first stage status check, to REQ_STATUS_CHECK_OPT_REPORT
, which means the second stage status check, or changed from REQ_STATUS_CHECK_OPT_REPORT
to REQ_STATUS_CHECK_OPT_CHECK
, so this function should be used carefully.chNo | the target channel number to check the status. |
wayNo | the target die number to check the status. |
Definition at line 1257 of file request_schedule.c.
void ExecuteNandReq | ( | unsigned int | chNo, |
unsigned int | wayNo, | ||
unsigned int | reqStatus | ||
) |
Update die state and issue new NAND requests if the die is in IDLE state.
If the die state is IDLE, we can just issue new NAND request on that die. But if the state is EXE, we should do different thing based on the request status:
previous request is RUNNING
Nothing to do, just wait for it.
previous request is DONE
Before we set the die state to IDLE, we need to do something based on its request type:
previous request is FAIL
If the request failed, there are different things to do based on the request type. For READ_TRIGGER and READ_TRANSFER, retry the request (from READ_TRIGGER state) until reaching the retry limitation. For other requests, just mark as bad block.
previous request is WARNING
This means ECC failed, report bad block then make die IDLE and reset retry count
chNo | the channel number which should exec this request |
wayNo | the way number which should exec this request |
reqStatus | the status of the previous request executed on the specified die |
Definition at line 1386 of file request_schedule.c.
unsigned int GenerateDataBufAddr | ( | unsigned int | reqSlotTag | ) |
Get the corresponding data buffer entry address of the given request.
Before issuing the DMA operations, we have to set the buffer address where the request should get/put their data during the READ/WRITE request.
To do this, we may have to specify the entry index of real data buffer and convert to the real address if the data buffer format not REQ_OPT_DATA_BUF_ADDR
:
find the index of data buffer entry to be used:
Similar to the two request data buffer dataBuf
and tempDataBuf
, there are also two types of real data buffer specified by the two address DATA_BUFFER_BASE_ADDR
and TEMPORARY_DATA_BUFFER_BASE_ADDR
.
Since the two real data buffer have same number of entries with its corresponding request data buffer, AVAILABLE_TEMPORARY_DATA_BUFFER_ENTRY_COUNT
for temp buffer and AVAILABLE_DATA_BUFFER_ENTRY_COUNT
for normal buffer, we can just simply use the index of the request data buffer entry to find the corresponding index of real data buffer entry.
get the address of real data buffer entry:
Since the real data buffer entry have the same size with NAND page size, and we have already found the entry index, we can just multiply the index by the page size defined by BYTES_PER_DATA_REGION_OF_SLICE
to get the starting address of the corresponding data buffer of the given data buffer entry.
However, if the request is a NVMe request, we should do some extra works. Since the unit size of NVMe block is 4K, which is one-fourth of the page size, if the LBA didn't align by 4, we have to move (N*4K) bytes within the real data buffer entry by using the offset to find the address corresponding to the NVMe block.
reqSlotTag | the request data buffer entry index |
Definition at line 1169 of file request_schedule.c.
unsigned int GenerateNandRowAddr | ( | unsigned int | reqSlotTag | ) |
Get the nand row (block) address of the given request.
To get the row address, we have first check if the nand address format is VSA or not. If the address is VSA, we should convert it to the physical address by doing address translation.
reqSlotTag | the request pool index of the target request. |
Definition at line 1085 of file request_schedule.c.
unsigned int GenerateSpareDataBufAddr | ( | unsigned int | reqSlotTag | ) |
Get the corresponding sparse data buffer entry address of the given request.
Similar to GenerateDataBufAddr()
, but with different buffer base address, different entry size (256B for metadata/sparse data) and no need to deal with the offset of NVMe requests.
RESERVED_DATA_BUFFER_BASE_ADDR
didn't explicitly split into real data area and sparse data area, hence we should manually add 16K (page size) to get the area for sparse data.reqSlotTag | the request data buffer entry index |
Definition at line 1216 of file request_schedule.c.
void InitReqScheduler | ( | ) |
Initialize scheduling related tables.
The following tables may be used for scheduling:
dieStateTablePtr
: contains the metadata of all dieswayPriorityTablePtr
: manages the way state table of each channelcompleteFlagTablePtr
:statusReportTablePtr
:eccErrorInfoTablePtr
:retryLimitTablePtr
: manages the remain retry count of each dieIn this function:
RETRY_LIMIT
Definition at line 83 of file request_schedule.c.
void IssueNandReq | ( | unsigned int | chNo, |
unsigned int | wayNo | ||
) |
Issue a flash operations to the storage controller.
To issue a NAND request, we should first allocate a data buffer entry for the request, though some request may not use the buffer, and then call the corresponding function defined in the nsc_driver.c
based on the request type.
Before we issue the request, we should set the reqStatusCheckOpt
flag of the specified die based on the request type:
REQ_STATUS_CHECK_OPT_COMPLETION_FLAG
, which means the we should use the complete flag table to determine if this request is done. Beside checking the status, this flag also used for distinguishing between READ_TRANSFER and other flash operations, since the ECC result may need to be checked, check the function CheckReqStatus()
for details.REQ_STATUS_CHECK_OPT_NONE
, which means the request won't update the status table, and we can just use the busy/ready status to determine whether this request is done.REQ_STATUS_CHECK_OPT_CHECK
, but this flag is a little bit complicated; this flag actually represent the first stage status check, and this flag may be updated to the REQ_STATUS_CHECK_OPT_REPORT
, which is used to represent the second stage status check, if the function CheckReqStatus()
called during the scheduling process. Check SchedulingNandReqPerCh()
and CheckReqStatus()
for details.chNo | the channel number of the targe die to issue the NAND request. |
wayNo | the way number of the targe die to issue the NAND request. |
Definition at line 1013 of file request_schedule.c.
void PutToNandEraseList | ( | unsigned int | chNo, |
unsigned int | wayNo | ||
) |
Append the specified die to the tail of the erase list of its channel.
Similar to PutToNandIdleList()
but with different target list.
chNo | the channel number of target die |
wayNo | the way number of target die |
Definition at line 859 of file request_schedule.c.
void PutToNandIdleList | ( | unsigned int | chNo, |
unsigned int | wayNo | ||
) |
Append the specified die to the tail of the idle list of its channel.
reqStatusCheckOpt
and dieState
flags.chNo | the channel number of target die |
wayNo | the way number of target die |
Definition at line 536 of file request_schedule.c.
void PutToNandReadTransferList | ( | unsigned int | chNo, |
unsigned int | wayNo | ||
) |
Append the specified die to the tail of the read transfer list of its channel.
Similar to PutToNandIdleList()
but with different target list.
chNo | the channel number of target die |
wayNo | the way number of target die |
Definition at line 796 of file request_schedule.c.
void PutToNandReadTriggerList | ( | unsigned int | chNo, |
unsigned int | wayNo | ||
) |
Append the specified die to the tail of the read trigger list of its channel.
Similar to PutToNandIdleList()
but with different target list.
chNo | the channel number of target die |
wayNo | the way number of target die |
Definition at line 670 of file request_schedule.c.
void PutToNandStatusCheckList | ( | unsigned int | chNo, |
unsigned int | wayNo | ||
) |
Append the specified die to the tail of the status check list of its channel.
Similar to PutToNandIdleList()
but with different target list.
chNo | the channel number of target die |
wayNo | the way number of target die |
Definition at line 922 of file request_schedule.c.
void PutToNandStatusReportList | ( | unsigned int | chNo, |
unsigned int | wayNo | ||
) |
Append the specified die to the tail of the status report list of its channel.
Similar to PutToNandIdleList()
but with different target list.
chNo | the channel number of target die |
wayNo | the way number of target die |
Definition at line 605 of file request_schedule.c.
void PutToNandWayPriorityTable | ( | unsigned int | reqSlotTag, |
unsigned int | chNo, | ||
unsigned int | wayNo | ||
) |
Append the specified die to a NAND state list based on the request type of the given request.
reqSlotTag | the request pool entry index of a request. |
chNo | the channel number of the specified die. |
wayNo | the way number of the specified die. |
Definition at line 511 of file request_schedule.c.
void PutToNandWriteList | ( | unsigned int | chNo, |
unsigned int | wayNo | ||
) |
Append the specified die to the tail of the write list of its channel.
Similar to PutToNandIdleList()
but with different target list.
chNo | the channel number of target die |
wayNo | the way number of target die |
Definition at line 733 of file request_schedule.c.
void SchedulingNandReq | ( | ) |
Iteratively do schedule on each channel by calling SchedulingNandReqPerCh
.
Definition at line 186 of file request_schedule.c.
void SchedulingNandReqPerCh | ( | unsigned int | chNo | ) |
The main function to schedule NAND requests on the specified channel.
This function can be separated into 3 parts:
Check the inline comments for more detailed explanation.
chNo | the channel number for scheduling |
Before doing scheduling on this channel, we should check if there is any idle way on this channel.
If there is any idle way in the idle list, we have to traverse the idle list, and try to schedule requests on the idle ways.
Currently no available requests should be executed on this way, but there may be some requests in the blockedByRowAddrDepReqQ
instead. Try to release the blockedByRowAddrDepReqQ
and check again if there are any requests to do later.
If any blocked request is released in ReleaseBlockedByRowAddrDepReq()
, they will be added to the PutToNandReqQ
.
If there is any request should be scheduled on this die, move this die from idle state list to the state list corresponding to the request type. Otherwise, there is really no request want to use this die, just skip this die.
The most important task of this part is to check the request status (second stage status check). Base on the request status, move to the die to the idle state list if its request is done, or back to statusCheck
list (first stage status check, check next part for details) if its request not complete yet.
But beside this, we also move the dies that had completed their requests to the corresponding state list if there is any request should be scheduled on this die, just like what we did in the previous part, before issuing requests in next part.
Since the previous part had moved all idle ways to the state list corresponding to the head request of this die, this die must not in DIE_STATE_IDLE
state.
Also, we had check the request state is not REQ_STATUS_RUNNING
, thus the ExecuteNandReq()
must bring the die to DIE_STATE_IDLE
.
Since the die become idle, now we can try to schedule request on this die like what we just did in the previous part, if there is any request should be executed on this die.
If the status shows that this request not finish yet, and the flag reqStatusCheckOpt
is set to REQ_STATUS_CHECK_OPT_CHECK
, which means this request is not READ_TRANSFER since READ_TRANSFER use another flag REQ_STATUS_CHECK_OPT_COMPLETION_FLAG
for checking, thus we have to move it back to the statusCheck
list (first stage status check) for the next part to check it again.
Similar to next part, because the CheckReqStatus()
will turn the flag reqStatusCheckOpt
from REQ_STATUS_CHECK_OPT_REPORT
to REQ_STATUS_CHECK_OPT_CHECK
, we don't have to manually change the flag after/before the die was moved to the statusCheck
list.
In the last part, we now can try to issue the requests based on the priority of flash operations. (check the paper)
If there is at least one request should be scheduled and their ways and the channel is not busy, we can issue the requests by calling ExecuteNandReq()
.
After the command is issued, we should move the die to the state list statusCheck
or statusReport
based on the request type:
For READ_TRIGGER, WRITE, ERASE requests:
These types of requests will be moved to the statusCheck
list as they were issued. And next time we entered this part, we will check the status of those requests first, since they are in the statusCheck
list and status check has the highest priority.
To check the request status, we use the function CheckReqStatus()
to get the requests status of the ways and then move the die to the statusReport
list.
CheckReqStatus()
will change the flag reqStatusCheckOpt
to REQ_STATUS_CHECK_OPT_REPORT
, therefore there is no need to modified the flag before/after we move the die to the statusReport
list.statusReport
for second stage status checking.For READ_TRANSFER requests:
This type of requests will be directly added to the statusReport
list. in other words, the status of READ_TRANSFER requests will not be checked in this part.
GUESS: The reason that we don't check the status of READ_TRANSFER requests may be this type of requests are supposed to be time consuming task, thus we have no need to check the status right after they just being issued.
Definition at line 211 of file request_schedule.c.
void SelectiveGetFromNandEraseList | ( | unsigned int | chNo, |
unsigned int | wayNo | ||
) |
Remove the specified die from the erase list of its channel.
Similar to SelectivGetFromNandIdleList()
, but with different target list.
chNo | the channel number of target die |
wayNo | the way number of target die |
Definition at line 885 of file request_schedule.c.
void SelectiveGetFromNandReadTransferList | ( | unsigned int | chNo, |
unsigned int | wayNo | ||
) |
Remove the specified die from the read transfer list of its channel.
Similar to SelectivGetFromNandIdleList()
, but with different target list.
chNo | the channel number of target die |
wayNo | the way number of target die |
Definition at line 822 of file request_schedule.c.
void SelectiveGetFromNandReadTriggerList | ( | unsigned int | chNo, |
unsigned int | wayNo | ||
) |
Remove the specified die from the read trigger list of its channel.
Similar to SelectivGetFromNandIdleList()
, but with different target list.
chNo | the channel number of target die |
wayNo | the way number of target die |
Definition at line 696 of file request_schedule.c.
void SelectiveGetFromNandStatusCheckList | ( | unsigned int | chNo, |
unsigned int | wayNo | ||
) |
Remove the specified die from the status check list of its channel.
Similar to SelectivGetFromNandIdleList()
, but with different target list.
chNo | the channel number of target die |
wayNo | the way number of target die |
Definition at line 948 of file request_schedule.c.
void SelectiveGetFromNandWriteList | ( | unsigned int | chNo, |
unsigned int | wayNo | ||
) |
Remove the specified die from the write list of its channel.
Similar to SelectivGetFromNandIdleList()
, but with different target list.
chNo | the channel number of target die |
wayNo | the way number of target die |
Definition at line 759 of file request_schedule.c.
void SelectivGetFromNandIdleList | ( | unsigned int | chNo, |
unsigned int | wayNo | ||
) |
Remove the specified die from the idle list of its channel.
Since the state lists only records the index of head/tail way in their list, there is no need to modify the wayPriority
if the target way is at the body of its idle list.
PutToNandIdleList()
, this function won't change reqStatusCheckOpt
and dieState
too.chNo | the channel number of target die |
wayNo | the way number of target die |
Definition at line 568 of file request_schedule.c.
void SelectivGetFromNandStatusReportList | ( | unsigned int | chNo, |
unsigned int | wayNo | ||
) |
Remove the specified die from the status report list of its channel.
Similar to SelectivGetFromNandIdleList()
, but with different target list.
chNo | the channel number of target die |
wayNo | the way number of target die |
Definition at line 633 of file request_schedule.c.
void SyncAllLowLevelReqDone | ( | ) |
Do schedule until all the requests are done.
As mentioned in the paper, the NVMe requests have higher priority than NAND requests. Therefore the function that handles NVMe request CheckDoneNvmeDmaReq()
should be called before the function for scheduling NAND requests SchedulingNandReq()
.
Definition at line 135 of file request_schedule.c.
void SyncAvailFreeReq | ( | ) |
Try release request entries by doing scheduling (both NVMe and NAND).
Similar to SyncAllLowLevelReqDone()
, but this function will stop at there is at least one free request entry exists.
Definition at line 150 of file request_schedule.c.
void SyncReleaseEraseReq | ( | unsigned int | chNo, |
unsigned int | wayNo, | ||
unsigned int | blockNo | ||
) |
Issuing requests until the specified block can be erased.
Sometimes, a request on a block may be blocked by the previous erase request on the same block. However, the erase request may also blocked by the previous read requests.
So, this function will try to release the pending requests on the specified block that is blocked by the pending erase request.
chNo | The channel number of the target block. |
wayNo | The way number of the target channel. |
blockNo | The block number of the target die. |
Definition at line 174 of file request_schedule.c.
P_COMPLETE_FLAG_TABLE completeFlagTablePtr |
Definition at line 54 of file request_schedule.c.
P_DIE_STATE_TABLE dieStateTablePtr |
Definition at line 59 of file request_schedule.c.
P_ERROR_INFO_TABLE eccErrorInfoTablePtr |
Definition at line 56 of file request_schedule.c.
P_RETRY_LIMIT_TABLE retryLimitTablePtr |
Definition at line 57 of file request_schedule.c.
P_STATUS_REPORT_TABLE statusReportTablePtr |
Definition at line 55 of file request_schedule.c.
P_WAY_PRIORITY_TABLE wayPriorityTablePtr |
Definition at line 60 of file request_schedule.c.