aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/vmw_pvscsi.c
diff options
context:
space:
mode:
authorArvind Kumar <arvindkumar@vmware.com>2014-03-08 15:51:12 -0500
committerJames Bottomley <JBottomley@Parallels.com>2014-03-19 18:04:45 -0400
commita2713cceb3a8efef8b86bec06f10689c95ddbc8c (patch)
tree66ae4312f340d057675091a9c240fe5bb09ce470 /drivers/scsi/vmw_pvscsi.c
parent4909cc2b89715c2dfd4c466a37cc08b2b3890fed (diff)
[SCSI] vmw_pvscsi: Fix pvscsi_abort() function.
This change ensures that pvscsi_abort() function returns SUCCESS only when the command in question was actually completed, otherwise returns FAILURE. The code before change, was causing a bug where driver tries to complete a command to the mid-layer while the mid-layer has already requested the driver to abort that command, in response to which the driver has responded with SUCCESS causing mid-layer to free the command struct. Signed-off-by: Arvind Kumar <arvindkumar@vmware.com> Tested-by: Ewan Milne <emilne@redhat.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/vmw_pvscsi.c')
-rw-r--r--drivers/scsi/vmw_pvscsi.c51
1 files changed, 47 insertions, 4 deletions
diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c
index b9755ec0e812..7c5abd7f6c67 100644
--- a/drivers/scsi/vmw_pvscsi.c
+++ b/drivers/scsi/vmw_pvscsi.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Linux driver for VMware's para-virtualized SCSI HBA. 2 * Linux driver for VMware's para-virtualized SCSI HBA.
3 * 3 *
4 * Copyright (C) 2008-2009, VMware, Inc. All Rights Reserved. 4 * Copyright (C) 2008-2014, VMware, Inc. All Rights Reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the 7 * under the terms of the GNU General Public License as published by the
@@ -62,6 +62,7 @@ struct pvscsi_ctx {
62 dma_addr_t dataPA; 62 dma_addr_t dataPA;
63 dma_addr_t sensePA; 63 dma_addr_t sensePA;
64 dma_addr_t sglPA; 64 dma_addr_t sglPA;
65 struct completion *abort_cmp;
65}; 66};
66 67
67struct pvscsi_adapter { 68struct pvscsi_adapter {
@@ -177,6 +178,7 @@ static void pvscsi_release_context(struct pvscsi_adapter *adapter,
177 struct pvscsi_ctx *ctx) 178 struct pvscsi_ctx *ctx)
178{ 179{
179 ctx->cmd = NULL; 180 ctx->cmd = NULL;
181 ctx->abort_cmp = NULL;
180 list_add(&ctx->list, &adapter->cmd_pool); 182 list_add(&ctx->list, &adapter->cmd_pool);
181} 183}
182 184
@@ -496,15 +498,27 @@ static void pvscsi_complete_request(struct pvscsi_adapter *adapter,
496{ 498{
497 struct pvscsi_ctx *ctx; 499 struct pvscsi_ctx *ctx;
498 struct scsi_cmnd *cmd; 500 struct scsi_cmnd *cmd;
501 struct completion *abort_cmp;
499 u32 btstat = e->hostStatus; 502 u32 btstat = e->hostStatus;
500 u32 sdstat = e->scsiStatus; 503 u32 sdstat = e->scsiStatus;
501 504
502 ctx = pvscsi_get_context(adapter, e->context); 505 ctx = pvscsi_get_context(adapter, e->context);
503 cmd = ctx->cmd; 506 cmd = ctx->cmd;
507 abort_cmp = ctx->abort_cmp;
504 pvscsi_unmap_buffers(adapter, ctx); 508 pvscsi_unmap_buffers(adapter, ctx);
505 pvscsi_release_context(adapter, ctx); 509 pvscsi_release_context(adapter, ctx);
506 cmd->result = 0; 510 if (abort_cmp) {
511 /*
512 * The command was requested to be aborted. Just signal that
513 * the request completed and swallow the actual cmd completion
514 * here. The abort handler will post a completion for this
515 * command indicating that it got successfully aborted.
516 */
517 complete(abort_cmp);
518 return;
519 }
507 520
521 cmd->result = 0;
508 if (sdstat != SAM_STAT_GOOD && 522 if (sdstat != SAM_STAT_GOOD &&
509 (btstat == BTSTAT_SUCCESS || 523 (btstat == BTSTAT_SUCCESS ||
510 btstat == BTSTAT_LINKED_COMMAND_COMPLETED || 524 btstat == BTSTAT_LINKED_COMMAND_COMPLETED ||
@@ -726,6 +740,8 @@ static int pvscsi_abort(struct scsi_cmnd *cmd)
726 struct pvscsi_adapter *adapter = shost_priv(cmd->device->host); 740 struct pvscsi_adapter *adapter = shost_priv(cmd->device->host);
727 struct pvscsi_ctx *ctx; 741 struct pvscsi_ctx *ctx;
728 unsigned long flags; 742 unsigned long flags;
743 int result = SUCCESS;
744 DECLARE_COMPLETION_ONSTACK(abort_cmp);
729 745
730 scmd_printk(KERN_DEBUG, cmd, "task abort on host %u, %p\n", 746 scmd_printk(KERN_DEBUG, cmd, "task abort on host %u, %p\n",
731 adapter->host->host_no, cmd); 747 adapter->host->host_no, cmd);
@@ -748,13 +764,40 @@ static int pvscsi_abort(struct scsi_cmnd *cmd)
748 goto out; 764 goto out;
749 } 765 }
750 766
767 /*
768 * Mark that the command has been requested to be aborted and issue
769 * the abort.
770 */
771 ctx->abort_cmp = &abort_cmp;
772
751 pvscsi_abort_cmd(adapter, ctx); 773 pvscsi_abort_cmd(adapter, ctx);
774 spin_unlock_irqrestore(&adapter->hw_lock, flags);
775 /* Wait for 2 secs for the completion. */
776 wait_for_completion_timeout(&abort_cmp, msecs_to_jiffies(2000));
777 spin_lock_irqsave(&adapter->hw_lock, flags);
752 778
753 pvscsi_process_completion_ring(adapter); 779 if (!completion_done(&abort_cmp)) {
780 /*
781 * Failed to abort the command, unmark the fact that it
782 * was requested to be aborted.
783 */
784 ctx->abort_cmp = NULL;
785 result = FAILED;
786 scmd_printk(KERN_DEBUG, cmd,
787 "Failed to get completion for aborted cmd %p\n",
788 cmd);
789 goto out;
790 }
791
792 /*
793 * Successfully aborted the command.
794 */
795 cmd->result = (DID_ABORT << 16);
796 cmd->scsi_done(cmd);
754 797
755out: 798out:
756 spin_unlock_irqrestore(&adapter->hw_lock, flags); 799 spin_unlock_irqrestore(&adapter->hw_lock, flags);
757 return SUCCESS; 800 return result;
758} 801}
759 802
760/* 803/*