Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a09c1441 authored by Scott Teel's avatar Scott Teel Committed by James Bottomley
Browse files

[SCSI] hpsa: retry certain ioaccel error cases on the RAID path



Change the handling of HP SSD Smart Path errors with status:
  0x02 CHECK CONDITION
  0x08 BUSY
  0x18 RESERVATION CONFLICT
  0x40 TASK ABORTED
So that they get retried on the RAID Path.

Signed-off-by: default avatarScott Teel <scott.teel@hp.com>
Signed-off-by: default avatarStephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 1b70150a
Loading
Loading
Loading
Loading
+39 −6
Original line number Original line Diff line number Diff line
@@ -1351,12 +1351,18 @@ static void hpsa_unmap_sg_chain_block(struct ctlr_info *h,
	pci_unmap_single(h->pdev, temp64.val, chain_sg->Len, PCI_DMA_TODEVICE);
	pci_unmap_single(h->pdev, temp64.val, chain_sg->Len, PCI_DMA_TODEVICE);
}
}


static void handle_ioaccel_mode2_error(struct ctlr_info *h,

/* Decode the various types of errors on ioaccel2 path.
 * Return 1 for any error that should generate a RAID path retry.
 * Return 0 for errors that don't require a RAID path retry.
 */
static int handle_ioaccel_mode2_error(struct ctlr_info *h,
					struct CommandList *c,
					struct CommandList *c,
					struct scsi_cmnd *cmd,
					struct scsi_cmnd *cmd,
					struct io_accel2_cmd *c2)
					struct io_accel2_cmd *c2)
{
{
	int data_len;
	int data_len;
	int retry = 0;


	switch (c2->error_data.serv_response) {
	switch (c2->error_data.serv_response) {
	case IOACCEL2_SERV_RESPONSE_COMPLETE:
	case IOACCEL2_SERV_RESPONSE_COMPLETE:
@@ -1380,16 +1386,19 @@ static void handle_ioaccel_mode2_error(struct ctlr_info *h,
			memcpy(cmd->sense_buffer,
			memcpy(cmd->sense_buffer,
				c2->error_data.sense_data_buff, data_len);
				c2->error_data.sense_data_buff, data_len);
			cmd->result |= SAM_STAT_CHECK_CONDITION;
			cmd->result |= SAM_STAT_CHECK_CONDITION;
			retry = 1;
			break;
			break;
		case IOACCEL2_STATUS_SR_TASK_COMP_BUSY:
		case IOACCEL2_STATUS_SR_TASK_COMP_BUSY:
			dev_warn(&h->pdev->dev,
			dev_warn(&h->pdev->dev,
				"%s: task complete with BUSY status.\n",
				"%s: task complete with BUSY status.\n",
				"HP SSD Smart Path");
				"HP SSD Smart Path");
			retry = 1;
			break;
			break;
		case IOACCEL2_STATUS_SR_TASK_COMP_RES_CON:
		case IOACCEL2_STATUS_SR_TASK_COMP_RES_CON:
			dev_warn(&h->pdev->dev,
			dev_warn(&h->pdev->dev,
				"%s: task complete with reservation conflict.\n",
				"%s: task complete with reservation conflict.\n",
				"HP SSD Smart Path");
				"HP SSD Smart Path");
			retry = 1;
			break;
			break;
		case IOACCEL2_STATUS_SR_TASK_COMP_SET_FULL:
		case IOACCEL2_STATUS_SR_TASK_COMP_SET_FULL:
			/* Make scsi midlayer do unlimited retries */
			/* Make scsi midlayer do unlimited retries */
@@ -1399,11 +1408,13 @@ static void handle_ioaccel_mode2_error(struct ctlr_info *h,
			dev_warn(&h->pdev->dev,
			dev_warn(&h->pdev->dev,
				"%s: task complete with aborted status.\n",
				"%s: task complete with aborted status.\n",
				"HP SSD Smart Path");
				"HP SSD Smart Path");
			retry = 1;
			break;
			break;
		default:
		default:
			dev_warn(&h->pdev->dev,
			dev_warn(&h->pdev->dev,
				"%s: task complete with unrecognized status: 0x%02x\n",
				"%s: task complete with unrecognized status: 0x%02x\n",
				"HP SSD Smart Path", c2->error_data.status);
				"HP SSD Smart Path", c2->error_data.status);
			retry = 1;
			break;
			break;
		}
		}
		break;
		break;
@@ -1412,6 +1423,7 @@ static void handle_ioaccel_mode2_error(struct ctlr_info *h,
		dev_warn(&h->pdev->dev,
		dev_warn(&h->pdev->dev,
			"unexpected delivery or target failure, status = 0x%02x\n",
			"unexpected delivery or target failure, status = 0x%02x\n",
			c2->error_data.status);
			c2->error_data.status);
		retry = 1;
		break;
		break;
	case IOACCEL2_SERV_RESPONSE_TMF_COMPLETE:
	case IOACCEL2_SERV_RESPONSE_TMF_COMPLETE:
		break;
		break;
@@ -1419,6 +1431,7 @@ static void handle_ioaccel_mode2_error(struct ctlr_info *h,
		break;
		break;
	case IOACCEL2_SERV_RESPONSE_TMF_REJECTED:
	case IOACCEL2_SERV_RESPONSE_TMF_REJECTED:
		dev_warn(&h->pdev->dev, "task management function rejected.\n");
		dev_warn(&h->pdev->dev, "task management function rejected.\n");
		retry = 1;
		break;
		break;
	case IOACCEL2_SERV_RESPONSE_TMF_WRONG_LUN:
	case IOACCEL2_SERV_RESPONSE_TMF_WRONG_LUN:
		dev_warn(&h->pdev->dev, "task management function invalid LUN\n");
		dev_warn(&h->pdev->dev, "task management function invalid LUN\n");
@@ -1426,9 +1439,13 @@ static void handle_ioaccel_mode2_error(struct ctlr_info *h,
	default:
	default:
		dev_warn(&h->pdev->dev,
		dev_warn(&h->pdev->dev,
			"%s: Unrecognized server response: 0x%02x\n",
			"%s: Unrecognized server response: 0x%02x\n",
			"HP SSD Smart Path", c2->error_data.serv_response);
			"HP SSD Smart Path",
			c2->error_data.serv_response);
		retry = 1;
		break;
		break;
	}
	}

	return retry;	/* retry on raid path? */
}
}


static void process_ioaccel2_completion(struct ctlr_info *h,
static void process_ioaccel2_completion(struct ctlr_info *h,
@@ -1436,6 +1453,7 @@ static void process_ioaccel2_completion(struct ctlr_info *h,
		struct hpsa_scsi_dev_t *dev)
		struct hpsa_scsi_dev_t *dev)
{
{
	struct io_accel2_cmd *c2 = &h->ioaccel2_cmd_pool[c->cmdindex];
	struct io_accel2_cmd *c2 = &h->ioaccel2_cmd_pool[c->cmdindex];
	int raid_retry = 0;


	/* check for good status */
	/* check for good status */
	if (likely(c2->error_data.serv_response == 0 &&
	if (likely(c2->error_data.serv_response == 0 &&
@@ -1452,11 +1470,16 @@ static void process_ioaccel2_completion(struct ctlr_info *h,
	if (is_logical_dev_addr_mode(dev->scsi3addr) &&
	if (is_logical_dev_addr_mode(dev->scsi3addr) &&
		c2->error_data.serv_response ==
		c2->error_data.serv_response ==
			IOACCEL2_SERV_RESPONSE_FAILURE) {
			IOACCEL2_SERV_RESPONSE_FAILURE) {
		if (c2->error_data.status !=
		if (c2->error_data.status ==
			IOACCEL2_STATUS_SR_IOACCEL_DISABLED)
			IOACCEL2_STATUS_SR_IOACCEL_DISABLED)
			dev_warn(&h->pdev->dev,
			dev_warn(&h->pdev->dev,
				"%s: Error 0x%02x, Retrying on standard path.\n",
				"%s: Path is unavailable, retrying on standard path.\n",
				"HP SSD Smart Path");
		else
			dev_warn(&h->pdev->dev,
				"%s: Error 0x%02x, retrying on standard path.\n",
				"HP SSD Smart Path", c2->error_data.status);
				"HP SSD Smart Path", c2->error_data.status);

		dev->offload_enabled = 0;
		dev->offload_enabled = 0;
		h->drv_req_rescan = 1;	/* schedule controller for a rescan */
		h->drv_req_rescan = 1;	/* schedule controller for a rescan */
		cmd->result = DID_SOFT_ERROR << 16;
		cmd->result = DID_SOFT_ERROR << 16;
@@ -1464,7 +1487,17 @@ static void process_ioaccel2_completion(struct ctlr_info *h,
		cmd->scsi_done(cmd);
		cmd->scsi_done(cmd);
		return;
		return;
	}
	}
	handle_ioaccel_mode2_error(h, c, cmd, c2);
	raid_retry = handle_ioaccel_mode2_error(h, c, cmd, c2);
	/* If error found, disable Smart Path, schedule a rescan,
	 * and force a retry on the standard path.
	 */
	if (raid_retry) {
		dev_warn(&h->pdev->dev, "%s: Retrying on standard path.\n",
			"HP SSD Smart Path");
		dev->offload_enabled = 0; /* Disable Smart Path */
		h->drv_req_rescan = 1;	  /* schedule controller rescan */
		cmd->result = DID_SOFT_ERROR << 16;
	}
	cmd_free(h, c);
	cmd_free(h, c);
	cmd->scsi_done(cmd);
	cmd->scsi_done(cmd);
}
}