Commit 4770e68d authored by Don Brace's avatar Don Brace Committed by Martin K. Petersen

scsi: hpsa: check for tag collision

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: default avatarJustin Lindley <justin.lindley@microsemi.com>
Reviewed-by: default avatarDavid Carroll <david.carroll@microsemi.com>
Reviewed-by: default avatarScott Teel <scott.teel@microsemi.com>
Signed-off-by: default avatarDon Brace <don.brace@microsemi.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 01192088
...@@ -5635,6 +5635,8 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd) ...@@ -5635,6 +5635,8 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
return 0; return 0;
} }
c = cmd_tagged_alloc(h, cmd); c = cmd_tagged_alloc(h, cmd);
if (c == NULL)
return SCSI_MLQUEUE_DEVICE_BUSY;
/* /*
* Call alternate submit routine for I/O accelerated commands. * Call alternate submit routine for I/O accelerated commands.
...@@ -6041,7 +6043,6 @@ static struct CommandList *cmd_tagged_alloc(struct ctlr_info *h, ...@@ -6041,7 +6043,6 @@ static struct CommandList *cmd_tagged_alloc(struct ctlr_info *h,
BUG(); BUG();
} }
atomic_inc(&c->refcount);
if (unlikely(!hpsa_is_cmd_idle(c))) { if (unlikely(!hpsa_is_cmd_idle(c))) {
/* /*
* We expect that the SCSI layer will hand us a unique tag * We expect that the SCSI layer will hand us a unique tag
...@@ -6049,14 +6050,20 @@ static struct CommandList *cmd_tagged_alloc(struct ctlr_info *h, ...@@ -6049,14 +6050,20 @@ static struct CommandList *cmd_tagged_alloc(struct ctlr_info *h,
* two requests...because if the selected command isn't idle * two requests...because if the selected command isn't idle
* then someone is going to be very disappointed. * then someone is going to be very disappointed.
*/ */
dev_err(&h->pdev->dev, if (idx != h->last_collision_tag) { /* Print once per tag */
"tag collision (tag=%d) in cmd_tagged_alloc().\n", dev_warn(&h->pdev->dev,
idx); "%s: tag collision (tag=%d)\n", __func__, idx);
if (c->scsi_cmd != NULL) if (c->scsi_cmd != NULL)
scsi_print_command(c->scsi_cmd); scsi_print_command(c->scsi_cmd);
scsi_print_command(scmd); if (scmd)
scsi_print_command(scmd);
h->last_collision_tag = idx;
}
return NULL;
} }
atomic_inc(&c->refcount);
hpsa_cmd_partial_init(h, idx, c); hpsa_cmd_partial_init(h, idx, c);
return c; return c;
} }
......
...@@ -174,6 +174,7 @@ struct ctlr_info { ...@@ -174,6 +174,7 @@ struct ctlr_info {
struct CfgTable __iomem *cfgtable; struct CfgTable __iomem *cfgtable;
int interrupts_enabled; int interrupts_enabled;
int max_commands; int max_commands;
int last_collision_tag; /* tags are global */
atomic_t commands_outstanding; atomic_t commands_outstanding;
# define PERF_MODE_INT 0 # define PERF_MODE_INT 0
# define DOORBELL_INT 1 # define DOORBELL_INT 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment