repository: C:/dev/kvm-guest-drivers-windows
branch: master
commit 597c5be5ab7fd44aa4e127c5cec028964588e9a7
Author: Yan Vugenfirer <[email protected]>
Date: Sun Oct 25 16:06:30 2009 +0200
[WIN-GUEST-DRIVERS] Add MSI-X support for viostor driver
Signed-off-by: Vadim Rozenfeld<[email protected]>
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html