- correct rare multipath issue where a device is deleted
with an outstanding cmd which results in a tag collision.
. The cmd eventually completes. If a collision is detected
wait until the command slot is cleared.
Reviewed-by: Justin Lindley <[email protected]>
Reviewed-by: David Carroll <[email protected]>
Reviewed-by: Scott Teel <[email protected]>
Signed-off-by: Don Brace <[email protected]>
---
drivers/scsi/hpsa.c | 21 ++++++++++++++-------
drivers/scsi/hpsa.h | 1 +
2 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index ade0d505a32c..a315d108fdcb 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -5620,6 +5620,8 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh,
struct scsi_cmnd *cmd)
return 0;
}
c = cmd_tagged_alloc(h, cmd);
+ if (c == NULL)
+ return SCSI_MLQUEUE_DEVICE_BUSY;
/*
* Call alternate submit routine for I/O accelerated commands.
@@ -6026,7 +6028,6 @@ static struct CommandList *cmd_tagged_alloc(struct
ctlr_info *h,
BUG();
}
- atomic_inc(&c->refcount);
if (unlikely(!hpsa_is_cmd_idle(c))) {
/*
* We expect that the SCSI layer will hand us a unique tag
@@ -6034,14 +6035,20 @@ static struct CommandList *cmd_tagged_alloc(struct
ctlr_info *h,
* two requests...because if the selected command isn't idle
* then someone is going to be very disappointed.
*/
- dev_err(&h->pdev->dev,
- "tag collision (tag=%d) in cmd_tagged_alloc().\n",
- idx);
- if (c->scsi_cmd != NULL)
- scsi_print_command(c->scsi_cmd);
- scsi_print_command(scmd);
+ if (idx != h->last_collision_tag) { /* Print once per tag */
+ dev_warn(&h->pdev->dev,
+ "%s: tag collision (tag=%d)\n", __func__, idx);
+ if (c->scsi_cmd != NULL)
+ scsi_print_command(c->scsi_cmd);
+ if (scmd)
+ scsi_print_command(scmd);
+ h->last_collision_tag = idx;
+ }
+ return NULL;
}
+ atomic_inc(&c->refcount);
+
hpsa_cmd_partial_init(h, idx, c);
return c;
}
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 7aa7378f70dd..75210de71917 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -174,6 +174,7 @@ struct ctlr_info {
struct CfgTable __iomem *cfgtable;
int interrupts_enabled;
int max_commands;
+ int last_collision_tag; /* tags are global */
atomic_t commands_outstanding;
# define PERF_MODE_INT 0
# define DOORBELL_INT 1