repository: C:/dev/kvm-guest-drivers-windows branch: master commit 597c5be5ab7fd44aa4e127c5cec028964588e9a7 Author: Yan Vugenfirer <yvuge...@redhat.com> Date: Sun Oct 25 16:06:30 2009 +0200
[WIN-GUEST-DRIVERS] Add MSI-X support for viostor driver Signed-off-by: Vadim Rozenfeld<vroze...@redhat.com> diff --git a/viostor/SOURCES b/viostor/SOURCES index 561cfc0..1352710 100644 --- a/viostor/SOURCES +++ b/viostor/SOURCES @@ -6,6 +6,7 @@ C_DEFINES = -DUSE_STORPORT=1 $(C_DEFINES) TARGETLIBS=$(SDK_LIB_PATH)\storport.lib !elseif "$(DDK_TARGET_OS)" == "WinLH" C_DEFINES = -DUSE_STORPORT=1 $(C_DEFINES) +C_DEFINES = -DMSI_SUPPORTED=1 $(C_DEFINES) TARGETLIBS=$(SDK_LIB_PATH)\storport.lib !else TARGETLIBS=$(SDK_LIB_PATH)\scsiport.lib diff --git a/viostor/virtio_pci.c b/viostor/virtio_pci.c index 6bf26cc..6023cef 100644 --- a/viostor/virtio_pci.c +++ b/viostor/virtio_pci.c @@ -86,7 +86,7 @@ VirtIODeviceGet( RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s\n", __FUNCTION__)); - ioaddr = adaptExt->device_base + VIRTIO_PCI_CONFIG + offset; + ioaddr = adaptExt->device_base + VIRTIO_PCI_CONFIG((adaptExt->msix_vectors > 0)) + offset; for (i = 0; i < len; i++) { ptr[i] = ScsiPortReadPortUchar((PUCHAR)(ioaddr + i)); @@ -125,7 +125,8 @@ struct virtqueue* VirtIODeviceFindVirtualQueue( IN PVOID DeviceExtension, - IN unsigned index) + IN unsigned index, + IN unsigned vector) { virtio_pci_vq_info *info; struct virtqueue *vq; @@ -133,9 +134,20 @@ VirtIODeviceFindVirtualQueue( ULONG dummy; PHYSICAL_ADDRESS pa; ULONG pageNum; + unsigned res; PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; - RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s\n", __FUNCTION__)); + RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s index = %d, vector = %d\n", __FUNCTION__, index, vector)); + + if(vector) { + ScsiPortWritePortUshort((PUSHORT)(adaptExt->device_base + VIRTIO_MSI_CONFIG_VECTOR),(USHORT)0); + res = ScsiPortReadPortUshort((PUSHORT)(adaptExt->device_base + VIRTIO_MSI_CONFIG_VECTOR)); + RhelDbgPrint(TRACE_LEVEL_FATAL, ("%s>> VIRTIO_MSI_CONFIG_VECTOR res = 0x%x\n", __FUNCTION__, res)); + if(res == VIRTIO_MSI_NO_VECTOR) { + RhelDbgPrint(TRACE_LEVEL_FATAL, ("%s>> Cannot find config vector res = 0x%x\n", __FUNCTION__, res)); + return NULL; + } + } // Select the queue we're interested in ScsiPortWritePortUshort((PUSHORT)(adaptExt->device_base + VIRTIO_PCI_QUEUE_SEL),(USHORT)index); @@ -144,7 +156,7 @@ VirtIODeviceFindVirtualQueue( 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 || ScsiPortReadPortUshort((PUSHORT)(adaptExt->device_base + VIRTIO_PCI_QUEUE_PFN))) + if (!num || ScsiPortReadPortUlong((PULONG)(adaptExt->device_base + VIRTIO_PCI_QUEUE_PFN))) return NULL; // allocate and fill out our structure the represents an active queue @@ -174,7 +186,18 @@ VirtIODeviceFindVirtualQueue( pageNum = (ULONG)(pa.QuadPart >> PAGE_SHIFT); RhelDbgPrint(TRACE_LEVEL_FATAL, ("[%s] queue phys.address %08lx:%08lx, pfn %lx\n", __FUNCTION__, pa.u.HighPart, pa.u.LowPart, pageNum)); ScsiPortWritePortUlong((PULONG)(adaptExt->device_base + VIRTIO_PCI_QUEUE_PFN),(ULONG)(pageNum)); - + + if(vector) { + ScsiPortWritePortUshort((PUSHORT)(adaptExt->device_base + VIRTIO_MSI_QUEUE_VECTOR),(USHORT)vector); + res = ScsiPortReadPortUshort((PUSHORT)(adaptExt->device_base + VIRTIO_MSI_QUEUE_VECTOR)); + RhelDbgPrint(TRACE_LEVEL_FATAL, ("%s>> VIRTIO_MSI_QUEUE_VECTOR vector = %d, res = 0x%x\n", __FUNCTION__, vector, res)); + if(res == VIRTIO_MSI_NO_VECTOR) { + ScsiPortWritePortUlong((PULONG)(adaptExt->device_base + VIRTIO_PCI_QUEUE_PFN),(ULONG)0); + RhelDbgPrint(TRACE_LEVEL_FATAL, ("%s>> Cannot create vq vector\n", __FUNCTION__)); + return NULL; + } + } + return vq; } diff --git a/viostor/virtio_pci.h b/viostor/virtio_pci.h index fc31163..8f99e18 100644 --- a/viostor/virtio_pci.h +++ b/viostor/virtio_pci.h @@ -52,7 +52,15 @@ /* The remaining space is defined by each driver as the per-driver * configuration space */ -#define VIRTIO_PCI_CONFIG 20 +#define VIRTIO_PCI_CONFIG(msix_enabled) (msix_enabled ? 24 : 20) + +/* MSI-X registers: only enabled if MSI-X is enabled. */ +/* A 16-bit vector for configuration changes. */ +#define VIRTIO_MSI_CONFIG_VECTOR 20 +/* A 16-bit vector for selected queue notifications. */ +#define VIRTIO_MSI_QUEUE_VECTOR 22 +/* Vector value used to disable MSI for queue */ +#define VIRTIO_MSI_NO_VECTOR 0xffff typedef struct virtio_pci_vq_info { @@ -98,7 +106,8 @@ struct virtqueue* VirtIODeviceFindVirtualQueue( IN PVOID DeviceExtension, - IN unsigned index); + IN unsigned index, + IN unsigned vector); void VirtIODeviceDeleteVirtualQueue( diff --git a/viostor/virtio_stor.c b/viostor/virtio_stor.c index 5341940..8457185 100644 --- a/viostor/virtio_stor.c +++ b/viostor/virtio_stor.c @@ -38,6 +38,13 @@ CompleteDpcRoutine( IN PVOID SystemArgument1, IN PVOID SystemArgument2 ) ; +#ifdef MSI_SUPPORTED +BOOLEAN +VirtIoMSInterruptRoutine ( + IN PVOID DeviceExtension, + IN ULONG MessageID + ); +#endif #endif BOOLEAN @@ -103,7 +110,8 @@ VOID FORCEINLINE CompleteDPC( IN PVOID DeviceExtension, - IN pblk_req vbr + IN pblk_req vbr, + IN ULONG MessageID ); ULONG @@ -210,6 +218,10 @@ VirtIoFindAdapter( #ifdef USE_STORPORT ConfigInfo->MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS; ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex; +#ifdef MSI_SUPPORTED + ConfigInfo->HwMSInterruptRoutine = VirtIoMSInterruptRoutine; + ConfigInfo->InterruptSynchronizationMode=InterruptSynchronizePerMessage;//InterruptSynchronizeAll;// +#endif #else ConfigInfo->MapBuffers = TRUE; #endif @@ -325,20 +337,6 @@ VirtIoFindAdapter( adaptExt->pci_vq_info.queue = PAGE_ALIGN(ptr); adaptExt->virtqueue = (vring_virtqueue*)((ULONG_PTR)(adaptExt->pci_vq_info.queue) + vr_sz); - adaptExt->pci_vq_info.vq = VirtIODeviceFindVirtualQueue(DeviceExtension, 0); - if (!adaptExt->pci_vq_info.vq) { - ScsiPortLogError(DeviceExtension, - NULL, - 0, - 0, - 0, - SP_INTERNAL_ADAPTER_ERROR, - __LINE__); - - RhelDbgPrint(TRACE_LEVEL_FATAL, ("Cannot find snd virtual queue\n")); - return SP_RETURN_ERROR; - } - InitializeListHead(&adaptExt->list_head); InitializeListHead(&adaptExt->complete_list); @@ -372,11 +370,47 @@ VirtIoHwInitialize( u64 cap; u32 v; struct virtio_blk_geometry vgeo; +#ifdef MSI_SUPPORTED + MESSAGE_INTERRUPT_INFORMATION msi_info; +#endif RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s (%d)\n", __FUNCTION__, KeGetCurrentIrql())); adaptExt = (PADAPTER_EXTENSION)DeviceExtension; +#ifdef MSI_SUPPORTED + while(StorPortGetMSIInfo(DeviceExtension, adaptExt->msix_vectors, &msi_info) == STOR_STATUS_SUCCESS) { + RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageId = %x\n", msi_info.MessageId)); + RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageData = %x\n", msi_info.MessageData)); + RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("InterruptVector = %x\n", msi_info.InterruptVector)); + RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("InterruptLevel = %x\n", msi_info.InterruptLevel)); + RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("InterruptMode = %s\n", msi_info.InterruptMode == LevelSensitive ? "LevelSensitive" : "Latched")); + RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageAddress = %p\n\n", msi_info.MessageAddress)); + ++adaptExt->msix_vectors; + } + + 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 + + if(!adaptExt->pci_vq_info.vq) { + adaptExt->pci_vq_info.vq = VirtIODeviceFindVirtualQueue(DeviceExtension, 0, 0); + } + if (!adaptExt->pci_vq_info.vq) { + ScsiPortLogError(DeviceExtension, + NULL, + 0, + 0, + 0, + SP_INTERNAL_ADAPTER_ERROR, + __LINE__); + + RhelDbgPrint(TRACE_LEVEL_FATAL, ("Cannot find snd virtual queue\n")); + return FALSE; + } + if (VirtIODeviceGetHostFeature(DeviceExtension, VIRTIO_BLK_F_BARRIER)) { RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_BLK_F_BARRIER\n")); } @@ -612,7 +646,7 @@ VirtIoInterrupt( Srb->SrbStatus = SRB_STATUS_ERROR; break; } - CompleteDPC(DeviceExtension, vbr); + CompleteDPC(DeviceExtension, vbr, 0); } } RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s isInterruptServiced = %d\n", __FUNCTION__, isInterruptServiced)); @@ -671,8 +705,15 @@ VirtIoAdapterControl( } case ScsiRestartAdapter: { RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("ScsiRestartAdapter\n")); - - adaptExt->pci_vq_info.vq = VirtIODeviceFindVirtualQueue(DeviceExtension, 0); + adaptExt->pci_vq_info.vq = NULL; +#ifdef MSI_SUPPORTED + if(!adaptExt->dump_mode & adaptExt->msix_vectors) { + adaptExt->pci_vq_info.vq = VirtIODeviceFindVirtualQueue(DeviceExtension, 0, adaptExt->msix_vectors); + } +#endif + if(!adaptExt->pci_vq_info.vq) { + adaptExt->pci_vq_info.vq = VirtIODeviceFindVirtualQueue(DeviceExtension, 0, 0); + } if (!adaptExt->pci_vq_info.vq) { RhelDbgPrint(TRACE_LEVEL_FATAL, ("Cannot find snd virtual queue\n")); @@ -765,6 +806,45 @@ VirtIoBuildIo( return TRUE; } + +#ifdef MSI_SUPPORTED +BOOLEAN +VirtIoMSInterruptRoutine ( + IN PVOID DeviceExtension, + IN ULONG MessageID + ) +{ + pblk_req vbr; + unsigned int len; + unsigned long flags; + PADAPTER_EXTENSION adaptExt; + PSCSI_REQUEST_BLOCK Srb; + + adaptExt = (PADAPTER_EXTENSION)DeviceExtension; + + RhelDbgPrint(TRACE_LEVEL_VERBOSE, + ("<--->%s : MessageID 0x%x\n", __FUNCTION__, MessageID)); + + while((vbr = adaptExt->pci_vq_info.vq->vq_ops->get_buf(adaptExt->pci_vq_info.vq, &len)) != NULL) { + Srb = (PSCSI_REQUEST_BLOCK)vbr->req; + switch (vbr->status) { + case VIRTIO_BLK_S_OK: + Srb->SrbStatus = SRB_STATUS_SUCCESS; + break; + case VIRTIO_BLK_S_UNSUPP: + Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; + break; + default: + Srb->SrbStatus = SRB_STATUS_ERROR; + break; + } + CompleteDPC(DeviceExtension, vbr, MessageID); + } + + return TRUE; +} +#endif + #endif UCHAR @@ -1031,7 +1111,8 @@ VOID FORCEINLINE CompleteDPC( IN PVOID DeviceExtension, - IN pblk_req vbr + IN pblk_req vbr, + IN ULONG MessageID ) { PSCSI_REQUEST_BLOCK Srb = (PSCSI_REQUEST_BLOCK)vbr->req; @@ -1044,7 +1125,7 @@ CompleteDPC( InsertTailList(&adaptExt->complete_list, &vbr->list_entry); StorPortIssueDpc(DeviceExtension, &adaptExt->completion_dpc, - NULL, + (PVOID)MessageID, NULL); return; } @@ -1063,26 +1144,41 @@ CompleteDpcRoutine( { STOR_LOCK_HANDLE LockHandle; PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)Context; + ULONG MessageID = (ULONG)SystemArgument1; + ULONG OldIrql; - StorPortAcquireSpinLock ( Context, InterruptLock , NULL, &LockHandle); - + if(adaptExt->msix_vectors) { + StorPortAcquireMSISpinLock (Context, MessageID, &OldIrql); + } else { + StorPortAcquireSpinLock ( Context, InterruptLock , NULL, &LockHandle); + } while (!IsListEmpty(&adaptExt->complete_list)) { PSCSI_REQUEST_BLOCK Srb; pblk_req vbr; vbr = (pblk_req) RemoveHeadList(&adaptExt->complete_list); Srb = (PSCSI_REQUEST_BLOCK)vbr->req; - StorPortReleaseSpinLock (Context, &LockHandle); + if(adaptExt->msix_vectors) { + StorPortReleaseMSISpinLock (Context, MessageID, OldIrql); + } else { + StorPortReleaseSpinLock (Context, &LockHandle); + } ScsiPortNotification(RequestComplete, Context, Srb); - StorPortAcquireSpinLock ( Context, InterruptLock , NULL, &LockHandle); - + if(adaptExt->msix_vectors) { + StorPortAcquireMSISpinLock (Context, MessageID, &OldIrql); + } else { + StorPortAcquireSpinLock ( Context, InterruptLock , NULL, &LockHandle); + } } - StorPortReleaseSpinLock (Context, &LockHandle); - + if(adaptExt->msix_vectors) { + StorPortReleaseMSISpinLock (Context, MessageID, OldIrql); + } else { + StorPortReleaseSpinLock (Context, &LockHandle); + } return; } diff --git a/viostor/virtio_stor.h b/viostor/virtio_stor.h index dd4728e..221c653 100644 --- a/viostor/virtio_stor.h +++ b/viostor/virtio_stor.h @@ -105,6 +105,7 @@ typedef struct _ADAPTER_EXTENSION { LIST_ENTRY complete_list; STOR_DPC completion_dpc; BOOLEAN has_sn; + ULONG msix_vectors; }ADAPTER_EXTENSION, *PADAPTER_EXTENSION; typedef struct _RHEL_SRB_EXTENSION { diff --git a/viostor/virtio_stor_hw_helper.c b/viostor/virtio_stor_hw_helper.c index 766dcd9..a697b90 100644 --- a/viostor/virtio_stor_hw_helper.c +++ b/viostor/virtio_stor_hw_helper.c @@ -40,7 +40,7 @@ BOOLEAN RhelDoReadWrite(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb) { - return StorPortSynchronizeAccess(DeviceExtension,SynchronizedAccessRoutine, (PVOID)Srb); + return StorPortSynchronizeAccess(DeviceExtension, SynchronizedAccessRoutine, (PVOID)Srb); } #else BOOLEAN diff --git a/viostor/wlh.inf b/viostor/wlh.inf index aae425a..42566ac 100644 --- a/viostor/wlh.inf +++ b/viostor/wlh.inf @@ -4,7 +4,7 @@ Signature="$Windows NT$" Provider=%RHEL% ClassGUID={4D36E97B-E325-11CE-BFC1-08002BE10318} Class=SCSIAdapter -DriverVer = 05/05/2009,4.3.0.17241 +DriverVer = 10/10/2009,5.3.0.17241 CatalogFile=viostor.cat ; @@ -56,8 +56,6 @@ viostor.sys,,,2 [rhelscsi_inst] CopyFiles=viostor_Files_Driver - - ; ; Service Installation ; @@ -73,6 +71,8 @@ ServiceBinary = %12%\viostor.sys LoadOrderGroup = SCSI miniport AddReg = pnpsafe_pci_addreg +[rhelscsi_inst.HW] +AddReg = pnpsafe_pci_addreg_msix [rhelscsi_EventLog_Inst] AddReg = rhelscsi_EventLog_AddReg @@ -86,6 +86,15 @@ HKR,,TypesSupported,%REG_DWORD%,7 HKR, "Parameters\PnpInterface", "5", %REG_DWORD%, 0x00000001 HKR, "Parameters", "BusType", %REG_DWORD%, 0x00000001 +[pnpsafe_pci_addreg_msix] +HKR, "Interrupt Management",, 0x00000010 +HKR, "Interrupt Management\MessageSignaledInterruptProperties",, 0x00000010 +HKR, "Interrupt Management\MessageSignaledInterruptProperties", MSISupported, 0x00010001, 0 +HKR, "Interrupt Management\MessageSignaledInterruptProperties", MessageNumberLimit, 0x00010001, 2 +HKR, "Interrupt Management\Affinity Policy",, 0x00000010 +HKR, "Interrupt Management\Affinity Policy", DevicePolicy, 0x00010001, 5 + + [Strings] ; ; Localizable Strings diff --git a/viostor/wnet.inf b/viostor/wnet.inf index aae425a..5682aa7 100644 --- a/viostor/wnet.inf +++ b/viostor/wnet.inf @@ -4,7 +4,7 @@ Signature="$Windows NT$" Provider=%RHEL% ClassGUID={4D36E97B-E325-11CE-BFC1-08002BE10318} Class=SCSIAdapter -DriverVer = 05/05/2009,4.3.0.17241 +DriverVer = 10/10/2009,5.3.0.17241 CatalogFile=viostor.cat ; @@ -56,8 +56,6 @@ viostor.sys,,,2 [rhelscsi_inst] CopyFiles=viostor_Files_Driver - - ; ; Service Installation ; @@ -73,7 +71,6 @@ ServiceBinary = %12%\viostor.sys LoadOrderGroup = SCSI miniport AddReg = pnpsafe_pci_addreg - [rhelscsi_EventLog_Inst] AddReg = rhelscsi_EventLog_AddReg @@ -81,7 +78,6 @@ AddReg = rhelscsi_EventLog_AddReg HKR,,EventMessageFile,%REG_EXPAND_SZ%,"%%SystemRoot%%\System32\IoLogMsg.dll" HKR,,TypesSupported,%REG_DWORD%,7 - [pnpsafe_pci_addreg] HKR, "Parameters\PnpInterface", "5", %REG_DWORD%, 0x00000001 HKR, "Parameters", "BusType", %REG_DWORD%, 0x00000001 -- 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