/*
  * Linux driver for VMware's para-virtualized SCSI HBA.
  *
- * Copyright (C) 2008-2009, VMware, Inc. All Rights Reserved.
+ * Copyright (C) 2008-2014, VMware, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
        dma_addr_t              dataPA;
        dma_addr_t              sensePA;
        dma_addr_t              sglPA;
+       struct completion       *abort_cmp;
 };
 
 struct pvscsi_adapter {
                                   struct pvscsi_ctx *ctx)
 {
        ctx->cmd = NULL;
+       ctx->abort_cmp = NULL;
        list_add(&ctx->list, &adapter->cmd_pool);
 }
 
 {
        struct pvscsi_ctx *ctx;
        struct scsi_cmnd *cmd;
+       struct completion *abort_cmp;
        u32 btstat = e->hostStatus;
        u32 sdstat = e->scsiStatus;
 
        ctx = pvscsi_get_context(adapter, e->context);
        cmd = ctx->cmd;
+       abort_cmp = ctx->abort_cmp;
        pvscsi_unmap_buffers(adapter, ctx);
        pvscsi_release_context(adapter, ctx);
-       cmd->result = 0;
+       if (abort_cmp) {
+               /*
+                * The command was requested to be aborted. Just signal that
+                * the request completed and swallow the actual cmd completion
+                * here. The abort handler will post a completion for this
+                * command indicating that it got successfully aborted.
+                */
+               complete(abort_cmp);
+               return;
+       }
 
+       cmd->result = 0;
        if (sdstat != SAM_STAT_GOOD &&
            (btstat == BTSTAT_SUCCESS ||
             btstat == BTSTAT_LINKED_COMMAND_COMPLETED ||
        struct pvscsi_adapter *adapter = shost_priv(cmd->device->host);
        struct pvscsi_ctx *ctx;
        unsigned long flags;
+       int result = SUCCESS;
+       DECLARE_COMPLETION_ONSTACK(abort_cmp);
 
        scmd_printk(KERN_DEBUG, cmd, "task abort on host %u, %p\n",
                    adapter->host->host_no, cmd);
                goto out;
        }
 
+       /*
+        * Mark that the command has been requested to be aborted and issue
+        * the abort.
+        */
+       ctx->abort_cmp = &abort_cmp;
+
        pvscsi_abort_cmd(adapter, ctx);
+       spin_unlock_irqrestore(&adapter->hw_lock, flags);
+       /* Wait for 2 secs for the completion. */
+       wait_for_completion_timeout(&abort_cmp, msecs_to_jiffies(2000));
+       spin_lock_irqsave(&adapter->hw_lock, flags);
 
-       pvscsi_process_completion_ring(adapter);
+       if (!completion_done(&abort_cmp)) {
+               /*
+                * Failed to abort the command, unmark the fact that it
+                * was requested to be aborted.
+                */
+               ctx->abort_cmp = NULL;
+               result = FAILED;
+               scmd_printk(KERN_DEBUG, cmd,
+                           "Failed to get completion for aborted cmd %p\n",
+                           cmd);
+               goto out;
+       }
+
+       /*
+        * Successfully aborted the command.
+        */
+       cmd->result = (DID_ABORT << 16);
+       cmd->scsi_done(cmd);
 
 out:
        spin_unlock_irqrestore(&adapter->hw_lock, flags);
-       return SUCCESS;
+       return result;
 }
 
 /*
 
 /*
  * VMware PVSCSI header file
  *
- * Copyright (C) 2008-2009, VMware, Inc. All Rights Reserved.
+ * Copyright (C) 2008-2014, VMware, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
 
 #include <linux/types.h>
 
-#define PVSCSI_DRIVER_VERSION_STRING   "1.0.2.0-k"
+#define PVSCSI_DRIVER_VERSION_STRING   "1.0.3.0-k"
 
 #define PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT 128