repository: c:/kernel.org/kvm-guest-drivers-windows branch: master commit 69fae3b5cdc84fbd0882d3d32f7deff29c246171 Author: Vadim Rozenfeld <vroze...@redhat.com> Date: Mon Sep 27 13:08:02 2010 +0200
[viostor] fix flush, shutdown and synchronize cache handlers diff --git a/viostor/SOURCES b/viostor/SOURCES index 5701b78..9680b09 100644 --- a/viostor/SOURCES +++ b/viostor/SOURCES @@ -1,20 +1,30 @@ TARGETNAME=viostor TARGETTYPE=MINIPORT -!if "$(DDK_TARGET_OS)" == "WinNET" +!if "$(DDK_TARGET_OS)" == "WinNET" +INF_NAME=WinNET C_DEFINES = -DUSE_STORPORT=1 $(C_DEFINES) TARGETLIBS=$(SDK_LIB_PATH)\storport.lib !elseif "$(DDK_TARGET_OS)" == "WinLH" +INF_NAME=WinLH C_DEFINES = -DUSE_STORPORT=1 $(C_DEFINES) C_DEFINES = -DMSI_SUPPORTED=1 $(C_DEFINES) +#C_DEFINES = -DINDIRECT_SUPPORTED=1 $(C_DEFINES) TARGETLIBS=$(SDK_LIB_PATH)\storport.lib !elseif "$(DDK_TARGET_OS)" == "WinXP" +INF_NAME=WinXP TARGETLIBS=$(SDK_LIB_PATH)\scsiport.lib !else +INF_NAME=WinLH C_DEFINES = -DUSE_STORPORT=1 $(C_DEFINES) TARGETLIBS=$(SDK_LIB_PATH)\storport.lib !endif +INF_TARGET=$(OBJ_PATH)\$(O)\$(TARGETNAME).inf + +NTTARGETFILE1=$(INF_TARGET) +PASS1_BINPLACE=$(NTTARGETFILE1) + SOURCES= virtio_stor.c \ virtio_stor_utils.c \ virtio_stor_hw_helper.c \ diff --git a/viostor/virtio_pci.c b/viostor/virtio_pci.c index ffa2ed0..6bc75a1 100644 --- a/viostor/virtio_pci.c +++ b/viostor/virtio_pci.c @@ -115,6 +115,7 @@ VirtIODeviceFindVirtualQueue( ULONG dummy; PHYSICAL_ADDRESS pa; ULONG pageNum; + ULONG pfns; unsigned res; PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; @@ -135,11 +136,11 @@ VirtIODeviceFindVirtualQueue( // Check if queue is either not available or already active. num = ScsiPortReadPortUshort((PUSHORT)(adaptExt->device_base + VIRTIO_PCI_QUEUE_NUM)); - - RhelDbgPrint(TRACE_LEVEL_FATAL, ("%s>>> [vp_dev->addr + VIRTIO_PCI_QUEUE_NUM] = %x\n", __FUNCTION__, num) ); - if (!num || ScsiPortReadPortUlong((PULONG)(adaptExt->device_base + VIRTIO_PCI_QUEUE_PFN))) + pfns = ScsiPortReadPortUlong((PULONG)(adaptExt->device_base + VIRTIO_PCI_QUEUE_PFN)); + if (!num || pfns) { + RhelDbgPrint(TRACE_LEVEL_FATAL, ("%s>>> num = 0x%x, pfns= 0x%x \n", __FUNCTION__, num, pfns) ); return NULL; - + } // allocate and fill out our structure the represents an active queue info = &adaptExt->pci_vq_info; @@ -156,6 +157,7 @@ VirtIODeviceFindVirtualQueue( if (!vq) { ScsiPortWritePortUlong((PULONG)(adaptExt->device_base + VIRTIO_PCI_QUEUE_PFN),(ULONG)0); + RhelDbgPrint(TRACE_LEVEL_FATAL, ("%s>>> vring_new_virtqueue failed\n", __FUNCTION__) ); return NULL; } diff --git a/viostor/virtio_ring.c b/viostor/virtio_ring.c index cedb4f5..1f1cca3 100644 --- a/viostor/virtio_ring.c +++ b/viostor/virtio_ring.c @@ -42,7 +42,7 @@ initialize_virtqueue( //#define to_vvq(_vq) container_of(_vq, struct vring_virtqueue, vq) #define to_vvq(_vq) (struct vring_virtqueue *)_vq -#if (NTDDI_VERSION >= NTDDI_VISTA) +#if (INDIRECT_SUPPORTED) /* Set up an indirect table of descriptors and add it to the queue. */ static int @@ -110,7 +110,7 @@ vring_add_buf( { struct vring_virtqueue *vq = to_vvq(_vq); unsigned int i, avail, head, prev; -#if (NTDDI_VERSION >= NTDDI_VISTA) +#if (INDIRECT_SUPPORTED) PSCSI_REQUEST_BLOCK Srb; PRHEL_SRB_EXTENSION srbExt; PADAPTER_EXTENSION adaptExt; @@ -121,7 +121,7 @@ vring_add_buf( RhelDbgPrint(TRACE_LEVEL_ERROR, ("%s: data is NULL!\n", __FUNCTION__) ); return -1; } -#if (NTDDI_VERSION >= NTDDI_VISTA) +#if (INDIRECT_SUPPORTED) adaptExt = (PADAPTER_EXTENSION)vq->vq.DeviceExtension; vbr = (pblk_req) data; Srb = (PSCSI_REQUEST_BLOCK)vbr->req; @@ -177,7 +177,7 @@ vring_add_buf( /* Update free pointer */ vq->free_head = i; -#if (NTDDI_VERSION >= NTDDI_VISTA) +#if (INDIRECT_SUPPORTED) add_head: #endif /* Set token. */ @@ -193,7 +193,7 @@ add_head: RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s: Added buffer head %i to %p \n", __FUNCTION__, head, vq) ); -#if (NTDDI_VERSION >= NTDDI_VISTA) +#if (INDIRECT_SUPPORTED) if (adaptExt->indirect) return vq->num_free ? vq->vring.num : 0; #endif @@ -253,7 +253,7 @@ detach_buf( { unsigned int i; PVOID addr; -#if (NTDDI_VERSION >= NTDDI_VISTA) +#if (INDIRECT_SUPPORTED) STOR_PHYSICAL_ADDRESS pa; #endif @@ -262,7 +262,7 @@ detach_buf( /* Put back on free list: find end */ i = head; -#if (NTDDI_VERSION >= NTDDI_VISTA) +#if (INDIRECT_SUPPORTED) if (vq->vring.desc[i].flags & VRING_DESC_F_INDIRECT) { pa.QuadPart = vq->vring.desc[i].addr; addr = StorPortGetVirtualAddress(vq->vq.DeviceExtension, pa); diff --git a/viostor/virtio_stor.c b/viostor/virtio_stor.c index 9980a2f..52e023b 100644 --- a/viostor/virtio_stor.c +++ b/viostor/virtio_stor.c @@ -69,11 +69,6 @@ VirtIoResetBus( IN ULONG PathId ); -BOOLEAN -VirtIoInterrupt( - IN PVOID DeviceExtension - ); - SCSI_ADAPTER_CONTROL_STATUS VirtIoAdapterControl( IN PVOID DeviceExtension, @@ -129,6 +124,7 @@ DriverEntry( UCHAR devId[4] = {'1', '0', '0', '1'}; #endif + RhelDbgPrint(TRACE_LEVEL_ERROR, ("Viostor driver started...built on %s %s\n", __DATE__, __TIME__)); IsCrashDumpMode = FALSE; if (RegistryPath == NULL) { RhelDbgPrint(TRACE_LEVEL_INFORMATION, @@ -207,8 +203,6 @@ VirtIoFindAdapter( UNREFERENCED_PARAMETER( ArgumentString ); UNREFERENCED_PARAMETER( Again ); - RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s (%d)\n", __FUNCTION__, KeGetCurrentIrql())); - adaptExt = (PADAPTER_EXTENSION)DeviceExtension; adaptExt->dump_mode = IsCrashDumpMode; @@ -308,6 +302,7 @@ VirtIoFindAdapter( adaptExt->features = ScsiPortReadPortUlong((PULONG)(adaptExt->device_base + VIRTIO_PCI_HOST_FEATURES)); ConfigInfo->CachesData = CHECKBIT(adaptExt->features, VIRTIO_BLK_F_WCACHE) ? TRUE : FALSE; + RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_BLK_F_WCACHE = %d \n", ConfigInfo->CachesData)); pageNum = ScsiPortReadPortUshort((PUSHORT)(adaptExt->device_base + VIRTIO_PCI_QUEUE_NUM)); vr_sz = vring_size(pageNum,PAGE_SIZE); @@ -322,7 +317,7 @@ VirtIoFindAdapter( ConfigInfo->MaximumTransferLength = 0x00FFFFFF; adaptExt->queue_depth = pageNum / ConfigInfo->NumberOfPhysicalBreaks - 1; -#if (NTDDI_VERSION >= NTDDI_VISTA) +#if (INDIRECT_SUPPORTED) if(!adaptExt->dump_mode) { adaptExt->indirect = CHECKBIT(adaptExt->features, VIRTIO_RING_F_INDIRECT_DESC); } @@ -407,7 +402,6 @@ VirtIoHwInitialize( } if(!adaptExt->dump_mode && (adaptExt->msix_vectors > 1)) { - RhelDbgPrint(TRACE_LEVEL_ERROR, ("xru dump_mode = %x\n", adaptExt->dump_mode)); adaptExt->pci_vq_info.vq = VirtIODeviceFindVirtualQueue(DeviceExtension, 0, adaptExt->msix_vectors - 1); } #endif @@ -502,6 +496,7 @@ VirtIoHwInitialize( adaptExt->inquiry_data.CommandQueue = 1; adaptExt->inquiry_data.DeviceType = DIRECT_ACCESS_DEVICE; adaptExt->inquiry_data.Wide32Bit = 1; + adaptExt->inquiry_data.AdditionalLength = 91; ScsiPortMoveMemory(&adaptExt->inquiry_data.VendorId, "Red Hat ", sizeof("Red Hat ")); ScsiPortMoveMemory(&adaptExt->inquiry_data.ProductId, "VirtIO", sizeof("VirtIO")); ScsiPortMoveMemory(&adaptExt->inquiry_data.ProductRevisionLevel, "0001", sizeof("0001")); @@ -541,18 +536,11 @@ VirtIoStartIo( CompleteSRB(DeviceExtension, Srb); return TRUE; } - case SRB_FUNCTION_SHUTDOWN: - case SRB_FUNCTION_FLUSH: { - if(CHECKBIT(adaptExt->features, VIRTIO_BLK_F_WCACHE)) { - Srb->SrbStatus = SRB_STATUS_PENDING; - if(!RhelDoFlush(DeviceExtension, Srb)) { - Srb->SrbStatus = SRB_STATUS_BUSY; - CompleteSRB(DeviceExtension, Srb); - } - } else { - Srb->SrbStatus = SRB_STATUS_SUCCESS; - CompleteSRB(DeviceExtension, Srb); - } + case SRB_FUNCTION_FLUSH: + case SRB_FUNCTION_SHUTDOWN: { + Srb->SrbStatus = (UCHAR)RhelDoFlush(DeviceExtension, Srb); + Srb->ScsiStatus = SCSISTAT_GOOD; + CompleteSRB(DeviceExtension, Srb); return TRUE; } @@ -642,13 +630,19 @@ VirtIoStartIo( case SCSIOP_RELEASE_UNIT10: case SCSIOP_VERIFY: case SCSIOP_VERIFY16: - case SCSIOP_SYNCHRONIZE_CACHE: case SCSIOP_MEDIUM_REMOVAL: { Srb->SrbStatus = SRB_STATUS_SUCCESS; Srb->ScsiStatus = SCSISTAT_GOOD; CompleteSRB(DeviceExtension, Srb); return TRUE; } + case SCSIOP_SYNCHRONIZE_CACHE: + case SCSIOP_SYNCHRONIZE_CACHE16: { + Srb->SrbStatus = (UCHAR)RhelDoFlush(DeviceExtension, Srb); + Srb->ScsiStatus = SCSISTAT_GOOD; + CompleteSRB(DeviceExtension, Srb); + return TRUE; + } default: { break; } @@ -695,9 +689,16 @@ VirtIoInterrupt( break; default: Srb->SrbStatus = SRB_STATUS_ERROR; + RhelDbgPrint(TRACE_LEVEL_ERROR, ("SRB_STATUS_ERROR \n")); break; } - CompleteDPC(DeviceExtension, vbr, 0); + if (vbr->out_hdr.type == VIRTIO_BLK_T_FLUSH) { + adaptExt->flush_done = TRUE; + } + else + { + CompleteDPC(DeviceExtension, vbr, 0); + } } } RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s isInterruptServiced = %d\n", __FUNCTION__, isInterruptServiced)); @@ -712,8 +713,6 @@ VirtIoResetBus( { UNREFERENCED_PARAMETER( DeviceExtension ); UNREFERENCED_PARAMETER( PathId ); - - RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("<--->%s\n", __FUNCTION__)); return TRUE; } @@ -759,6 +758,7 @@ VirtIoAdapterControl( } case ScsiRestartAdapter: { RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("ScsiRestartAdapter\n")); + VirtIODeviceReset(DeviceExtension); adaptExt->pci_vq_info.vq = NULL; #ifdef MSI_SUPPORTED if(!adaptExt->dump_mode && adaptExt->msix_vectors) { @@ -1200,11 +1200,9 @@ CompleteDpcRoutine( #ifdef MSI_SUPPORTED } #endif - ScsiPortNotification(RequestComplete, Context, Srb); - #ifdef MSI_SUPPORTED if(adaptExt->msix_vectors) { StorPortAcquireMSISpinLock (Context, MessageID, &OldIrql); diff --git a/viostor/virtio_stor.h b/viostor/virtio_stor.h index 9c99b75..85cf090 100644 --- a/viostor/virtio_stor.h +++ b/viostor/virtio_stor.h @@ -109,10 +109,11 @@ typedef struct _ADAPTER_EXTENSION { LIST_ENTRY list_head; ULONG msix_vectors; ULONG features; + BOOLEAN flush_done; #ifdef USE_STORPORT LIST_ENTRY complete_list; STOR_DPC completion_dpc; -#if (NTDDI_VERSION >= NTDDI_VISTA) +#if (INDIRECT_SUPPORTED) BOOLEAN indirect; #endif #endif @@ -125,9 +126,16 @@ typedef struct _RHEL_SRB_EXTENSION { #ifndef USE_STORPORT BOOLEAN call_next; #endif -#if (NTDDI_VERSION >= NTDDI_VISTA) +#if (INDIRECT_SUPPORTED) PVOID addr; #endif }RHEL_SRB_EXTENSION, *PRHEL_SRB_EXTENSION; +BOOLEAN +VirtIoInterrupt( + IN PVOID DeviceExtension + ); + + + #endif ___VIOSTOR__H__ diff --git a/viostor/virtio_stor_hw_helper.c b/viostor/virtio_stor_hw_helper.c index 8060fa8..9cf6ded 100644 --- a/viostor/virtio_stor_hw_helper.c +++ b/viostor/virtio_stor_hw_helper.c @@ -25,64 +25,108 @@ SynchronizedFlushRoutine( PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; PSCSI_REQUEST_BLOCK Srb = (PSCSI_REQUEST_BLOCK) Context; PRHEL_SRB_EXTENSION srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; + ULONG fragLen; + srbExt->vbr.out_hdr.sector = 0; srbExt->vbr.out_hdr.ioprio = 0; - srbExt->vbr.req = (struct request *)Srb; - srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_FLUSH; - srbExt->out = 1; - srbExt->in = 1; + srbExt->vbr.req = (struct request *)Srb; + srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_FLUSH; + srbExt->out = 1; + srbExt->in = 1; + + srbExt->vbr.sg[0].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.out_hdr, &fragLen); + srbExt->vbr.sg[0].ulSize = sizeof(srbExt->vbr.out_hdr); + srbExt->vbr.sg[1].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.status, &fragLen); + srbExt->vbr.sg[1].ulSize = sizeof(srbExt->vbr.status); if (adaptExt->pci_vq_info.vq->vq_ops->add_buf(adaptExt->pci_vq_info.vq, &srbExt->vbr.sg[0], srbExt->out, srbExt->in, - &srbExt->vbr) >= 0){ - InsertTailList(&adaptExt->list_head, &srbExt->vbr.list_entry); + &srbExt->vbr) >= 0) { adaptExt->pci_vq_info.vq->vq_ops->kick(adaptExt->pci_vq_info.vq); return TRUE; } - - RhelDbgPrint(TRACE_LEVEL_ERROR, ("%s StorPortBusy\n", __FUNCTION__)); - StorPortBusy(DeviceExtension, 2); return FALSE; } -BOOLEAN -RhelDoFlush(PVOID DeviceExtension, - PSCSI_REQUEST_BLOCK Srb) +ULONG +RhelDoFlush( + PVOID DeviceExtension, + PSCSI_REQUEST_BLOCK Srb + ) { - return StorPortSynchronizeAccess(DeviceExtension, SynchronizedFlushRoutine, (PVOID)Srb); + PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; + ULONG i; + ULONG Wait = 100000; + + ASSERT(adaptExt->flush_done != TRUE); + if(StorPortSynchronizeAccess(DeviceExtension, SynchronizedFlushRoutine, (PVOID)Srb)) { + for (i = 0; i < Wait; i++) { + StorPortStallExecution(1000); + if (adaptExt->flush_done == TRUE) { + adaptExt->flush_done = FALSE; + return Srb->SrbStatus; + } + } + } + return SRB_STATUS_ERROR; } #else -BOOLEAN -RhelDoFlush(PVOID DeviceExtension, - PSCSI_REQUEST_BLOCK Srb) +ULONG +RhelDoFlush( + PVOID DeviceExtension, + PSCSI_REQUEST_BLOCK Srb + ) { PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; PRHEL_SRB_EXTENSION srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; + ULONG fragLen; int num_free; + ULONG i; + ULONG Wait = 100000; + ULONG status = SRB_STATUS_ERROR; + srbExt->vbr.out_hdr.sector = 0; srbExt->vbr.out_hdr.ioprio = 0; - srbExt->vbr.req = (struct request *)Srb; - srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_FLUSH; - srbExt->out = 1; - srbExt->in = 1; + srbExt->vbr.req = (struct request *)Srb; + srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_FLUSH; + srbExt->out = 1; + srbExt->in = 1; + + srbExt->vbr.sg[0].physAddr = ScsiPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.out_hdr, &fragLen); + srbExt->vbr.sg[0].ulSize = sizeof(srbExt->vbr.out_hdr); + srbExt->vbr.sg[1].physAddr = ScsiPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.status, &fragLen); + srbExt->vbr.sg[1].ulSize = sizeof(srbExt->vbr.status); num_free = adaptExt->pci_vq_info.vq->vq_ops->add_buf(adaptExt->pci_vq_info.vq, &srbExt->vbr.sg[0], srbExt->out, srbExt->in, &srbExt->vbr); - if ( num_free >= 0) { - InsertTailList(&adaptExt->list_head, &srbExt->vbr.list_entry); adaptExt->pci_vq_info.vq->vq_ops->kick(adaptExt->pci_vq_info.vq); - srbExt->call_next = FALSE; - if(num_free < VIRTIO_MAX_SG) { - srbExt->call_next = TRUE; - } else { - ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); + for (i = 0; i < Wait; i++) { + if (adaptExt->flush_done == TRUE) { + adaptExt->flush_done = FALSE; + status = Srb->SrbStatus; + break; + } + ScsiPortStallExecution(1000); + VirtIoInterrupt(DeviceExtension); } } - return TRUE; + if (status != SRB_STATUS_SUCCESS) { + RhelDbgPrint(TRACE_LEVEL_ERROR, ("%s 0x%x\n", __FUNCTION__, status) ); + ScsiPortLogError(DeviceExtension, + NULL, + 0, + 0, + 0, + SP_INTERNAL_ADAPTER_ERROR, + __LINE__); + status = SRB_STATUS_SUCCESS; + } + ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); + return status; } #endif @@ -105,7 +149,6 @@ SynchronizedReadWriteRoutine( return TRUE; } - RhelDbgPrint(TRACE_LEVEL_ERROR, ("%s StorPortBusy\n", __FUNCTION__)); StorPortBusy(DeviceExtension, 5); return FALSE; } @@ -116,13 +159,13 @@ RhelDoReadWrite(PVOID DeviceExtension, { BOOLEAN res = FALSE; PRHEL_SRB_EXTENSION srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; -#if (NTDDI_VERSION >= NTDDI_VISTA) +#if (INDIRECT_SUPPORTED) NTSTATUS status = STATUS_SUCCESS; struct vring_desc *desc = NULL; srbExt->addr = NULL; #endif res = StorPortSynchronizeAccess(DeviceExtension, SynchronizedReadWriteRoutine, (PVOID)Srb); -#if (NTDDI_VERSION >= NTDDI_VISTA) +#if (INDIRECT_SUPPORTED) if (!res) { status = StorPortAllocatePool(DeviceExtension, diff --git a/viostor/virtio_stor_hw_helper.h b/viostor/virtio_stor_hw_helper.h index 13c1938..3fee3c2 100644 --- a/viostor/virtio_stor_hw_helper.h +++ b/viostor/virtio_stor_hw_helper.h @@ -35,7 +35,7 @@ RhelDoReadWrite( PSCSI_REQUEST_BLOCK Srb ); -BOOLEAN +ULONG RhelDoFlush( IN PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb diff --git a/viostor/virtio_stor_utils.c b/viostor/virtio_stor_utils.c index db025af..6dda5b4 100644 --- a/viostor/virtio_stor_utils.c +++ b/viostor/virtio_stor_utils.c @@ -14,7 +14,7 @@ ULONG _cdecl RhelDbgPrintToComPort( - __in LPTSTR Format, + IN LPTSTR Format, ... ) { diff --git a/viostor/virtio_stor_utils.h b/viostor/virtio_stor_utils.h index c490341..dbfa7bc 100644 --- a/viostor/virtio_stor_utils.h +++ b/viostor/virtio_stor_utils.h @@ -62,7 +62,7 @@ extern ULONG RhelDbgLevel; ULONG _cdecl RhelDbgPrintToComPort( - __in LPTSTR Format, + IN LPTSTR Format, ... ); -- To unsubscribe from this list: send the line "unsubscribe kvm-commits" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html