none
NDIS serialization of OIDs vs. direct calls RRS feed

  • Question

  • NDIS serializes OIDs requests (non-direct) and also independently serializes most direct calls (such as miniportPause, miniportHaltEx etc.). However, I couldn't find anywhere in the documentation whether direct calls are serialized against OIDs. E.g., is it possible to get miniportPause call while OID is being processed by the miniport? Or vice versa.

    Thanks

    Tuesday, February 10, 2015 7:47 AM

Answers

  • Regarding reset - how can it be serialized against OIDs if its uses include recovery from non-completed OIDs?

    Sorry, my terse summary obscured an important distinction and made things unnecessarily confusing.  Let me clarify.  For Reset, the call is only synchronized against the function call into MiniportOidRequest.   The Reset call is not synchronized against the completion of the OID itself.

    If you intend to process the OID synchronously, there's no difference.  And that means that Reset is indeed ineffective when used against a miniport that is processing OIDs synchronously.

    But if the OID is processed asynchronously -- i.e., the MiniportOidRequest returned NDIS_STATUS_PENDING -- then the Reset can be delivered.

    • Proposed as answer by Pavel A Saturday, February 14, 2015 1:26 AM
    • Marked as answer by -IgorC- Sunday, February 15, 2015 6:24 PM
    Thursday, February 12, 2015 6:13 AM
  • > is it possible to get miniportPause call while OID is being processed by the mini port? 

    Yep. "Independent serialization" means exactly that.

    - pa

    • Marked as answer by -IgorC- Tuesday, February 10, 2015 12:39 PM
    Tuesday, February 10, 2015 9:15 AM

All replies

  • > is it possible to get miniportPause call while OID is being processed by the mini port? 

    Yep. "Independent serialization" means exactly that.

    - pa

    Thanks, I was hoping it's not so :)
    Tuesday, February 10, 2015 12:39 PM
  • Pavel's right.

    It's ok to delay an OID for a bit while you complete a transition to Paused or to Restarted.  But you can't pend the OID for the entire duration of the Pause, since your Restart might be blocked on completing the OID.

    • Initialize/Halt are serialized against each other and nearly everything else.
    • Regular OIDs are serialized against each other, and Initialize/Halt.
    • Restart/Pause are serialized against each other, and Initialize/Halt.  (But Restart/Pause are not serialized against OIDs.)
    • Direct OIDs and CheckForHang are not serialized against anything other than Initialize/Halt.
    • Shutdown is only synchronized against Initialize; in some cases, Shutdown isn't even serialized against Halt.  So I suggest avoiding Shutdown altogether.
    • Reset is synchronized against OIDs and Initialize/Halt.  Edit: See the correction below.  Reset is only synchronized against the function call that issues the OID; not the OID itself.
    • The datapath (Send, CancelSend, ReceiveComplete) are not synchronized against each other.  It might seem that they're synchronized against Pause/Restart, but that's not actually true.  They're only synchronized against Initialize/Halt.  In contrast, Pause/Restart only set up requirements on what your driver is allowed to originate; it doesn't guarantee that NDIS won't still give your driver a few NBLs while you're paused.  (Of course, you can fail the NBLs if you're paused.)

    • Proposed as answer by Pavel A Wednesday, February 11, 2015 10:40 AM
    • Unproposed as answer by Pavel A Saturday, February 14, 2015 1:26 AM
    • Edited by Jeffrey Tippet [MSFT] Monday, February 23, 2015 1:24 AM
    Wednesday, February 11, 2015 4:26 AM
  • Pavel's right.

    It's ok to delay an OID for a bit while you complete a transition to Paused or to Restarted.  But you can't pend the OID for the entire duration of the Pause, since your Restart might be blocked on completing the OID.

    • Initialize/Halt are serialized against each other and nearly everything else.
    • Regular OIDs are serialized against each other, and Initialize/Halt.
    • Restart/Pause are serialized against each other, and Initialize/Halt.  (But Restart/Pause are not serialized against OIDs.)
    • Direct OIDs and CheckForHang are not serialized against anything other than Initialize/Halt.
    • Shutdown is only synchronized against Initialize; in some cases, Shutdown isn't even serialized against Halt.  So I suggest avoiding Shutdown altogether.
    • Reset is synchronized against OIDs and Initialize/Halt.
    • The datapath (Send, CancelSend, ReceiveComplete) are not synchronized against each other.  It might seem that they're synchronized against Pause/Restart, but that's not actually true.  They're only synchronized against Initialize/Halt.  In contrast, Pause/Restart only set up requirements on what your driver is allowed to originate; it doesn't guarantee that NDIS won't still give your driver a few NBLs while you're paused.  (Of course, you can fail the NBLs if you're paused.)

    Excellent piece of info! Can this be added to the official documentation? It will surely help a lot of people.

    Regarding reset - how can it be serialized against OIDs if its uses include recovery from non-completed OIDs? Also, from documentation: 

    "...the driver must complete these pending requests by calling the NdisMOidRequestComplete or NdisMSendNetBufferListsComplete functions respectively before the reset operation is complete. If the driver completes the reset operation asynchronously, it must complete pending OID and send requests before the driver calls NdisMResetComplete".

    https://msdn.microsoft.com/en-us/library/windows/hardware/ff559432(v=vs.85).aspx

    This implies that OID handling might be in progress when reset request arrives.


    • Edited by -IgorC- Wednesday, February 11, 2015 6:28 PM
    Wednesday, February 11, 2015 6:27 PM
  • Regarding reset - how can it be serialized against OIDs if its uses include recovery from non-completed OIDs?

    Sorry, my terse summary obscured an important distinction and made things unnecessarily confusing.  Let me clarify.  For Reset, the call is only synchronized against the function call into MiniportOidRequest.   The Reset call is not synchronized against the completion of the OID itself.

    If you intend to process the OID synchronously, there's no difference.  And that means that Reset is indeed ineffective when used against a miniport that is processing OIDs synchronously.

    But if the OID is processed asynchronously -- i.e., the MiniportOidRequest returned NDIS_STATUS_PENDING -- then the Reset can be delivered.

    • Proposed as answer by Pavel A Saturday, February 14, 2015 1:26 AM
    • Marked as answer by -IgorC- Sunday, February 15, 2015 6:24 PM
    Thursday, February 12, 2015 6:13 AM
  • Regarding reset - how can it be serialized against OIDs if its uses include recovery from non-completed OIDs?

    Sorry, my terse summary obscured an important distinction and made things unnecessarily confusing.  Let me clarify.  For Reset, the call is only synchronized against the function call into MiniportOidRequest.   The Reset call is not synchronized against the completion of the OID itself.

    If you intend to process the OID synchronously, there's no difference.  And that means that Reset is indeed ineffective when used against a miniport that is processing OIDs synchronously.

    But if the OID is processed asynchronously -- i.e., the MiniportOidRequest returned NDIS_STATUS_PENDING -- then the Reset can be delivered.

    Ok, I see now. And about the rest of the calls mentioned in your summary - serialized means only serialized against function call or against the entire execution till the completion?
    Thursday, February 12, 2015 2:01 PM
  • In other cases, the call is serialized against the OID itself; not just the function call.  Reset is special.
    Saturday, February 14, 2015 7:20 PM