void cdc_ncm_intr_complete(struct urb *urb)
{
	struct if_usb_devdata *pipe_data = urb->context;
	struct usb_link_device *usb_ld = pipe_data->usb_ld;
	int ret;

	mif_debug("status = %d\n", urb->status);

	switch (urb->status) {
	/* success */
	case -ENOENT:		/* urb killed by L2 suspend */
	case 0:
		usb_ld->rx_cnt++;
		if (urb->actual_length) {
			mif_info("ep=%d\n", usb_pipeendpoint(urb->pipe));
			pr_urb(__func__, urb);
		}
		cdc_ncm_status(pipe_data, urb);
		break;

	case -ESHUTDOWN:	/* hardware gone */
		mif_err("intr shutdown, code %d\n", urb->status);
		return;

	/* NOTE:  not throttling like RX/TX, since this endpoint
	 * already polls infrequently
	 */
	default:
		mif_err("intr status %d\n", urb->status);
		break;
	}

	if (!urb->status) { /*skip -ENOENT L2 enter status */
		memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
		ret = usb_submit_urb(urb, GFP_ATOMIC);
		mif_debug("status: usb_submit_urb ret=%d\n", ret);
		if (ret != 0)
			mif_err("intr resubmit --> %d\n", ret);
	}
}
NTSTATUS
InterruptPipeCompletion(
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp,
    IN PVOID            Context
    )
/*++

Routine Description:

    Completion routine for the read request. This routine
    indicates the received packet from the WDM driver to 
    NDIS. This routine also handles the case where another 
    thread has canceled the read request.
        
Arguments:

    DeviceObject    -  not used. Should be NULL
    Irp    -   Pointer to our read IRP
    Context - pointer to our adapter context structure

Return Value:

    STATUS_MORE_PROCESSING_REQUIRED - because this is an asynchronouse IRP
    and we want to reuse it.
    
--*/
{


	PNOTICB    pNotiCB = (PNOTICB)Context;
	PMP_ADAPTER Adapter = pNotiCB->Adapter;
	ULONG   bytesRead = 0;

	UNREFERENCED_PARAMETER(DeviceObject);

	DEBUGP(MP_TRACE, ("--> InterruptPipeCompletion\n"));


	if(!NT_SUCCESS(Irp->IoStatus.Status)) {       

		Adapter->nReadsCompletedWithError++;        
		DEBUGP (MP_LOUD, ("Read request failed %x\n", Irp->IoStatus.Status));        

		//
		// Clear the flag to prevent any more reads from being
		// posted to the target device.
		//
		MP_CLEAR_FLAG(Adapter, fMP_POST_INTERRUPT);

	} else {
		bytesRead = (ULONG)pNotiCB->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
		DEBUGP (MP_VERY_LOUD, ("Read %d bytes\n", bytesRead));
		pNotiCB->ulSize=bytesRead;
	}

	if (InterlockedExchange((PVOID)&pNotiCB->IrpLock, IRPLOCK_COMPLETED) 
		== IRPLOCK_CANCEL_STARTED) {
			// 
			// NICFreeBusyRecvPackets has got the control of the IRP. It will
			// now take the responsibility of freeing  the IRP. 
			// Therefore...

			return STATUS_MORE_PROCESSING_REQUIRED;
	}
	if (NT_SUCCESS(Irp->IoStatus.Status))
	{
		cdc_ncm_status(Adapter,pNotiCB->pData,pNotiCB->ulSize);
	}

	if(NdisInterlockedDecrement(&pNotiCB->Ref) == 0)
	{
		NICFreeNotify(pNotiCB);
	}

	DEBUGP(MP_TRACE, ("<-- InterruptPipeCompletion\n"));
	return STATUS_MORE_PROCESSING_REQUIRED;
}