Re: Bugcheck D1 in NDIS-WDM driver

Tech-Archive recommends: Fix windows errors by optimizing your registry

From: Alireza Dabagh [MS] (alid_at_online.microsoft.com)
Date: 12/17/04


Date: Fri, 17 Dec 2004 05:49:18 -0800

Seems to me that you code is completely unprotected.
For example I see that you check to see if the queue is empty or not and if
it is not, you go ahead and try to "get" the head of queue. how do you know
that between the time you check for non-empty queue and the time you get the
head, the queue does not get empty? the assert code you have only kicks in
if you are running debug version of your code. and then between the time you
"get" the head of queue and the time you "remove" the head, there is no
protection. This is all assuming that at least your Queue routines are safe.
i.e. they use a spinlock to protect the list.
Even if you could guarantee that this code itself is serialized (i.e. you
will never have two thread running osIndicateReceiveDeserized at the same
time,) and your Queue functions are protected, you still need to avoid the
gaps between check, get and remove above because your ReturnPacket handler
can kick in-between and changes your queue. In particular description of
your bug (the bugcheck happens when you have a lot of packet to indicate)
points to lack of list protection and serialization issues in your code.

Put a spinlock around these operations and make sure you release it before
you call NdisMIndicateReceivePacket and see what happens. Make sure you do
the same protection everywhere you access the elements in this queue
(ReturnPacket handler, etc.)

Hope this helps.

-ali

-- 
This posting is provided "AS IS" with no warranties, and confers no rights.
"Harshal" <harshal@gmail.com> wrote in message 
news:1103216938.709945.131110@f14g2000cwb.googlegroups.com...
> Hi,
>
> My NDIS-WDM driver for a wireless NIC (umacusb.sys) is dying with a D1
> bugcheck after receiving a bunch of packets (> 200 in this case).
> Everything else before this is fine i.e. ping and other apps work as
> expected.
>
> I can't figure out where the problem is and would appreciate any
> insight. (Aside: I tried running the driver through the driver verifier
> but other drivers on the PC (for eg. the anti-virus software) crashes
> the verifier. Is there a way to tell the verifier to only check my
> driver and ignore whatever else the other drivers are doing?)
>
>
>
> The relevant code is:
>
> VOID osIndicateReceiveDeserized( PTIWLAN_T pAdapter,
> PUCHAR    pData,
> UINT      length
> )
> {
> PSWRFD          pSwRfd;
> PNDIS_PACKET    PacketArray[MAX_NUM_ALLOCATED_RFDS];
> NDIS_STATUS     SavedPacketStatus[MAX_NUM_ALLOCATED_RFDS];
> UINT            PacketArrayCount = 1;
> PRFDLIST        pRfdL;
> ...
> pRfdL = ( PRFDLIST ) pDc->pContext;
>
> if( QueueEmpty( &pRfdL->RfdList ) )
> {
> dprintf( 1, "Receive buffers went to 0!( %d )\n",
> pRfdL->FreeRfdCount );
> return;
> }
>
> pSwRfd = ( PSWRFD ) QueueGetHead( &pRfdL->RfdList );
> ASSERT( pSwRfd );
>
> // Remove the RFD from the head of the List
> QueueRemoveHead( &pRfdL->RfdList );
> // Get the packet length
> pSwRfd->FrameLength = length;
>
> NdisAdjustBufferLength( ( PNDIS_BUFFER ) pSwRfd->ReceiveBuffer, (
> UINT ) pSwRfd->FrameLength );
>
> NdisMoveMemory( ( PUCHAR )pSwRfd->pBuffer, pData, length );
>
> PacketArray[0] = pSwRfd->ReceivePacket;
>
> NDIS_SET_PACKET_STATUS( PacketArray[0], NDIS_STATUS_SUCCESS );
> SavedPacketStatus[0] = NDIS_STATUS_SUCCESS;
>
> if( PacketArrayCount )
> {
> dprintf( 4, "Indicate receive packet size: %d   Packetarraycount:
> %d FreeRfdCount: %d\n",
> length, PacketArrayCount,  pRfdL->FreeRfdCount);
> pRfdL->FreeRfdCount--;
> NdisMIndicateReceivePacket( pAdapter->osAdapterHandle,
> PacketArray,
> PacketArrayCount );
> }
> ..
> }
>
> and the output of '!analyze -v' is:
>
>
> DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
> An attempt was made to access a pageable (or completely invalid)
> address at an
> interrupt request level (IRQL) that is too high.  This is usually
> caused by drivers using improper addresses.
> If kernel debugger is available get stack backtrace.
> Arguments:
> Arg1: 67027379, memory referenced
> Arg2: 00000002, IRQL
> Arg3: 00000000, value 0 = read operation, 1 = write operation
> Arg4: f75ad50d, address which referenced memory
>
> Debugging Details:
> ------------------
>
>
> OVERLAPPED_MODULE:  rdbss
>
> READ_ADDRESS:  67027379
>
> CURRENT_IRQL:  2
>
> FAULTING_IP:
> NDIS!NdisGetFirstBufferFromPacket+3b
> f75ad50d 8b4614           mov     eax,[esi+0x14]
>
> DEFAULT_BUCKET_ID:  DRIVER_FAULT
>
> BUGCHECK_STR:  0xD1
>
> LAST_CONTROL_TRANSFER:  from f75cc532 to f75ad50d
>
> TRAP_FRAME:  80543030 -- (.trap ffffffff80543030)
> ErrCode = 00000000
> eax=0000004a ebx=8311be30 ecx=80543108 edx=80543104 esi=67027365
> edi=83216ad8
> eip=f75ad50d esp=805430a4 ebp=805430a8 iopl=0         nv up ei pl nz na
> po nc
> cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000
> efl=00010206
> NDIS!NdisGetFirstBufferFromPacket+0x3b:
> f75ad50d 8b4614           mov     eax,[esi+0x14]
> Resetting default scope
>
> STACK_TEXT:
> 805430a8 f75cc532 8311be68 80543100 8054310c
> NDIS!NdisGetFirstBufferFromPacket+0x3b
> 80543114 aea58c04 834a2454 80543144 00000001
> NDIS!ethFilterDprIndicateReceivePacket+0xd4
> 8054335c aea57680 83492000 83494954 0000004a
> umacusb!osIndicateReceiveDeserized+0x255
> [c:\userdata\corextend\driver\seqfrag\wincode.c @ 2398]
> 8054337c aea5da95 831b88c0 83494954 0000004a umacusb!osRxFunc+0x6e
> [c:\userdata\corextend\driver\seqfrag\wincode.c @ 1482]
> 805433d0 aea5d310 83492000 8349494c 00000052
> umacusb!HandleACXMPDU+0x3ec
> [c:\userdata\corextend\driver\seqfrag\iusb.c @ 2246]
> 805433f0 aea5a44c 83492000 8349494c 00000052 umacusb!USBRxComplete+0x9e
> [c:\userdata\corextend\driver\seqfrag\iusb.c @ 1915]
> 80543438 804edbb2 00000000 8351b450 8385a138
> umacusb!USBwinReadWrite_Complete+0x143
> [c:\userdata\corextend\driver\seqfrag\usbaccess.c @ 856]
> 80543468 f6d52af5 8351b450 8323faa8 83a2a028
> nt!IopfCompleteRequest+0xa0
> 805434c0 f6d5373b 46616d64 02707269 83a2a7d8
> USBPORT!USBPORT_CompleteTransfer+0x369
> 805434f0 f6d5431e 026e6f44 83a2a0e0 83a2a0e0
> USBPORT!USBPORT_DoneTransfer+0x135
> 80543528 f6d55abd 83a2a028 805130d8 83a2a230
> USBPORT!USBPORT_FlushDoneTransferList+0x16a
> 80543554 f6d6322b 83a2a028 805130d8 83a2a028
> USBPORT!USBPORT_DpcWorker+0x225
> 80543590 f6d6339c 83a2a028 00000001 8054bf80
> USBPORT!USBPORT_IsrDpcWorker+0x375
> 805435ac 804f2262 83a2a64c 6b755044 00000000
> USBPORT!USBPORT_IsrDpc+0x164
> 805435c0 804ef168 8054bd20 ffdffc50 00000000 nt!KiRetireDpcList+0x46
> ffdff980 8054c364 f7a4b000 00012810 00000002 nt!PopIdle0+0x50
> 83a2a670 ffdff980 f6d547c6 83a2a028 00000000 nt!KiTimerExpireDpc+0x4
> WARNING: Frame IP not in any known module. Following frames may be
> wrong.
> 83a2a670 ffdff980 f6d547c6 83a2a028 00000000 0xffdff980
> 8054c364 83a2a670 804ec27c 00000000 00007daa 0xffdff980
> ffdff980 8054c364 f7a4b000 00012810 00000002 0x83a2a670
> 83a2a670 ffdff980 f6d547c6 83a2a028 00000000 nt!KiTimerExpireDpc+0x4
> 8054c364 83a2a670 804ec27c 00000000 00007daa 0xffdff980
> ffdff980 8054c364 f7a4b000 00012810 00000002 0x83a2a670
> 83a2a670 ffdff980 f6d547c6 83a2a028 00000000 nt!KiTimerExpireDpc+0x4
> 8054c364 83a2a670 804ec27c 00000000 00007daa 0xffdff980
> ffdff980 8054c364 f7a4b000 00012810 00000002 0x83a2a670
> 83a2a670 ffdff980 f6d547c6 83a2a028 00000000 nt!KiTimerExpireDpc+0x4
> 8054c364 83a2a670 804ec27c 00000000 00007daa 0xffdff980
> ffdff980 8054c364 f7a4b000 00012810 00000002 0x83a2a670
> 83a2a670 ffdff980 f6d547c6 83a2a028 00000000 nt!KiTimerExpireDpc+0x4
> 8054c364 83a2a670 804ec27c 00000000 00007daa 0xffdff980
> ffdff980 8054c364 f7a4b000 00012810 00000002 0x83a2a670
> 83a2a670 ffdff980 f6d547c6 83a2a028 00000000 nt!KiTimerExpireDpc+0x4
> 8054c364 83a2a670 804ec27c 00000000 00007daa 0xffdff980
> ffdff980 8054c364 f7a4b000 00012810 00000002 0x83a2a670
> 83a2a670 ffdff980 f6d547c6 83a2a028 00000000 nt!KiTimerExpireDpc+0x4
> 8054c364 83a2a670 804ec27c 00000000 00007daa 0xffdff980
> ffdff980 8054c364 f7a4b000 00012810 00000002 0x83a2a670
> 83a2a670 ffdff980 f6d547c6 83a2a028 00000000 nt!KiTimerExpireDpc+0x4
> 8054c364 83a2a670 804ec27c 00000000 00007daa 0xffdff980
> ffdff980 8054c364 f7a4b000 00012810 00000002 0x83a2a670
> 83a2a670 ffdff980 f6d547c6 83a2a028 00000000 nt!KiTimerExpireDpc+0x4
> 8054c364 83a2a670 804ec27c 00000000 00007daa 0xffdff980
> ffdff980 8054c364 f7a4b000 00012810 00000002 0x83a2a670
> 83a2a670 ffdff980 f6d547c6 83a2a028 00000000 nt!KiTimerExpireDpc+0x4
> 8054c364 83a2a670 804ec27c 00000000 00007daa 0xffdff980
> ffdff980 8054c364 f7a4b000 00012810 00000002 0x83a2a670
> 83a2a670 ffdff980 f6d547c6 83a2a028 00000000 nt!KiTimerExpireDpc+0x4
> 8054c364 83a2a670 804ec27c 00000000 00007daa 0xffdff980
> ffdff980 8054c364 f7a4b000 00012810 00000002 0x83a2a670
>
>
> FOLLOWUP_IP:
> umacusb!osIndicateReceiveDeserized+255
> [c:\userdata\corextend\driver\seqfrag\wincode.c @ 2398]
> aea58c04 8b8de8fdffff     mov     ecx,[ebp-0x218]
>
> SYMBOL_STACK_INDEX:  2
>
> FOLLOWUP_NAME:  MachineOwner
>
> SYMBOL_NAME:  umacusb!osIndicateReceiveDeserized+255
>
> MODULE_NAME:  umacusb
>
> IMAGE_NAME:  umacusb.sys
>
> DEBUG_FLR_IMAGE_TIMESTAMP:  41c1b764
>
> STACK_COMMAND:  .trap ffffffff80543030 ; kb
>
> FAILURE_BUCKET_ID:  0xD1_umacusb!osIndicateReceiveDeserized+255
>
> BUCKET_ID:  0xD1_umacusb!osIndicateReceiveDeserized+255
>
> Followup: MachineOwner
> ---------
>
>
> Any help is much appreciated.
>
> Regards,
> - Harshal
> 


Relevant Pages

  • [RFC] macvlan: add tap device backend
    ... This is a second prototype of a new interface into the network ... to eventually replace tun/tap and the bridge driver ... we can do most of that efficiently in the Linux bridge code, ... * A macvtap queue is the central object of this driver, ...
    (Linux-Kernel)
  • Re: IF_HANDOFF vs. IFQ_HANDOFF
    ... Is IF_HANDOFF supposed to be used only when the target queue is not the ... The network adapter's transmit descriptor ring ... whether coalescing that locking with existing driver locking makes ... The whole point of the IFF_OACTIVE flag is to suppress the call to the ...
    (freebsd-net)
  • Re: Changes in the network interface queueing handoff model
    ... layer output routine via ifp->if_outputwith the ifnet pointer, packet, ... as ARP), and hands off to the ifnet driver via a call to IFQ_HANDOFF, ... encapsulation and wrapping, and notifies the hardware. ... The ifnet layer send queue is becoming decreasingly useful over time. ...
    (freebsd-arch)
  • Changes in the network interface queueing handoff model
    ... 5BOne of the ideas that I, Scott Long, and a few others have been bouncing around for some time is a restructuring of the network interface packet transmission API to reduce the number of locking operations and allow network device drivers increased control of the queueing behavior. ... to "start" output by the driver. ... encapsulation and wrapping, and notifies the hardware. ... The ifnet layer send queue is becoming decreasingly useful over time. ...
    (freebsd-net)
  • Changes in the network interface queueing handoff model
    ... 5BOne of the ideas that I, Scott Long, and a few others have been bouncing around for some time is a restructuring of the network interface packet transmission API to reduce the number of locking operations and allow network device drivers increased control of the queueing behavior. ... to "start" output by the driver. ... encapsulation and wrapping, and notifies the hardware. ... The ifnet layer send queue is becoming decreasingly useful over time. ...
    (freebsd-arch)