From: Brian King Date: Fri, 24 Aug 2012 21:50:59 +0000 (-0500) Subject: [SCSI] ibmvfc: Fix double completion on abort timeout X-Git-Tag: next-20120918~73^2~1^2~2 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=90d76b757de84264cdc1b5d13654751ed38c6bed;p=karo-tx-linux.git [SCSI] ibmvfc: Fix double completion on abort timeout If an abort request times out to the virtual fibre channel adapter, the ibmvfc driver will kick off a reset of the adapter. This patch ensures we wait for the both the abort request and the request being aborted to be completed prior to exiting the eh_abort handler. This fixes a bug where the ibmvfc driver was erroneously returning success to the eh_abort handler then later sending back a response to the same command. Signed-off-by: Brian King Signed-off-by: James Bottomley --- diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 134a0ae85bb7..4f73daccc9f1 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -2241,6 +2241,21 @@ static int ibmvfc_match_key(struct ibmvfc_event *evt, void *key) return 0; } +/** + * ibmvfc_match_evt - Match function for specified event + * @evt: ibmvfc event struct + * @match: event to match + * + * Returns: + * 1 if event matches key / 0 if event does not match key + **/ +static int ibmvfc_match_evt(struct ibmvfc_event *evt, void *match) +{ + if (evt == match) + return 1; + return 0; +} + /** * ibmvfc_abort_task_set - Abort outstanding commands to the device * @sdev: scsi device to abort commands @@ -2322,7 +2337,20 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) if (rc) { sdev_printk(KERN_INFO, sdev, "Cancel failed, resetting host\n"); ibmvfc_reset_host(vhost); - rsp_rc = 0; + rsp_rc = -EIO; + rc = ibmvfc_wait_for_ops(vhost, sdev->hostdata, ibmvfc_match_key); + + if (rc == SUCCESS) + rsp_rc = 0; + + rc = ibmvfc_wait_for_ops(vhost, evt, ibmvfc_match_evt); + if (rc != SUCCESS) { + spin_lock_irqsave(vhost->host->host_lock, flags); + ibmvfc_hard_reset_host(vhost); + spin_unlock_irqrestore(vhost->host->host_lock, flags); + rsp_rc = 0; + } + goto out; } }