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

Reply via email to