Simple question on

Hopefully a very quick question for anyone familiar with IOUserSCSIParallelInterfaceController - what is the right initialization to implement:

  1. init () override;
  2. Start (IOService * provider) override;
  3. UserInitializeController () override;
  4. something else

Seems #3 is required, but guidance varies on the others, undoubtedly bc IOUserSCSI.. implements a lot of things beyond the usual DriverKit structure.

Thanks in advance for any help. (We're trying to implement a driver for a legacy SCSI controller).

Answered by DTS Engineer in 890964022

Hopefully a very quick question for anyone familiar with IOUserSCSIParallelInterfaceController - what is the right initialization to implement:

init () override;

This is basically "I exist". You can do things like create your core data structure, but you aren't attached to a specific driver (well, you know that you know about) and generally won't do any "active" configuration.

Start (IOService * provider) override;

Congratulations, you're a driver now! You now have your provider, which means you can talk to the kernel and start exploring the wider world. In virtually all drivers, this is where most of the actual "work" starts.

...and then the SCSI stack starts.

UserInitializeController () override;

This is your chance to get yourself "ready" to actually do something useful. The most critical thing is that you MUST get your queues set up as the documentation describes. Note this comment:

"For best results, use a model with three dispatch queues. DriverKit creates a default queue for you, and you’ll also need to create interrupt auxiliary queues. Because DriverKit dispatch queues are serial, this arrangement prevents calls from DriverKit, interrupts, and I/O work from competing with one another on the same thread."

The term "For best results..." is another way of saying "we don't expect any other way to work". More specifically, there are multiple places in SCSIControllerDriverKit where the kernel will reenter your DEXT while your DEXT is executing a different callback. If your DispatchQueue configuration or usage is wrong, you'll either deadlock your driver or panic the kernel.

One final note on DispatchQueue. Mostly because of the name and usage pattern, it's tempting to think of DispatchQueue in the same way you would user space dispatch queues and, following that line of thinking, assume that you could improve performance by using more queues to increase parallelism. While I'm sure there are cases where that might be true, I haven't seen one yet and I'm not expecting to anytime soon. A storage DEXT operates as one component within a much larger system and that larger system is what primarily defines your threading behavior, NOT your DEXT. More importantly, a storage driver is the definition of "I/O bound", which means the real performance gains are around how you process I/O request (sizes/counts/etc), not overhead of individual requests.

something else

...and then things get more complicated. I'm not going to try and outline that full flow, but the references I'd recommend are:

While the open-source release does not include IOUserSCSIParallelInterfaceController (and please, do file a bug asking for us to open source it), IOSCSIParallelInterfaceController is the base class for IOUserSCSIParallelInterfaceController, and its implementation defines the general "flow" the driver uses. For example, "UserInitializeController" is simply the DEXT method the kernel calls inside... InitializeController(). Seeing how that flow works can be really helpful in understanding how your DEXT works.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Hopefully a very quick question for anyone familiar with IOUserSCSIParallelInterfaceController - what is the right initialization to implement:

init () override;

This is basically "I exist". You can do things like create your core data structure, but you aren't attached to a specific driver (well, you know that you know about) and generally won't do any "active" configuration.

Start (IOService * provider) override;

Congratulations, you're a driver now! You now have your provider, which means you can talk to the kernel and start exploring the wider world. In virtually all drivers, this is where most of the actual "work" starts.

...and then the SCSI stack starts.

UserInitializeController () override;

This is your chance to get yourself "ready" to actually do something useful. The most critical thing is that you MUST get your queues set up as the documentation describes. Note this comment:

"For best results, use a model with three dispatch queues. DriverKit creates a default queue for you, and you’ll also need to create interrupt auxiliary queues. Because DriverKit dispatch queues are serial, this arrangement prevents calls from DriverKit, interrupts, and I/O work from competing with one another on the same thread."

The term "For best results..." is another way of saying "we don't expect any other way to work". More specifically, there are multiple places in SCSIControllerDriverKit where the kernel will reenter your DEXT while your DEXT is executing a different callback. If your DispatchQueue configuration or usage is wrong, you'll either deadlock your driver or panic the kernel.

One final note on DispatchQueue. Mostly because of the name and usage pattern, it's tempting to think of DispatchQueue in the same way you would user space dispatch queues and, following that line of thinking, assume that you could improve performance by using more queues to increase parallelism. While I'm sure there are cases where that might be true, I haven't seen one yet and I'm not expecting to anytime soon. A storage DEXT operates as one component within a much larger system and that larger system is what primarily defines your threading behavior, NOT your DEXT. More importantly, a storage driver is the definition of "I/O bound", which means the real performance gains are around how you process I/O request (sizes/counts/etc), not overhead of individual requests.

something else

...and then things get more complicated. I'm not going to try and outline that full flow, but the references I'd recommend are:

While the open-source release does not include IOUserSCSIParallelInterfaceController (and please, do file a bug asking for us to open source it), IOSCSIParallelInterfaceController is the base class for IOUserSCSIParallelInterfaceController, and its implementation defines the general "flow" the driver uses. For example, "UserInitializeController" is simply the DEXT method the kernel calls inside... InitializeController(). Seeing how that flow works can be really helpful in understanding how your DEXT works.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Simple question on
 
 
Q