You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
So I don't think I really understand async/await (even with the blog's explanation). All my research says that defining a function as async will insert yield points in my code. Essentially, my situation is this: I have an NVMe driver that I want to be interrupt driven. The driver initializes the controller by following the steps in the NVMe specification, which are as follows:
Set the PCI and PCI Express registers described in section 2 appropriately based on the system
configuration. This includes configuration of power management features. A single interrupt (e.g.,
pin-based, single-MSI, or single MSI-X) should be used until the number of I/O Queues is
determined;
The host waits for the controller to indicate that any previous reset is complete by waiting for
CSTS.RDY to become 0;
The Admin Queue should be configured. The Admin Queue is configured by setting the Admin
Queue Attributes (AQA), Admin Submission Queue Base Address (ASQ), and Admin Completion
Queue Base Address (ACQ) to appropriate values;
The controller settings should be configured. Specifically:
The arbitration mechanism should be selected in CC.AMS;
The memory page size should be initialized in CC.MPS; and
The I/O Command Set that is to be used should be selected in CC.CSS or CC.CSS field should
be set to the value indicating that only the Admin Command Set is supported;
The controller should be enabled by setting CC.EN to 1;
The host should wait for the controller to indicate that the controller is ready to process commands.
The controller is ready to process commands when CSTS.RDY is set to 1;
The host should determine the configuration of the controller by issuing the Identify command,
specifying the Controller data structure. The host should then determine the configuration of each
namespace by issuing the Identify command for each namespace, specifying the Namespace data
structure;
If the controller implements I/O queues, then the host should determine the number of I/O
Submission Queues and I/O Completion Queues supported using the Set Features command with
the Number of Queues feature identifier. After determining the number of I/O Queues, the MSI
and/or MSI-X registers should be configured;
If the controller implements I/O queues, then the host should allocate the appropriate number of
I/O Completion Queues based on the number required for the system configuration and the number
supported by the controller. The I/O Completion Queues are allocated using the Create I/O
Completion Queue command;
If the controller implements I/O queues, then the host should allocate the appropriate number of
I/O Submission Queues based on the number required for the system configuration and the number
supported by the controller. The I/O Submission Queues are allocated using the Create I/O
Submission Queue command; and
To enable asynchronous notification of optional events, the host should issue a Set Features
command specifying the events to enable. To enable asynchronous notification of events, the host
should submit an appropriate number of Asynchronous Event Request commands. This step may
be done at any point after the controller signals that the controller is ready (i.e., CSTS.RDY is set
to 1).
Interrupts are configured by the time my driver starts. However, I'm stuck when I send the identify command. Preferably, here's what I want to do:
Another kernel task calls a function that my driver exposes (say, a read/write function call).
My driver performs the necessary actions to enqueue the command.
My driver yields to the executor, allowing another task to run, if there are any.
An interrupt comes in for the controller and my driver gets notified. My driver takes control.
My driver gets the response and the function finally returns to the caller.
I believe that none of this requires preemptive multitasking, since my driver still needs to yield to it. However, I don't really know how to set up this infrastructure. Right now I'm suffering a bit of a lock contention problem in my driver because I have a mutex for a container that holds all the controllers on the system (or that's what it should do, anyway). However, the initialization function blocks until its done, and so the lock is never released. When the interrupt is fired its stuck trying to acquire a lock that's already held. If I need to, I'll rewrite the driver -- that might be a good thing, actually -- but I'd like to make it fully asynchronous if possible. Can this be accomplished with the current executor? If it can, what isthe best way of doing this?
This discussion was converted from issue #892 on December 27, 2020 14:09.
Heading
Bold
Italic
Quote
Code
Link
Numbered list
Unordered list
Task list
Attach files
Mention
Reference
Menu
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
So I don't think I really understand async/await (even with the blog's explanation). All my research says that defining a function as
async
will insert yield points in my code. Essentially, my situation is this: I have an NVMe driver that I want to be interrupt driven. The driver initializes the controller by following the steps in the NVMe specification, which are as follows:configuration. This includes configuration of power management features. A single interrupt (e.g.,
pin-based, single-MSI, or single MSI-X) should be used until the number of I/O Queues is
determined;
CSTS.RDY to become
0
;Queue Attributes (AQA), Admin Submission Queue Base Address (ASQ), and Admin Completion
Queue Base Address (ACQ) to appropriate values;
be set to the value indicating that only the Admin Command Set is supported;
1
;The controller is ready to process commands when CSTS.RDY is set to
1
;specifying the Controller data structure. The host should then determine the configuration of each
namespace by issuing the Identify command for each namespace, specifying the Namespace data
structure;
Submission Queues and I/O Completion Queues supported using the Set Features command with
the Number of Queues feature identifier. After determining the number of I/O Queues, the MSI
and/or MSI-X registers should be configured;
I/O Completion Queues based on the number required for the system configuration and the number
supported by the controller. The I/O Completion Queues are allocated using the Create I/O
Completion Queue command;
I/O Submission Queues based on the number required for the system configuration and the number
supported by the controller. The I/O Submission Queues are allocated using the Create I/O
Submission Queue command; and
command specifying the events to enable. To enable asynchronous notification of events, the host
should submit an appropriate number of Asynchronous Event Request commands. This step may
be done at any point after the controller signals that the controller is ready (i.e., CSTS.RDY is set
to
1
).Interrupts are configured by the time my driver starts. However, I'm stuck when I send the identify command. Preferably, here's what I want to do:
I believe that none of this requires preemptive multitasking, since my driver still needs to yield to it. However, I don't really know how to set up this infrastructure. Right now I'm suffering a bit of a lock contention problem in my driver because I have a mutex for a container that holds all the controllers on the system (or that's what it should do, anyway). However, the initialization function blocks until its done, and so the lock is never released. When the interrupt is fired its stuck trying to acquire a lock that's already held. If I need to, I'll rewrite the driver -- that might be a good thing, actually -- but I'd like to make it fully asynchronous if possible. Can this be accomplished with the current executor? If it can, what isthe best way of doing this?
Beta Was this translation helpful? Give feedback.
All reactions