forked from Minki/linux
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: Justin Lindley <justin.lindley@microsemi.com> Reviewed-by: David Carroll <david.carroll@microsemi.com> Reviewed-by: Scott Teel <scott.teel@microsemi.com> Signed-off-by: Don Brace <don.brace@microsemi.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
0119208885
commit
4770e68d16
@ -5635,6 +5635,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.
|
||||
@ -6041,7 +6043,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
|
||||
@ -6049,14 +6050,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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user