Commit 62fc2661 authored by Tyrel Datwyler's avatar Tyrel Datwyler Committed by Martin K. Petersen

scsi: ibmvfc: Make ibmvfc_wait_for_ops() MQ aware

During MQ enablement of the ibmvfc driver ibmvfc_wait_for_ops() was
missed. This function is responsible for waiting on commands to complete
that match a certain criteria such as LUN or cancel key. The implementation
as is only scans the CRQ for events ignoring any sub-queues and as a result
will exit successfully without doing anything when operating in MQ
channelized mode.

Check the MQ and channel use flags to determine which queues are
applicable, and scan each queue accordingly. Note in MQ mode SCSI commands
are only issued down sub-queues and the CRQ is only used for driver
specific management commands. As such the CRQ events are ignored when
operating in MQ mode with channels.

Link: https://lore.kernel.org/r/20210319205029.312969-3-tyreld@linux.ibm.com
Fixes: 9000cb99 ("scsi: ibmvfc: Enable MQ and set reasonable defaults")
Reviewed-by: default avatarBrian King <brking@linux.vnet.ibm.com>
Signed-off-by: default avatarTyrel Datwyler <tyreld@linux.ibm.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 8b1c9b20
...@@ -2403,41 +2403,58 @@ static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device, ...@@ -2403,41 +2403,58 @@ static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device,
{ {
struct ibmvfc_event *evt; struct ibmvfc_event *evt;
DECLARE_COMPLETION_ONSTACK(comp); DECLARE_COMPLETION_ONSTACK(comp);
int wait, i; int wait, i, q_index, q_size;
unsigned long flags; unsigned long flags;
signed long timeout = IBMVFC_ABORT_WAIT_TIMEOUT * HZ; signed long timeout = IBMVFC_ABORT_WAIT_TIMEOUT * HZ;
struct ibmvfc_queue *queues;
ENTER; ENTER;
if (vhost->mq_enabled && vhost->using_channels) {
queues = vhost->scsi_scrqs.scrqs;
q_size = vhost->scsi_scrqs.active_queues;
} else {
queues = &vhost->crq;
q_size = 1;
}
do { do {
wait = 0; wait = 0;
spin_lock_irqsave(&vhost->crq.l_lock, flags); spin_lock_irqsave(vhost->host->host_lock, flags);
for (i = 0; i < vhost->crq.evt_pool.size; i++) { for (q_index = 0; q_index < q_size; q_index++) {
evt = &vhost->crq.evt_pool.events[i]; spin_lock(&queues[q_index].l_lock);
if (!ibmvfc_event_is_free(evt)) { for (i = 0; i < queues[q_index].evt_pool.size; i++) {
if (match(evt, device)) { evt = &queues[q_index].evt_pool.events[i];
evt->eh_comp = &comp; if (!ibmvfc_event_is_free(evt)) {
wait++; if (match(evt, device)) {
evt->eh_comp = &comp;
wait++;
}
} }
} }
spin_unlock(&queues[q_index].l_lock);
} }
spin_unlock_irqrestore(&vhost->crq.l_lock, flags); spin_unlock_irqrestore(vhost->host->host_lock, flags);
if (wait) { if (wait) {
timeout = wait_for_completion_timeout(&comp, timeout); timeout = wait_for_completion_timeout(&comp, timeout);
if (!timeout) { if (!timeout) {
wait = 0; wait = 0;
spin_lock_irqsave(&vhost->crq.l_lock, flags); spin_lock_irqsave(vhost->host->host_lock, flags);
for (i = 0; i < vhost->crq.evt_pool.size; i++) { for (q_index = 0; q_index < q_size; q_index++) {
evt = &vhost->crq.evt_pool.events[i]; spin_lock(&queues[q_index].l_lock);
if (!ibmvfc_event_is_free(evt)) { for (i = 0; i < queues[q_index].evt_pool.size; i++) {
if (match(evt, device)) { evt = &queues[q_index].evt_pool.events[i];
evt->eh_comp = NULL; if (!ibmvfc_event_is_free(evt)) {
wait++; if (match(evt, device)) {
evt->eh_comp = NULL;
wait++;
}
} }
} }
spin_unlock(&queues[q_index].l_lock);
} }
spin_unlock_irqrestore(&vhost->crq.l_lock, flags); spin_unlock_irqrestore(vhost->host->host_lock, flags);
if (wait) if (wait)
dev_err(vhost->dev, "Timed out waiting for aborted commands\n"); dev_err(vhost->dev, "Timed out waiting for aborted commands\n");
LEAVE; LEAVE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment