none
Windows 8. NDIS 6.3. MiniportIdleNotification is not called. RRS feed

  • Question

  • I hav developed NDIS6.3 miniport driver. From logs I see that NDIS_MINIPORT_SS_CHARACTERISTICS structure is successfully registered in  MiniportSetOptions function. Also I can see and change "Selective Suspend" and "Selective suspend idle timeout" values in Advanced properties of my adapter. But NDIS does not call my MiniportIdleNotification callbeck when there is no network activity during idle timeout. What can be wrong?
    Wednesday, July 3, 2013 6:21 AM

Answers

  • I have found cause. My new device did not provide Remote Wakeup in bmAttributes of his Configuration Descriptor. When I set it, all works fine.
    Thursday, July 18, 2013 4:04 PM

All replies

  • What is the output of !ndiskd.miniport <handle> -ss on your miniport? It should print out the selective suspend state.
    Wednesday, July 3, 2013 4:32 PM
  • Output is:

    ERROR: !miniport: extension exception 0x80070057

    "Unrecognized argument 'ss' "

    Is 'ss' option available with WinDbg:6.12.0002.633?

    Thursday, July 4, 2013 8:23 AM
  • One time I have got Idle notification and cancel idle notification from NDIS. May be, it is required to disable timers? I'l try.
    Friday, July 5, 2013 5:09 PM
  • Try running windbg that comes with the win8 dev kits

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Friday, July 5, 2013 5:56 PM
  • Yeah, WinDbg 6.12.0002.633 is from a Windows 7 WDK; its debugging tools won't know about Windows 8 features like NDIS selective suspend.  You should upgrade your toolchain -- it's not really supported to use parts of a Windows 7 WDK to build an NDIS 6.30 driver.

    NDIS will not give an idle notification when there has been a recent send or receive packet, OID request, status indication, or pause/restart. Make sure that these activities aren't happening so frequently that NDIS has no chance to send the idle notification. (For example, the Task Manager GUI likes to poll for statistics, which means there's a constant stream of OID requests going down to the NIC. If you happen to be running an app that polls like Task Manager, then the NIC will never go to idle.)

    Monday, July 8, 2013 3:47 AM
  • After !ndiskd.miniport <handle> -ss I see message:

    Selective suspend is disabled.

    Will search what is wrong.

    Monday, July 8, 2013 2:33 PM
  • I tried with new WinDbg - this option is exists, thank you. Now !ndiskd.miniport <handle> -ss commands is showing "Selective suspend is disabled". When I use this option after disabling selective suspend from advanced adapter properties it shows "Selective suspend is administratively disabled on this miniport.

    Seems I have missed some important thing in my code. Will check it once more.

    Monday, July 8, 2013 2:58 PM
  • If your driver doesn't have an IdleNotificationHandler, then ndiskd says "the miniport does not support selective suspend".  Otherwise, if the *SelectiveSuspend keyword is zero, then ndiskd says "selective suspend is administratively disabled".  Otherwise, ndiskd says "selective suspend is disabled".

    There can be a few reasons you see that last message:

    • the miniport doesn't set the NDIS_PM_SELECTIVE_SUSPEND_SUPPORTED flag
    • the the miniport doesn't provide both IdleNotificationHandler and CancelIdleNotificationHandler
    • NDIS failed a memory allocation (highly unlikely)

    My best guess is that you're missing the flag; read about it here http://msdn.microsoft.com/en-us/library/windows/hardware/hh440216(v=vs.85).aspx .

    Monday, July 8, 2013 8:17 PM
  • Very strange.

    This is my simplified code for setting  NDIS_PM_SELECTIVE_SUSPEND_SUPPORTED flag:

    NDIS_PM_CAPABILITIES                   PmCapabilities;

    ...

    NdisZeroMemory(&PmCapabilities,NDIS_SIZEOF_NDIS_PM_CAPABILITIES_REVISION_2);
    PmCapabilities.Header.Revision = NDIS_PM_CAPABILITIES_REVISION_2;
    PmCapabilities.Header.Size = NDIS_SIZEOF_NDIS_PM_CAPABILITIES_REVISION_2;
    PmCapabilities.Flags = NDIS_PM_SELECTIVE_SUSPEND_SUPPORTED;
        MiniportAttributes.GeneralAttributes.PowerManagementCapabilitiesEx = &PmCapabilities;

    ...

    NdisMSetMiniportAttributes(
            Adapter->MiniportAdapterHandle,
            &MiniportAttributes
            );

    This is code for SetOptions:

    NDIS_STATUS MyMiniportIdleNotification(
      _In_  NDIS_HANDLE MiniportAdapterContext,
      _In_  BOOLEAN ForceIdle
    )
    {
    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
        MySendIdleRequest(Adapter);
    return NDIS_STATUS_PENDING;
    }

    VOID MyMiniportCancelIdleNotification(
      _In_  NDIS_HANDLE MiniportAdapterContext
    )
    { PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
    MyCancelSelectiveSuspend(Adapter);
    }

    NDIS_STATUS MyMiniportSetOptions(
      _In_  NDIS_HANDLE NdisDriverHandle,
      _In_  NDIS_HANDLE DriverContext
    )
    {
    NDIS_STATUS status;
    NDIS_MINIPORT_SS_CHARACTERISTICS NdisMiniportSsCharacteristics;
    MyDbgPrint(__FUNCTION__": ++\n");

    NdisZeroMemory(&NdisMiniportSsCharacteristics,sizeof(NDIS_MINIPORT_SS_CHARACTERISTICS));
    NdisMiniportSsCharacteristics.Header.Type =  NDIS_OBJECT_TYPE_MINIPORT_SS_CHARACTERISTICS;
    NdisMiniportSsCharacteristics.Header.Revision = NDIS_MINIPORT_SS_CHARACTERISTICS_REVISION_1;
    NdisMiniportSsCharacteristics.Header.Size = NDIS_SIZEOF_MINIPORT_SS_CHARACTERISTICS_REVISION_1;
    NdisMiniportSsCharacteristics.IdleNotificationHandler = MyMiniportIdleNotification;
    NdisMiniportSsCharacteristics.CancelIdleNotificationHandler = MyMiniportCancelIdleNotification;
    status = NdisSetOptionalHandlers(NdisDriverHandle, (PNDIS_DRIVER_OPTIONAL_HANDLERS)&NdisMiniportSsCharacteristics);
    MyDbgPrint(__FUNCTION__": -- status = 0x%x\n",status);
    return status;
    }

    I see from logs that MyMiniportSetOptions is called during NdisMRegisterMiniportDriver. Code fo setting flag is also called, this is seen from logs. But status in Windbg is "Selective suspend is disabled". I also cannot imagine that NDIS failed memory allocation. Can be some another reason of "Selective suspend is disabled" message  except of  NDIS_PM_SELECTIVE_SUSPEND_SUPPORTED flag and both IdleNotificationHandler and CancelIdleNotificationHandler absence?

    Tuesday, July 9, 2013 11:58 AM
  • I don't see

    PmCapabilities.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;

    Although this doesn't affect selective suspend (so maybe you didn't include it in the code here), you're also going to want to set the supported sleep states.  These are used when the system goes to sleep/hibernate.  For a USB device that supports wake, these will typically be D2:

    PmCapabilities.MinLinkChangeWakeUp = NdisDeviceStateD2;
    PmCapabilities.MinMagicPacketWakeUp = NdisDeviceStateD2;
    // . . . etc . . .

    Wednesday, July 10, 2013 5:18 AM
  • You are rigt, I really missed PmCapabilities.Header.Type. But after its setting I also have "Selective suspend is disabled" in WinDbg.  I tried to set all fields of PmCapabilities structure, but this also does not help. Seems for Windows8 in my miniport will be required to use my own selective suspend management mechanism not based on new NDIS 6.3 features, because I cannot solve problem with "Selective suspend is disabled" in WinDbg

    You said in other thread that NDIS 6.3 will proactively detect and circumvent miniports that illegally attempt to initiate their own power transitions. Now NDIS 6.3 does not try to circumvent my own selective suspend mechanism (not based on NDIS6.3 features) on Windows 8. Do you think later it can be situation when NDIS will circumvent it?

    Wednesday, July 10, 2013 10:17 AM
  • Regarding detecting miniports that illegally manage their own power transitions: If NDIS receives an IRP_MJ_POWER on the FDO that NDIS did not request, then NDIS will set a flag on the NIC that marks it as being "bad", and NDIS will stop attempting to do any power management on the NIC.  I just realized that I forgot to put this flag into !ndiskd (oops).

    When your NIC is initialized, does NDIS call into ndis!ndisSelectiveSuspendInitialize ?  (This is an internal routine to NDIS, so you cannot do much more than set a breakpoint on it.)  If NDIS does call into it, does it seem to bail out quickly, or does it roughly execute to the end? If it gets to the end, does !ndiskd.miniport -ss work then? If it works, check if ndis!ndisSelectiveSuspendFree is ever called.
    Thursday, July 11, 2013 2:58 AM
  • Seems I made some mistake when set breakpoint:

    0: kd> ndis!ndisSelectiveSuspendInitialize
           ^ Syntax error in 'ndis!ndisSelectiveSuspendInitialize'
    0: kd> ndis!ndisSelectiveSuspendFree
           ^ Syntax error in 'ndis!ndisSelectiveSuspendFree'

    I run this 2 commands (ndis!ndisSelectiveSuspendInitialize and ndis!ndisSelectiveSuspendFree) when had a breakpoint in the beginning of my MiniportInitialize function. Do you see any syntax error in my commands?

    Thursday, July 11, 2013 6:53 PM
  • I had forgotten that on host machine I had run old windbg. Will try with new.
    Thursday, July 11, 2013 6:56 PM
  • Same errors with new WinDbg. Seems I made some mistake in these commands.
    Thursday, July 11, 2013 7:09 PM
  • I just accidentally have obtained required callbacks - MiniportIdleNotification and MiniportCancelIdleNotification.

    Command !ndiskd.miniport handle -ss gives:

    SELECTIVE SUSPEND

    State

    Suspended now No

    Suspend requested No

    Idle timeout 5 seconds

    Pending Operations

    [None]

    Statistics

    Number of suspends 0

    Last event CheckForHang

    Last resume reason Send

    I did not do any special things, I just keeped Windows 8 suspend mechanism turned on in my driver and worked on another issue. It is interesting, how did system decide, that miniport has earned selective suspend?

    Wednesday, July 17, 2013 9:40 AM
  • NDIS doesn't do any sort of caching of SS capability; it's re-queried each time the miniport is initialized.  Something must have changed somewhere; computers aren't actually capable of nondeterminism :)

    Wednesday, July 17, 2013 10:34 AM
  • Fully agree with you - computers aren't actually capable of nondeterminism. I have obtained selective suspend with our old device, and before firmware loading ss is disabled in WinDbg, after firmware loadindg we have reenumeration and reloading driver. And with this reloaded driver selective suspend is enabled. Now I analyze logs to understand what is the cause of selective suspend enabling after reloading, because driver is the same.
    Wednesday, July 17, 2013 1:33 PM
  • Ok, I have configured native Windows 8 selective suspend with our old device, this is output from WinDbg:

    SELECTIVE SUSPEND

        State
        Suspended now      No
        Suspend requested  No
        Idle timeout       5 seconds

        Pending Operations
        [None]

        Statistics
        Number of suspends 85
        Suspend latency    89 ms (average)
        Suspend duration   5343 ms (average)
        Suspend duration   7 minutes (total)

        Last event         OID_request
            OID type       OID_IP6_OFFLOAD_STATS

        Last resume reason Send

     

    Good feature, I like it.

    Now I need to understand, why with our new device and with our old device without firmware loaded selective suspend is disabled.

    Thursday, July 18, 2013 7:33 AM
  • Very strange. With both devices the same driver is using and the same capabilities are reported, but in one case selective suspend is disabled and in another case is working good. Is ability to have selective suspend enabled depends only on miniport reported capabilities or some bus specific information obtained without driver can be used by OS to decide allow selective suspend or not?
    Thursday, July 18, 2013 11:27 AM
  • I have found cause. My new device did not provide Remote Wakeup in bmAttributes of his Configuration Descriptor. When I set it, all works fine.
    Thursday, July 18, 2013 4:04 PM
  • Glad to hear it's working.
    Thursday, July 18, 2013 4:49 PM