Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[vioscsi] New ProcessQueue() routine #1214

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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");
benyamin-codez marked this conversation as resolved.
Show resolved Hide resolved
} 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)
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)
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