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

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
Loading
Loading
Loading
Loading
+14 −7
Original line number Diff line number Diff line
@@ -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,13 +6050,19 @@ 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 (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;
+1 −0
Original line number Diff line number Diff line
@@ -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