This series contains a minor simplification of ibmvfc_init_sub_crqs() followed
by a couple fixes for sub-CRQ handling which effect hard reset of the
client/host adapter CRQ pair.
A non-zero return code for H_REG_SUB_CRQ is currently treated as a
failure resulting in failing sub-CRQ setup. The case of H_CLOSED should
not be treated as a failure. This return code translates to a successful
sub-CRQ registration by the hypervisor, and is meant to communicate back
that there is currently no partner VIOS CRQ connection established as of
yet. This is a common occurrence during a disconnect where the client
adapter can possibly come back up prior to the partner adapter.
For non-zero return code from H_REG_SUB_CRQ treat a H_CLOSED as success
so that sub-CRQs are successfully setup.
Fixes: faacf8c5f1d5 ("ibmvfc: add alloc/dealloc routines for SCSI Sub-CRQ Channels")
Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
---
drivers/scsi/ibmvscsi/ibmvfc.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
@@ -5636,7 +5636,8 @@ static int ibmvfc_register_scsi_channel(struct ibmvfc_host *vhost,rc=h_reg_sub_crq(vdev->unit_address,scrq->msg_token,PAGE_SIZE,&scrq->cookie,&scrq->hw_irq);-if(rc){+/* H_CLOSED indicates successful register, but no CRQ partner */+if(rc&&rc!=H_CLOSED){dev_warn(dev,"Error registering sub-crq: %d\n",rc);if(rc==H_PARAMETER)dev_warn_once(dev,"Firmware may not support MQ\n");
The H_FREE_SUB_CRQ hypercall can return a retry delay return code that
indicates the call needs to be retried after a specific amount of time
delay. The error path to free a sub-CRQ in case of a failure during
channel registration fails to capture the return code of H_FREE_SUB_CRQ
which will result in the delay loop being skipped in the case of a retry
delay return code.
Store the return code result of the H_FREE_SUB_CRQ call such that the
return code check in the delay loop evaluates a meaningful value.
Fixes: 9288d35d70b5 ("ibmvfc: map/request irq and register Sub-CRQ interrupt handler")
Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
---
drivers/scsi/ibmvscsi/ibmvfc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
A hard reset results in a complete transport disconnect such that the
CRQ connection with the partner VIOS is broken. This has the side effect
of also invalidating the associated sub-CRQs. The current code assumes
that the sub-CRQs are perserved resulting in a protocol violation after
trying to reconnect them with the VIOS. This introduces an infinite loop
such that the VIOS forces a disconnect after each subsequent attempt to
re-register with invalid handles.
Avoid the aforementioned issue by releasing the sub-CRQs prior to CRQ
disconnect, and driving a reinitialization of the sub-CRQs once a new
CRQ is registered with the hypervisor.
fixes: faacf8c5f1d5 ("ibmvfc: add alloc/dealloc routines for SCSI Sub-CRQ Channels")
Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
---
drivers/scsi/ibmvscsi/ibmvfc.c | 21 +++++++++------------
1 file changed, 9 insertions(+), 12 deletions(-)
@@ -926,8 +929,8 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)unsignedlongflags;structvio_dev*vdev=to_vio_dev(vhost->dev);structibmvfc_queue*crq=&vhost->crq;-structibmvfc_queue*scrq;-inti;++ibmvfc_release_sub_crqs(vhost);/* Close the CRQ */do{
@@ -947,16 +950,6 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)memset(crq->msgs.crq,0,PAGE_SIZE);crq->cur=0;-if(vhost->scsi_scrqs.scrqs){-for(i=0;i<nr_scsi_hw_queues;i++){-scrq=&vhost->scsi_scrqs.scrqs[i];-spin_lock(scrq->q_lock);-memset(scrq->msgs.scrq,0,PAGE_SIZE);-scrq->cur=0;-spin_unlock(scrq->q_lock);-}-}-/* And re-open it again */rc=plpar_hcall_norets(H_REG_CRQ,vdev->unit_address,crq->msg_token,PAGE_SIZE);
@@ -966,6 +959,9 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)dev_warn(vhost->dev,"Partner adapter not ready\n");elseif(rc!=0)dev_warn(vhost->dev,"Couldn't register crq (rc=%d)\n",rc);++ibmvfc_init_sub_crqs(vhost);+spin_unlock(vhost->crq.q_lock);spin_unlock_irqrestore(vhost->host->host_lock,flags);
If ibmvfc_init_sub_crqs() fails ibmvfc_probe() simply parrots
registration failure reported elsewhere, and futher
vhost->scsi_scrq.scrq == NULL is indication enough to the driver that it
has no sub-CRQs available. The mq_enabled check can also be moved into
ibmvfc_init_sub_crqs() such that each caller doesn't have to gate the
call with a mq_enabled check. Finally, in the case of sub-CRQ setup
failure setting do_enquiry can be turned off to putting the driver into
single queue fallback mode.
The aforementioned changes also simplify the next patch in the series
that fixes a hard reset issue, by tying a sub-CRQ setup failure and
do_enquiry logic into ibmvfc_init_sub_crqs().
Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
---
drivers/scsi/ibmvscsi/ibmvfc.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
@@ -5670,7 +5670,7 @@ static int ibmvfc_register_scsi_channel(struct ibmvfc_host *vhost,irq_failed:do{-plpar_hcall_norets(H_FREE_SUB_CRQ,vdev->unit_address,scrq->cookie);+rc=plpar_hcall_norets(H_FREE_SUB_CRQ,vdev->unit_address,scrq->cookie);}while(rc==H_BUSY||H_IS_LONG_BUSY(rc));
Other places in the driver where we get a busy return code back we have an msleep(100).
Should we be doing that here as well?
Thanks,
Brian
--
Brian King
Power Linux I/O
IBM Linux Technology Center
@@ -5670,7 +5670,7 @@ static int ibmvfc_register_scsi_channel(struct ibmvfc_host *vhost,irq_failed:do{-plpar_hcall_norets(H_FREE_SUB_CRQ,vdev->unit_address,scrq->cookie);+rc=plpar_hcall_norets(H_FREE_SUB_CRQ,vdev->unit_address,scrq->cookie);}while(rc==H_BUSY||H_IS_LONG_BUSY(rc));
Other places in the driver where we get a busy return code back we have an msleep(100).
Should we be doing that here as well?
Indeed, and actually even better would be to use rtas_busy_delay() which will
perform the sleep with the correct ms delay, and marks itself with the
might_sleep() macro.
-Tyrel