Пример #1
0
VOID
DeferredRxCompleteDpc(
    IN PKDPC Dpc,
    IN PVOID DeferredContext,
    IN PVOID SystemArgument1,
    IN PVOID SystemArgument2
){
	PRX_COMP_DPC_CTX     rxCompCtx = DeferredContext;
	PDEVICE_CONTEXT		deviceContext = rxCompCtx->DeviceContext;

	UNREFERENCED_PARAMETER(Dpc);
	UNREFERENCED_PARAMETER(SystemArgument1);
	UNREFERENCED_PARAMETER(SystemArgument2);

	LpxReceiveComplete2(deviceContext, &rxCompCtx->ReceivedPackets);

	ExFreeToNPagedLookasideList(&deviceContext->DeferredRxCompContext, rxCompCtx);

	ACQUIRE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
	ClearFlag( deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_DEFFERED_DPC_SET );
	RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );

	LpxReceiveComplete( deviceContext );

	LpxDereferenceDeviceContext("RxCompDpc", deviceContext, DCREF_REQUEST);
}
Пример #2
0
PCONNECTION
WalkConnectionTable (
    IN PENDPOINT Endpoint,
    IN OUT PCSHORT Index
    )
{
    CSHORT i;
    PTABLE_HEADER tableHeader;
    PCONNECTION connection;
    KIRQL oldIrql;

    ACQUIRE_SPIN_LOCK( &ENDPOINT_SPIN_LOCK(0), &oldIrql );
    for ( i = 1; i < ENDPOINT_LOCK_COUNT ; i++ ) {
        ACQUIRE_DPC_SPIN_LOCK( &ENDPOINT_SPIN_LOCK(i) );
    }

    tableHeader = &Endpoint->ConnectionTable;

    for ( i = *Index + 1; i < tableHeader->TableSize; i++ ) {

        connection = (PCONNECTION)tableHeader->Table[i].Owner;
        if ( (connection != NULL) &&
             (GET_BLOCK_STATE(connection) == BlockStateActive) ) {
            *Index = i;
            SrvReferenceConnectionLocked( connection );
            goto exit;
        }
    }
    connection = NULL;

exit:

    for ( i = ENDPOINT_LOCK_COUNT-1 ; i > 0  ; i-- ) {
        RELEASE_DPC_SPIN_LOCK( &ENDPOINT_SPIN_LOCK(i) );
    }
    RELEASE_SPIN_LOCK( &ENDPOINT_SPIN_LOCK(0), oldIrql );

    return connection;
} // WalkConnectionTable
Пример #3
0
VOID
DeferredLpxReceiveComplete (
    IN PKDPC Dpc,
    IN PVOID DeferredContext,
    IN PVOID SystemArgument1,
    IN PVOID SystemArgument2
	)
{
	PDEVICE_CONTEXT		deviceContext = DeferredContext;

	UNREFERENCED_PARAMETER( Dpc );
	UNREFERENCED_PARAMETER( SystemArgument1 );
	UNREFERENCED_PARAMETER( SystemArgument2 );

	LpxReceiveComplete2( deviceContext, &deviceContext->DeferredLpxReceiveCompleteDpcPacketList );

	ACQUIRE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
	deviceContext->DeferredLpxReceiveCompleteDpcRun = FALSE;
	RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );

	LpxReceiveComplete( deviceContext );

	LpxDereferenceDeviceContext( "DeferredLpxReceiveComplete", deviceContext, DCREF_REQUEST );
}
Пример #4
0
VOID
LpxReceiveComplete (
	IN NDIS_HANDLE BindingContext
	)
{
#if 1

	PDEVICE_CONTEXT		deviceContext = (PDEVICE_CONTEXT)BindingContext;
	BOOLEAN				queued;


	ACQUIRE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );

	IF_LPXDBG(LPX_DEBUG_TEST)
		ASSERT( FALSE );

	if (IsListEmpty(&deviceContext->PacketInProgressList)) {

		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
		return;
	}

	if (deviceContext->DeferredLpxReceiveCompleteDpcRun == TRUE) {

		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
		return;
	}

	LPX_ASSERT( IsListEmpty(&deviceContext->DeferredLpxReceiveCompleteDpcPacketList) );

	deviceContext->DeferredLpxReceiveCompleteDpcPacketList.Flink = deviceContext->PacketInProgressList.Flink;
	deviceContext->DeferredLpxReceiveCompleteDpcPacketList.Blink = deviceContext->PacketInProgressList.Blink;
	deviceContext->DeferredLpxReceiveCompleteDpcPacketList.Flink->Blink = &deviceContext->DeferredLpxReceiveCompleteDpcPacketList;
	deviceContext->DeferredLpxReceiveCompleteDpcPacketList.Blink->Flink = &deviceContext->DeferredLpxReceiveCompleteDpcPacketList;

	InitializeListHead( &deviceContext->PacketInProgressList );

	//
	// Perform actual LPX receive completion
	// If the completion is deferred, queue the DPC.
	// Some NIC drivers show receiving performance degrade
	// when receive complete routine consumes much CPU time.
	// Ex> Broadcom Giga ehternet 3788. driver name = b57nd60x.sys 11/1/2005/11:30 164KB
	//

	LpxReferenceDeviceContext( "LpxReceiveComplete", deviceContext, DCREF_REQUEST );

	deviceContext->DeferredLpxReceiveCompleteDpcRun = TRUE;

	queued = KeInsertQueueDpc( &deviceContext->DeferredLpxReceiveCompleteDpc, NULL, NULL );
	
	if (queued) {

	} else {

		LPX_ASSERT( FALSE );
		deviceContext->DeferredLpxReceiveCompleteDpcRun = FALSE;
		LpxDereferenceDeviceContext( "LpxReceiveComplete", deviceContext, DCREF_REQUEST );		
	}

	if (queued == FALSE) {

		deviceContext->DeferredLpxReceiveCompleteDpcRun = TRUE;
	}

	RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );

	if (queued == FALSE) {

		LpxReceiveComplete2( BindingContext, &deviceContext->DeferredLpxReceiveCompleteDpcPacketList );

		ACQUIRE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
		deviceContext->DeferredLpxReceiveCompleteDpcRun = FALSE;
		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
	}

#else

	PDEVICE_CONTEXT		deviceContext = (PDEVICE_CONTEXT)BindingContext;
	PRX_COMP_DPC_CTX	rxCompDpcCtx;
	LIST_ENTRY			receivedPackets;

	ACQUIRE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock);

	IF_LPXDBG(LPX_DEBUG_TEST)
		ASSERT( FALSE );

	if (FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_DEFFERED_DPC_SET)) {

		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock);
		return;
	}

	if (deviceContext->SendingThreadCount) {

		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock);
		return;
	}

	if (IsListEmpty(&deviceContext->PacketInProgressList)) {

		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock);
		return;
	}

	//
	// Allocate a DPC context
	//
	rxCompDpcCtx = ExAllocateFromNPagedLookasideList(&deviceContext->DeferredRxCompContext);
	
	if (rxCompDpcCtx == NULL) {

		LPX_ASSERT( FALSE );
		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock);
		return;
	}

	//
	// Move received packets from the in-progress list to the temporary list.
	// LpxReceiveComplete2() will process only packets in this temporary list.
	// By doing this, we can spread out time-consume in LpxReceiveComplete2().
	// Especially, deferred LpxReceiveComplete2() in DPC routine does not
	// need to loop and timeout-check because LpxReceiveComplete2() will process
	// only packets in the temporary list.
	//
	if(rxCompDpcCtx) {
		KeInitializeDpc(&rxCompDpcCtx->Dpc, DeferredRxCompleteDpc, rxCompDpcCtx);
		rxCompDpcCtx->DeviceContext = deviceContext;
		rxCompDpcCtx->ReceivedPackets.Flink = deviceContext->PacketInProgressList.Flink;
		rxCompDpcCtx->ReceivedPackets.Blink = deviceContext->PacketInProgressList.Blink;
		deviceContext->PacketInProgressList.Flink->Blink = &rxCompDpcCtx->ReceivedPackets;
		deviceContext->PacketInProgressList.Blink->Flink = &rxCompDpcCtx->ReceivedPackets;
	} else {
		receivedPackets.Flink = deviceContext->PacketInProgressList.Flink;
		receivedPackets.Blink = deviceContext->PacketInProgressList.Blink;
		deviceContext->PacketInProgressList.Flink->Blink = &receivedPackets;
		deviceContext->PacketInProgressList.Blink->Flink = &receivedPackets;
	}
	InitializeListHead(&deviceContext->PacketInProgressList);

	//
	// Perform actual LPX receive completion
	// If the completion is deferred, queue the DPC.
	// Some NIC drivers show receiving performance degrade
	// when receive complete routine consumes much CPU time.
	// Ex> Broadcom Giga ehternet 3788. driver name = b57nd60x.sys 11/1/2005/11:30 164KB
	//

	if(rxCompDpcCtx) {
		BOOLEAN	queued;
		LpxReferenceDeviceContext("RxCompDpc", deviceContext, DCREF_REQUEST);
		queued = KeInsertQueueDpc(&rxCompDpcCtx->Dpc, NULL, NULL);
		ASSERT(queued);
		if(!queued) {
			LpxDereferenceDeviceContext("RxCompDpc", deviceContext, DCREF_REQUEST);
		
		} else {

			SetFlag( deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_DEFFERED_DPC_SET );
		}

		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock);

	} else {
	
		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock);

		// Call actual LPX receive completion directly.
		LpxReceiveComplete2( BindingContext, &receivedPackets );
	}

#endif
}
Пример #5
0
NTSTATUS
NbfTdiReceive(
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine performs the TdiReceive request for the transport provider.

Arguments:

    Irp - I/O Request Packet for this request.

Return Value:

    NTSTATUS - status of operation.

--*/

{
    NTSTATUS status;
    PTP_CONNECTION connection;
    KIRQL oldirql;
    PIO_STACK_LOCATION irpSp;

    //
    // verify that the operation is taking place on a connection. At the same
    // time we do this, we reference the connection. This ensures it does not
    // get removed out from under us. Note also that we do the connection
    // lookup within a try/except clause, thus protecting ourselves against
    // really bogus handles
    //

    irpSp = IoGetCurrentIrpStackLocation (Irp);
    connection = irpSp->FileObject->FsContext;

    //
    // Check that this is really a connection.
    //

    if ((connection->Size != sizeof (TP_CONNECTION)) ||
        (connection->Type != NBF_CONNECTION_SIGNATURE)) {
#if DBG
        NbfPrint2 ("TdiReceive: Invalid Connection %lx Irp %lx\n", connection, Irp);
#endif
        return STATUS_INVALID_CONNECTION;
    }

    //
    // Initialize bytes transferred here.
    //

    Irp->IoStatus.Information = 0;              // reset byte transfer count.

    // This reference is removed by NbfDestroyRequest.

    KeRaiseIrql (DISPATCH_LEVEL, &oldirql);

    ACQUIRE_DPC_C_SPIN_LOCK (&connection->SpinLock);

    if ((connection->Flags & CONNECTION_FLAGS_READY) == 0) {

        RELEASE_DPC_C_SPIN_LOCK (&connection->SpinLock);

        Irp->IoStatus.Status = connection->Status;
        IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);

        status = STATUS_PENDING;

    } else {
        KIRQL cancelIrql;

        //
        // Once the reference is in, LinkSpinLock will be valid.
        //

        NbfReferenceConnection("TdiReceive request", connection, CREF_RECEIVE_IRP);
        RELEASE_DPC_C_SPIN_LOCK (&connection->SpinLock);

        IoAcquireCancelSpinLock(&cancelIrql);
        ACQUIRE_DPC_SPIN_LOCK (connection->LinkSpinLock);

        IRP_RECEIVE_IRP(irpSp) = Irp;
        IRP_RECEIVE_REFCOUNT(irpSp) = 1;

#if DBG
        NbfReceives[NbfReceivesNext].Irp = Irp;
        NbfReceives[NbfReceivesNext].Request = NULL;
        NbfReceives[NbfReceivesNext].Connection = (PVOID)connection;
        NbfReceivesNext = (NbfReceivesNext++) % TRACK_TDI_LIMIT;
#endif

        //
        // If this IRP has been cancelled, complete it now.
        //

        if (Irp->Cancel) {

#if DBG
            NbfCompletedReceives[NbfCompletedReceivesNext].Irp = Irp;
            NbfCompletedReceives[NbfCompletedReceivesNext].Request = NULL;
            NbfCompletedReceives[NbfCompletedReceivesNext].Status = STATUS_CANCELLED;
            {
                ULONG i,j,k;
                PUCHAR va;
                PMDL mdl;

                mdl = Irp->MdlAddress;

                NbfCompletedReceives[NbfCompletedReceivesNext].Contents[0] = (UCHAR)0;

                i = 1;
                while (i<TRACK_TDI_CAPTURE) {
                    if (mdl == NULL) break;
                    va = MmGetSystemAddressForMdl (mdl);
                    j = MmGetMdlByteCount (mdl);

                    for (i=i,k=0;i<TRACK_TDI_CAPTURE&k<j;i++,k++) {
                        NbfCompletedReceives[NbfCompletedReceivesNext].Contents[i] = *va++;
                    }
                    mdl = mdl->Next;
                }
            }

            NbfCompletedReceivesNext = (NbfCompletedReceivesNext++) % TRACK_TDI_LIMIT;
#endif

            //
            // It is safe to do this with locks held.
            //
            NbfCompleteReceiveIrp (Irp, STATUS_CANCELLED, 0);

            RELEASE_DPC_SPIN_LOCK (connection->LinkSpinLock);
            IoReleaseCancelSpinLock(cancelIrql);

        } else {

            //
            // Insert onto the receive queue, and make the IRP
            // cancellable.
            //

            InsertTailList (&connection->ReceiveQueue,&Irp->Tail.Overlay.ListEntry);
            IoSetCancelRoutine(Irp, NbfCancelReceive);

            //
            // Release the cancel spinlock out of order. Since we were
            // already at dpc level when it was acquired, we don't
            // need to swap irqls.
            //
            ASSERT(cancelIrql == DISPATCH_LEVEL);
            IoReleaseCancelSpinLock(cancelIrql);

            //
            // This call releases the link spinlock, and references the
            // connection first if it needs to access it after
            // releasing the lock.
            //

            AwakenReceive (connection);             // awaken if sleeping.

        }

        status = STATUS_PENDING;

    }

    KeLowerIrql (oldirql);

    return status;
} /* TdiReceive */
Пример #6
0
VOID
ActivateReceive(
    PTP_CONNECTION Connection
    )

/*++

Routine Description:

    This routine activates the next TdiReceive request on the specified
    connection object if there is no active request on that connection
    already.  This allows the request to accept data on the connection.

    NOTE: THIS FUNCTION MUST BE CALLED AT DPC LEVEL.

Arguments:

    Connection - Pointer to a TP_CONNECTION object.

Return Value:

    none.

--*/

{
    PIRP Irp;

    ASSERT (KeGetCurrentIrql() == DISPATCH_LEVEL);

    IF_NBFDBG (NBF_DEBUG_RCVENG) {
        NbfPrint0 ("    ActivateReceive:  Entered.\n");
    }

    //
    // The ACTIVE_RECEIVE bitflag will be set on the connection if
    // the receive-fields in the CONNECTION object are valid.  If
    // this flag is cleared, then we try to make the next TdiReceive
    // request in the ReceiveQueue the active request.
    //

    ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
    if (!(Connection->Flags & CONNECTION_FLAGS_ACTIVE_RECEIVE)) {
        if (!IsListEmpty (&Connection->ReceiveQueue)) {

            //
            // Found a receive, so make it the active one.
            //

            Connection->Flags |= CONNECTION_FLAGS_ACTIVE_RECEIVE;

            Irp = CONTAINING_RECORD(
                      Connection->ReceiveQueue.Flink,
                      IRP,
                      Tail.Overlay.ListEntry);
            Connection->MessageBytesReceived = 0;
            Connection->MessageBytesAcked = 0;
            Connection->MessageInitAccepted = 0;
            Connection->CurrentReceiveIrp = Irp;
            Connection->CurrentReceiveSynchronous =
                Connection->Provider->MacInfo.SingleReceive;
            Connection->CurrentReceiveMdl = Irp->MdlAddress;
            Connection->ReceiveLength = IRP_RECEIVE_LENGTH(IoGetCurrentIrpStackLocation(Irp));
            Connection->ReceiveByteOffset = 0;
        }
    }
    RELEASE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
    IF_NBFDBG (NBF_DEBUG_RCVENG) {
        NbfPrint0 ("    ActivateReceive:  Exiting.\n");
    }
} /* ActivateReceive */
Пример #7
0
VOID
LpxReceiveComplete (
	IN NDIS_HANDLE BindingContext
	)
{
	PDEVICE_CONTEXT deviceContext = (PDEVICE_CONTEXT)BindingContext;
	BOOLEAN			queued;


	ACQUIRE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );

	IF_LPXDBG (LPX_DEBUG_TEST) {

		NDAS_ASSERT(FALSE);
	}

	if (IsListEmpty(&deviceContext->PacketInProgressList)) {

		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
		return;
	}

	if (deviceContext->DeferredLpxReceiveCompleteDpcRun == TRUE) {

		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
		return;
	}

	NDAS_ASSERT( IsListEmpty(&deviceContext->DeferredLpxReceiveCompleteDpcPacketList) );

	deviceContext->DeferredLpxReceiveCompleteDpcPacketList.Flink = deviceContext->PacketInProgressList.Flink;
	deviceContext->DeferredLpxReceiveCompleteDpcPacketList.Blink = deviceContext->PacketInProgressList.Blink;

	deviceContext->DeferredLpxReceiveCompleteDpcPacketList.Flink->Blink = &deviceContext->DeferredLpxReceiveCompleteDpcPacketList;
	deviceContext->DeferredLpxReceiveCompleteDpcPacketList.Blink->Flink = &deviceContext->DeferredLpxReceiveCompleteDpcPacketList;

	InitializeListHead( &deviceContext->PacketInProgressList );

	// Perform actual LPX receive completion
	// If the completion is deferred, queue the DPC.
	// Some NIC drivers show receiving performance degrade
	// when receive complete routine consumes much CPU time.
	// Ex> Broadcom Giga ehternet 3788. driver name = b57nd60x.sys 11/1/2005/11:30 164KB

	LpxReferenceDeviceContext( "LpxReceiveComplete", deviceContext, DCREF_REQUEST );

	NDAS_ASSERT( deviceContext->DeferredLpxReceiveCompleteDpcRun == FALSE );

	queued = KeInsertQueueDpc( &deviceContext->DeferredLpxReceiveCompleteDpc, NULL, NULL );
	
	if (queued == FALSE) {

		NDAS_ASSERT(FALSE);
		LpxDereferenceDeviceContext( "LpxReceiveComplete", deviceContext, DCREF_REQUEST );		
	}

	deviceContext->DeferredLpxReceiveCompleteDpcRun = TRUE;

	RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );

	if (queued == FALSE) {

		LpxReceiveComplete2( BindingContext, &deviceContext->DeferredLpxReceiveCompleteDpcPacketList );

		ACQUIRE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
		deviceContext->DeferredLpxReceiveCompleteDpcRun = FALSE;
		RELEASE_DPC_SPIN_LOCK( &deviceContext->PacketInProgressQSpinLock );
	}

	return;
}