-
Notifications
You must be signed in to change notification settings - Fork 99
Interrupts
The details of incorporating interrupts into this design mostly reside within dnvme, but the high level details will be discussed here. IOQ’s may or may not choose to use interrupts to notify of CE’s arriving from a DUT. If interrupts are not used then the host software must poll those CQ’s for new entries by observing the P-bit of the CE’s. Moreover a concurrent mixture of support must be handled where some CQ’s choose to and others do not use interrupts. The framework handles both schemes simultaneously by adopting a polling interface to the kernel and attaching ISR support so that both mechanisms report when CE’s arrive correctly. In fact, if ISR support is active for a particular CQ, the interface to those CQ’s looks just like the CQ is operating under a polling scheme. In other words, a test case developer does not have to customize coding for each CQ dependent upon what type of reporting scheme is active.
Reaping CE’s from a CQ is done by 1st checking if a particular CQ has any elements to reap. This is done by calling any one of the many CQ::ReapInquiryXXXX() methods from a queue resource.
CQ::ReapInquiry()
This method returns immediately with an answer. There are either CE’s waiting or not and the number which are available to reap is returned. This method will not wait, and if a test case calls this method before a DUT has had a chance to process a previously submitted command, then answer could very well be 0.
CQ::ReapInquiryWaitAny()
This method will return when any number of CE’s arrives in the CQ or a timeout occurs, whichever comes first.
CQ::ReapInquiryWaitSpecify()
This method will return when at least the specified number of CE’s arrives in the CQ or a timeout occurs, whichever comes first.
As long as at least 1 CE is waiting in a CQ, it can be reaped. Reaping from a CQ with 0 CE’s waiting is considered an error. Reaping does not imply that all CE’s must be reaped and it does not mean that any CE’s need to be reaped. CE’s can be left in a CQ as long as a test desires. The reaping action requires a test case to allocate enough memory to receive those CE’s which are being reaped. If too little memory is allocated, this is not an error, dnvme will return as much as it can up to and including the maximum number of CE’s requested. A subsequent call to ReapInquiry() will not be needed, because the act of reaping returns the number of CE’s remaining in the CQ. The CE’s which are successfully reaped will be reported back to tnvme. dnvme will also update the appropriate doorbell register by specifying the number of CE’s successfully reaped back to tnvme. It is important to realize that nothing will be done automatically; action onto the DUT is incurred by dnvme only when the direct authorization arrives from tnvme.
This interface conforms nicely to the polling scheme, for this is the definition of polling. CQ’s are polled until items arrive and then they may be reaped if need be.
By default all interrupts are disabled when tnvme launches. This includes disabling interrupts for the ACQ and thus polling the ACQ will be the only way to extract CE’s from it. The disabling of pin-based, MSI-single, MSI-multi and MSI-X is supported. The enabling of all types of interrupts is supported except pin-based. If pin-based support is desired, a hybrid approach will need to be invoked by writing custom code in dnvme. Pin-based interrupts don’t fit nicely into this design, however all other interrupts do.
To enable interrupts a test developer must interact with CtrlrConfig::SetIrqScheme(). This method sets the desired scheme for the entire DUT to one of MSI-single, MSI-multi or MSI-X. In order to set/change the active scheme the DUT must be disabled. This scheme becomes active when the DUT is enabled and remains until the DUT is again disabled. Moreover, the framework disables all interrupts before each group initiates execution. Remember the framework attempts to bring the system back to a known state before each group executes so that each effectively starts from the same state. This also implies that the DUT is disabled before each group executes because in order to disable interrupts this is a prerequisite.
After interrupts are setup, subsequent tests within the same grouping may create IOCQ’s using interrupts. IOQ’s are created in the usual manner by using a shared_ptr and by initializing the resource thereafter. It is during initialization that
TBD…….