Skip to content

Commit

Permalink
[vioscsi] New ProcessQueue() routine
Browse files Browse the repository at this point in the history
Elminates VioScsiMSInterruptWorker() by refactoring contents into
new ProcessQueue() routine. This consolidates the child processes of:
HW_INTERRUPT
HW_MESSAGE_SIGNALLED_INTERRUPT_ROUTINE

Implemented using new tracing functionality, including use of new
ENTER_INL_FN and EXIT_INL_FN functions when FORCEINLINE is used.

Implemented new VIRTIO_SCSI_MSI_CONTROL_Q_OFFSET definition, and
updated QUEUE_TO_MESSAGE() and MESSAGE_TO_QUEUE() to use it.

DispatchQueue() now returns a BOOLEAN and uses new tracing
functionality, as above.

Signed-off-by: benyamin-codez <[email protected]>
  • Loading branch information
benyamin-codez committed Dec 6, 2024
1 parent 13de4f0 commit c4ac94b
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 153 deletions.
8 changes: 8 additions & 0 deletions vioscsi/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,14 @@ VioScsiCompleteDpcRoutine(
IN PVOID SystemArgument2
);

BOOLEAN
FORCEINLINE
ProcessQueue(
IN PVOID DeviceExtension,
IN ULONG MessageId,
IN PVOID InlineFuncName
);

VOID
ProcessBuffer(
IN PVOID DeviceExtension,
Expand Down
301 changes: 150 additions & 151 deletions vioscsi/vioscsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,12 @@ PostProcessRequest(
IN PSRB_TYPE Srb
);

VOID
BOOLEAN
FORCEINLINE
DispatchQueue(
IN PVOID DeviceExtension,
IN ULONG MessageId
IN ULONG MessageId,
IN PVOID InlineFuncName
);

BOOLEAN
Expand Down Expand Up @@ -996,13 +997,7 @@ VioScsiInterrupt(
IN PVOID DeviceExtension
)
{
PVirtIOSCSICmd cmd = NULL;
PVirtIOSCSIEventNode evtNode = NULL;
unsigned int len = 0;
PADAPTER_EXTENSION adaptExt = NULL;
BOOLEAN isInterruptServiced = FALSE;
PSRB_TYPE Srb = NULL;
ULONG intReason = 0;

adaptExt = (PADAPTER_EXTENSION)DeviceExtension;

Expand All @@ -1011,147 +1006,22 @@ VioScsiInterrupt(
return FALSE;
}

#if !defined(RUN_UNCHECKED)
//NOTE : SDV banned function
//RhelDbgPrint(TRACE_LEVEL_VERBOSE, " IRQL (%d)\n", KeGetCurrentIrql());
#endif

intReason = virtio_read_isr_status(&adaptExt->vdev);

if (intReason == 1 || adaptExt->dump_mode) {
isInterruptServiced = TRUE;

if (adaptExt->tmf_infly) {
while((cmd = (PVirtIOSCSICmd)virtqueue_get_buf(adaptExt->vq[VIRTIO_SCSI_CONTROL_QUEUE], &len)) != NULL) {
VirtIOSCSICtrlTMFResp *resp;
Srb = (PSRB_TYPE)cmd->srb;
ASSERT(Srb == (PSRB_TYPE)&adaptExt->tmf_cmd.Srb);
resp = &cmd->resp.tmf;
switch(resp->response) {
case VIRTIO_SCSI_S_OK:
case VIRTIO_SCSI_S_FUNCTION_SUCCEEDED:
break;
default:
RhelDbgPrint(TRACE_LEVEL_ERROR, " unknown response %d\n", resp->response);
ASSERT(0);
break;
}
StorPortResume(DeviceExtension);
}
adaptExt->tmf_infly = FALSE;
}
while((evtNode = (PVirtIOSCSIEventNode)virtqueue_get_buf(adaptExt->vq[VIRTIO_SCSI_EVENTS_QUEUE], &len)) != NULL) {
PVirtIOSCSIEvent evt = &evtNode->event;
switch (evt->event) {
case VIRTIO_SCSI_T_NO_EVENT:
break;
case VIRTIO_SCSI_T_TRANSPORT_RESET:
TransportReset(DeviceExtension, evt);
break;
case VIRTIO_SCSI_T_PARAM_CHANGE:
ParamChange(DeviceExtension, evt);
break;
default:
RhelDbgPrint(TRACE_LEVEL_ERROR, " Unsupport virtio scsi event %x\n", evt->event);
break;
}
SynchronizedKickEventRoutine(DeviceExtension, evtNode);
}

if (!adaptExt->dump_mode && adaptExt->dpc_ok)
{
StorPortIssueDpc(DeviceExtension,
&adaptExt->dpc[0],
ULongToPtr(QUEUE_TO_MESSAGE(VIRTIO_SCSI_REQUEST_QUEUE_0)),
ULongToPtr(QUEUE_TO_MESSAGE(VIRTIO_SCSI_REQUEST_QUEUE_0)));
}
else
{
ProcessBuffer(DeviceExtension, QUEUE_TO_MESSAGE(VIRTIO_SCSI_REQUEST_QUEUE_0), InterruptLock);
}
}

RhelDbgPrint(TRACE_LEVEL_VERBOSE, " isInterruptServiced = %d\n", isInterruptServiced);
return isInterruptServiced;
}

static BOOLEAN
VioScsiMSInterruptWorker(
IN PVOID DeviceExtension,
IN ULONG MessageID
)
{
PVirtIOSCSICmd cmd;
PVirtIOSCSIEventNode evtNode;
unsigned int len;
PADAPTER_EXTENSION adaptExt;
PSRB_TYPE Srb = NULL;
ULONG intReason = 0;

adaptExt = (PADAPTER_EXTENSION)DeviceExtension;

RhelDbgPrint(TRACE_LEVEL_VERBOSE,
" MessageID 0x%x\n", MessageID);

if (MessageID >= QUEUE_TO_MESSAGE(VIRTIO_SCSI_REQUEST_QUEUE_0))
{
DispatchQueue(DeviceExtension, MessageID);
return TRUE;
}
if (MessageID == 0)
{
return TRUE;
}
if (MessageID == QUEUE_TO_MESSAGE(VIRTIO_SCSI_CONTROL_QUEUE))
{
if (adaptExt->tmf_infly)
{
while((cmd = (PVirtIOSCSICmd)virtqueue_get_buf(adaptExt->vq[VIRTIO_SCSI_CONTROL_QUEUE], &len)) != NULL)
{
VirtIOSCSICtrlTMFResp *resp;
Srb = (PSRB_TYPE)(cmd->srb);
ASSERT(Srb == (PSRB_TYPE)&adaptExt->tmf_cmd.Srb);
resp = &cmd->resp.tmf;
switch(resp->response) {
case VIRTIO_SCSI_S_OK:
case VIRTIO_SCSI_S_FUNCTION_SUCCEEDED:
break;
default:
RhelDbgPrint(TRACE_LEVEL_ERROR, " Unknown response %d\n", resp->response);
ASSERT(0);
break;
}
StorPortResume(DeviceExtension);
}
adaptExt->tmf_infly = FALSE;
}
return TRUE;
}
if (MessageID == QUEUE_TO_MESSAGE(VIRTIO_SCSI_EVENTS_QUEUE)) {
while((evtNode = (PVirtIOSCSIEventNode)virtqueue_get_buf(adaptExt->vq[VIRTIO_SCSI_EVENTS_QUEUE], &len)) != NULL) {
PVirtIOSCSIEvent evt = &evtNode->event;
switch (evt->event) {
case VIRTIO_SCSI_T_NO_EVENT:
break;
case VIRTIO_SCSI_T_TRANSPORT_RESET:
TransportReset(DeviceExtension, evt);
break;
case VIRTIO_SCSI_T_PARAM_CHANGE:
ParamChange(DeviceExtension, evt);
break;
default:
RhelDbgPrint(TRACE_LEVEL_ERROR, " Unsupport virtio scsi event %x\n", evt->event);
break;
}
SynchronizedKickEventRoutine(DeviceExtension, evtNode);
}
return TRUE;
if ((virtio_read_isr_status(&adaptExt->vdev) == 1) || adaptExt->dump_mode) {
return ProcessQueue(DeviceExtension, VIRTIO_SCSI_REQUEST_QUEUE_0 + VIRTIO_SCSI_MSI_CONTROL_Q_OFFSET, "ProcessQueue");
} else {
return FALSE;
}
return FALSE;
}

BOOLEAN
VioScsiMSInterrupt(
IN PVOID DeviceExtension,
IN ULONG MessageID
IN ULONG MessageId
)
{
PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension;
Expand All @@ -1165,13 +1035,13 @@ VioScsiMSInterrupt(

if (!adaptExt->msix_one_vector) {
/* Each queue has its own vector, this is the fast and common case */
return VioScsiMSInterruptWorker(DeviceExtension, MessageID);
return ProcessQueue(DeviceExtension, MessageId, "ProcessQueue");
}

/* Fall back to checking all queues */
for (i = 0; i < adaptExt->num_queues + VIRTIO_SCSI_REQUEST_QUEUE_0; i++) {
if (virtqueue_has_buf(adaptExt->vq[i])) {
isInterruptServiced |= VioScsiMSInterruptWorker(DeviceExtension, i + 1);
isInterruptServiced |= ProcessQueue(DeviceExtension, i + VIRTIO_SCSI_MSI_CONTROL_Q_OFFSET, "ProcessQueue");
}
}
return isInterruptServiced;
Expand Down Expand Up @@ -1458,29 +1328,158 @@ EXIT_FN_SRB();
}


VOID
BOOLEAN
FORCEINLINE
ProcessQueue(
IN PVOID DeviceExtension,
IN ULONG MessageId,
IN PVOID InlineFuncName
)
{
#if !defined(RUN_UNCHECKED)
ENTER_INL_FN();
#endif

PVirtIOSCSICmd cmd;
PVirtIOSCSIEventNode evtNode;
unsigned int len;
PADAPTER_EXTENSION adaptExt;
PSRB_TYPE Srb = NULL;

adaptExt = (PADAPTER_EXTENSION)DeviceExtension;

#if !defined(RUN_UNCHECKED)
RhelDbgPrint(TRACE_LEVEL_VERBOSE, " Processing VirtIO Queue : %lu \n", MESSAGE_TO_QUEUE(MessageId));
#endif

if (MessageId >= QUEUE_TO_MESSAGE(VIRTIO_SCSI_REQUEST_QUEUE_0))
{
#if !defined(RUN_UNCHECKED)
RhelDbgPrint(TRACE_LEVEL_VERBOSE, " Dispatching to Request Queue...\n");
#endif
BOOLEAN dispatch_q_status = DispatchQueue(DeviceExtension, MessageId, "DispatchQueue");
#if !defined(RUN_UNCHECKED)
EXIT_INL_FN();
#endif
return dispatch_q_status;
}
if ((MessageId == 0) && (VIRTIO_SCSI_MSI_CONTROL_Q_OFFSET != 0))
{
#if !defined(RUN_UNCHECKED)
RhelDbgPrint(TRACE_LEVEL_VERBOSE, " MSI-X Vector 0 [MessageId = 0] is unused by HBA. Returning without further processing.\n");
#endif
#if !defined(RUN_UNCHECKED)
EXIT_INL_FN();
#endif
return TRUE;
}
if (MessageId == QUEUE_TO_MESSAGE(VIRTIO_SCSI_CONTROL_QUEUE))
{
#if !defined(RUN_UNCHECKED)
RhelDbgPrint(TRACE_LEVEL_VERBOSE, " Processing Control Queue...\n");
#endif
if (adaptExt->tmf_infly)
{
while((cmd = (PVirtIOSCSICmd)virtqueue_get_buf(adaptExt->vq[VIRTIO_SCSI_CONTROL_QUEUE], &len)) != NULL)
{
VirtIOSCSICtrlTMFResp *resp;
Srb = (PSRB_TYPE)(cmd->srb);
ASSERT(Srb == (PSRB_TYPE)&adaptExt->tmf_cmd.Srb);
resp = &cmd->resp.tmf;
switch(resp->response) {
case VIRTIO_SCSI_S_OK:
case VIRTIO_SCSI_S_FUNCTION_SUCCEEDED:
break;
default:
#if !defined(RUN_UNCHECKED) || defined(RUN_MIN_CHECKED)
RhelDbgPrint(TRACE_LEVEL_ERROR, " Unknown ERROR response %d\n", resp->response);
#endif
ASSERT(0);
break;
}
StorPortResume(DeviceExtension);
}
adaptExt->tmf_infly = FALSE;
}
#if !defined(RUN_UNCHECKED)
EXIT_INL_FN();
#endif
return TRUE;
}
if (MessageId == QUEUE_TO_MESSAGE(VIRTIO_SCSI_EVENTS_QUEUE)) {
#if !defined(RUN_UNCHECKED)
RhelDbgPrint(TRACE_LEVEL_VERBOSE, " Processing Events Queue...\n");
#endif
while((evtNode = (PVirtIOSCSIEventNode)virtqueue_get_buf(adaptExt->vq[VIRTIO_SCSI_EVENTS_QUEUE], &len)) != NULL) {
PVirtIOSCSIEvent evt = &evtNode->event;
switch (evt->event) {
case VIRTIO_SCSI_T_NO_EVENT:
break;
case VIRTIO_SCSI_T_TRANSPORT_RESET:
TransportReset(DeviceExtension, evt);
break;
case VIRTIO_SCSI_T_PARAM_CHANGE:
ParamChange(DeviceExtension, evt);
break;
default:
#if !defined(RUN_UNCHECKED) || defined(RUN_MIN_CHECKED)
RhelDbgPrint(TRACE_LEVEL_ERROR, " Unsupport virtio scsi event %x\n", evt->event);
#endif
break;
}
SynchronizedKickEventRoutine(DeviceExtension, evtNode);
}
#if !defined(RUN_UNCHECKED)
EXIT_INL_FN();
#endif
return TRUE;
}
#if !defined(RUN_UNCHECKED)
EXIT_INL_FN();
#endif
return FALSE;
}

BOOLEAN
FORCEINLINE
DispatchQueue(
IN PVOID DeviceExtension,
IN ULONG MessageId
IN ULONG MessageId,
IN PVOID InlineFuncName
)
{
#if !defined(RUN_UNCHECKED)
ENTER_INL_FN();
#endif

PADAPTER_EXTENSION adaptExt;
ENTER_FN();

adaptExt = (PADAPTER_EXTENSION)DeviceExtension;

if (!adaptExt->dump_mode && adaptExt->dpc_ok) {
NT_ASSERT(MessageId >= QUEUE_TO_MESSAGE(VIRTIO_SCSI_REQUEST_QUEUE_0));
StorPortIssueDpc(DeviceExtension,
if (StorPortIssueDpc(DeviceExtension,
&adaptExt->dpc[MessageId - QUEUE_TO_MESSAGE(VIRTIO_SCSI_REQUEST_QUEUE_0)],
ULongToPtr(MessageId),
ULongToPtr(MessageId));
EXIT_FN();
return;
ULongToPtr(MessageId))) {
#if !defined(RUN_UNCHECKED)
RhelDbgPrint(TRACE_DPC, " The request to queue a DPC was successful.\n");
EXIT_INL_FN();
#endif
return TRUE;
} else {
#if !defined(RUN_UNCHECKED)
RhelDbgPrint(TRACE_DPC, " The request to queue a DPC was NOT successful. It may already be queued elsewhere.\n");
EXIT_INL_FN();
#endif
return FALSE;
}
}
ProcessBuffer(DeviceExtension, MessageId, InterruptLock);
EXIT_FN();
#if !defined(RUN_UNCHECKED)
EXIT_INL_FN();
#endif
return TRUE;
}

VOID
Expand Down
5 changes: 3 additions & 2 deletions vioscsi/vioscsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,9 @@ typedef struct VirtIOBufferDescriptor VIO_SG, *PVIO_SG;
#define VIRTIO_SCSI_QUEUE_LAST VIRTIO_SCSI_REQUEST_QUEUE_0 + MAX_CPU

/* MSI messages and virtqueue indices are offset by 1, MSI 0 is not used */
#define QUEUE_TO_MESSAGE(QueueId) ((QueueId) + 1)
#define MESSAGE_TO_QUEUE(MessageId) ((MessageId) - 1)
#define VIRTIO_SCSI_MSI_CONTROL_Q_OFFSET 1
#define QUEUE_TO_MESSAGE(QueueId) ((QueueId) + VIRTIO_SCSI_MSI_CONTROL_Q_OFFSET)
#define MESSAGE_TO_QUEUE(MessageId) ((MessageId) - VIRTIO_SCSI_MSI_CONTROL_Q_OFFSET)

/* SCSI command request, followed by data-out */
#pragma pack(1)
Expand Down

0 comments on commit c4ac94b

Please sign in to comment.