will i recv packet during MiniportHalt is running?

Hi, all

i’m writting a NDIS Intermediate driver, and I call NdisCloseAdapter in MiniportHalt routine to close the binding with underlying NIC miniport.
my questions are:

  1. Will I recv packet after entering MiniportHalt routine but before the NdisCloseAdapter is called?

  2. I the answer for above question is YES, then my ProtocolReceive or ProtocolReceivePacket routine will get called, so is it still safe to use the binding with underlying NIC miniport (passed to me by parameter ProtocolBindingContext) to send packet in the context of ProtocolReceive
    of ProtocolReceivePacket? Any synchronization needed?

E.g., when i recv a request packet, can i just compose a reply packet and send it out at once (I don’t need to queue the request packet), using the binding handle pass to me by parameter ProtocolBindingContext, without care about whether the binding btw. me and NIC miniport is releasing.

thanks!

Weiyu Dong


ÑÅ»¢Ãâ·ÑÓÊÏä-3.5GÈÝÁ¿£¬20M¸½¼þ

The short anser to (1) is that depends on how the ‘miniport’ was terminated. If you called NdisIMDeinitializeDeviceInstance() in your ProtocolUnbind() then you probably wont get any more Rx indications on the binding (you are being unbound) but I cannot say I have really ever looked that closely. If the miniport ‘virtual adapter’ is being stopped by PnP for some other reason and you shure could get RX and status indications since you have not called close on the adapter.

The short answer to (2) is no, you cannot call NdisSend() on a binding handle that you have called NdisClose() on. After you call close, you are done. Don’t touch the binding handle.

Good Luck,
Dave Cattley
Consulting Engineer
Systems Software Development


From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of identifier scorpio
Sent: Wednesday, July 05, 2006 9:47 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] will i recv packet during MiniportHalt is running?

Hi, all

i’m writting a NDIS Intermediate driver, and I call NdisCloseAdapter in MiniportHalt routine to close the binding with underlying NIC miniport.
my questions are:

  1. Will I recv packet after entering MiniportHalt routine but before the NdisCloseAdapter is called?

  2. I the answer for above question is YES, then my ProtocolReceive or ProtocolReceivePacket routine will get called, so is it still safe to use the binding with underlying NIC miniport (passed to me by parameter ProtocolBindingContext) to send packet in the context of ProtocolReceive
    of ProtocolReceivePacket? Any synchronization needed?

E.g., when i recv a request packet, can i just compose a reply packet and send it out at once (I don’t need to queue the request packet), using the binding handle pass to me by parameter ProtocolBindingContext, without care about whether the binding btw. me and NIC miniport is releasing.

thanks!

Weiyu Dong


雅虎免费邮箱-3.5G容量,20M附件 http:</http:> — Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256 To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

thank you, David.

But i don’t agree with your answer to my 2nd question. I observed the prototypes of Ndis receive handlers (such as ProtocolReceive and ProtocolReceivePacket), they all take ProtocolBindingContext as the first parameter, which is actually the binding handle to underlying NIC. since NDIS pass the binding handle to me, I think it should be safe to use it in receive handler, e.g., its safe to use it to send packet in receive handler context, without need to care about whether the unbinding operation is in processing or not.

do you agree?

regards!

Weiyu Dong.


Mp3·è¿ñËÑ-иèÈȸè¸ßËÙÏÂ

Weiyu,

From the DDK documentation:

ProtocolBindingContext
Specifies the handle to a protocol-allocated context area in which the protocol driver maintains per-binding run-time state. The driver supplied this handle when it called mk: NdisOpenAdapter.

What is passed to an ‘indication’ handler by NDIS is a ‘Context’ value defined by the driver, not, a binding handle. This value is determined by the driver (your driver) and not NDIS. It is typically the address of a structure representing the binding in the protocol, or, in an IM driver, the protocol/adapter pair. It is usual that the NDIS Binding Handle is stored in this context (structure). The distinction between Handle and Context in NDIS is very important. An NdisXxxHandle is an opaque value representing some resource in NDIS an is defined and managed by NDIS. An NdisXxxContext is a value defined by your driver and managed by your driver but associated with some resource in NDIS. NDIS only manages the association (by storing the value) between the NDIS object and the ‘context’ object.

So again I will say, no, I don’t agree. After a protocol calls NdisCloseAdapter() the protocol must not reference the NdisBindingHandle again. Or as the DDK documentation states for NdisCloseAdapter()

As soon as a protocol calls NdisCloseAdapter, the handle at NdisBindingHandle should be considered invalid by the caller. It is a programming error to pass this handle in any subsequent call to an NdisXxx function.

Good Luck,
Dave Cattley
Consulting Engineer
Systems Software Development



From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of identifier scorpio
Sent: Wednesday, July 05, 2006 11:39 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] will i recv packet during MiniportHalt is running?

thank you, David.

But i don’t agree with your answer to my 2nd question. I observed the prototypes of Ndis receive handlers (such as ProtocolReceive and ProtocolReceivePacket), they all take ProtocolBindingContext as the first parameter, which is actually the binding handle to underlying NIC. since NDIS pass the binding handle to me, I think it should be safe to use it in receive handler, e.g., its safe to use it to send packet in receive handler context, without need to care about whether the unbinding operation is in processing or not.

do you agree?

regards!

Weiyu Dong.



Mp3疯狂搜-新歌热歌高速下 http: — Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256 To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer</http:></mk:>

Sorry, David
I have mistake in statmement of my last post, the *binding handle* is indeed different with *binding context*.
So, as what you said, to avoid blindly using the *binding handle*, i think i should do some synchronization btw receive handler and MpHalt.
Add a *State* variable in PADAPT and a *SpinLock* to guard the *State*. Each time i enter recv handler, check binding state. if the binding state is IDLE (which means, unbinding is undergoing), abandon the packet. Note that all recv handler works at DISPATCH_LEVEL, so if the check is passed, NdisCloseAdapter will not get called in MPHalt() until recv handler return, so i can safely use the binding handle to NdisSend a packet in recv handler.
Is following code OK?
NDIS_STATUS
PtReceive(
IN NDIS_HANDLE ProtocolBindingContext,

)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;

KeAcquireSpinLock( &pAdapt->SpinLock, &OldIrql);
if ( pAdapt->State != BINDING_STATE_ACTIVE) {
KeReleaseSpinLock( &pAdapt->SpinLock, OldIrql);
return NDIS_NOT_ACCEPT;
}
KeReleaseSpinLock( &pAdapt->SpinLock, OldIrql);
// actraully recv operation
// …
// send reply in PtReceive context.
NdisSend( &Status, pAdapt->BindingHandle, pPacket);

}
INT
PtReceivePacket(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;

KeAcquireSpinLock( &pAdapt->SpinLock, &OldIrql);
if ( pAdapt->State != BINDING_STATE_ACTIVE) {
KeReleaseSpinLock( &pAdapt->SpinLock, OldIrql);
return 0;
}
KeReleaseSpinLock( &pAdapt->SpinLock, OldIrql);

// actraully recv operation
// …
// send reply in PtReceive context.
NdisSend( &Status, pAdapt->BindingHandle, pPacket);

}
VOID
MPHalt(
IN NDIS_HANDLE MiniportAdapterContext
)
{
PADAPT pAdapt = (PADAPT)MiniportAdapterContext;

// set binding state to IDLE
KeAcquireSpinLock( &pAdapt->SpinLock, &OldIrql);
SET_BINDING_STATE( pAdapt, BINDING_STATE_IDLE);
KeReleaseSpinLock( &pAdapt->SpinLock, OldIrql);

//
// Make sure any threads trying to send have finished.
//
for (LoopCount = 0; LoopCount < 60; LoopCount++)
{
if ( (PendingCount = NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle)) == 0)
{
break;
}
DBGPRINT((“%d pended sending, waiting …\n”, PendingCount));
_SLEEP(1);
}
ASSERT(LoopCount < 60);
//
// Make sure no outstanding recv operations.
//
for (LoopCount = 0; LoopCount < 60; LoopCount++)
{
if ( (PendingCount = NdisPacketPoolUsage(pAdapt->RecvPacketPoolHandle)) == 0)
{
break;
}
DBGPRINT((“%d pended recving, waiting …\n”, PendingCount));
_SLEEP(1);
}
ASSERT(LoopCount < 60);

//
// If we have a valid bind, close the miniport below the protocol
//
if (pAdapt->BindingHandle != NULL)
{
//
// Close the binding below. and wait for it to complete
//
NdisResetEvent(&pAdapt->Event);
NdisCloseAdapter(&Status, pAdapt->BindingHandle);
if (Status == NDIS_STATUS_PENDING)
{
NdisWaitEvent(&pAdapt->Event, 0);
Status = pAdapt->Status;
}
ASSERT (Status == NDIS_STATUS_SUCCESS);
pAdapt->BindingHandle = NULL;
}
//
// Before MiniportHalt routine is called, all binding btw. upper protocols and me
// have already been released, and after NdisCloseAdapter is called, all bindings
// btw. under NICs and me have already been released. Now, i’ll not recv any
// sending request from upper protocol, and i’ll not recv any recving request from
// below NICs, so now i can go ahead to release packet pool.
//
if (pAdapt->SendPacketPoolHandle != NULL)
{
ASSERT( 0 == NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle));
NdisFreePacketPool(pAdapt->SendPacketPoolHandle);
}
if (pAdapt->RecvPacketPoolHandle != NULL)
{
ASSERT( 0 == NdisPacketPoolUsage(pAdapt->RecvPacketPoolHandle));
NdisFreePacketPool(pAdapt->RecvPacketPoolHandle);
}
NdisFreeMemory( pAdapt);
return;
}


ÇÀ×¢ÑÅ»¢Ãâ·ÑÓÊÏä-3.5GÈÝÁ¿£¬20M¸½¼þ£¡