|
@@ -2389,6 +2389,106 @@ mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * _scsih_setup_eedp - setup MPI request for EEDP transfer
|
|
|
|
+ * @scmd: pointer to scsi command object
|
|
|
|
+ * @mpi_request: pointer to the SCSI_IO reqest message frame
|
|
|
|
+ *
|
|
|
|
+ * Supporting protection 1 and 3.
|
|
|
|
+ *
|
|
|
|
+ * Returns nothing
|
|
|
|
+ */
|
|
|
|
+static void
|
|
|
|
+_scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request)
|
|
|
|
+{
|
|
|
|
+ u16 eedp_flags;
|
|
|
|
+ unsigned char prot_op = scsi_get_prot_op(scmd);
|
|
|
|
+ unsigned char prot_type = scsi_get_prot_type(scmd);
|
|
|
|
+
|
|
|
|
+ if (prot_type == SCSI_PROT_DIF_TYPE0 ||
|
|
|
|
+ prot_type == SCSI_PROT_DIF_TYPE2 ||
|
|
|
|
+ prot_op == SCSI_PROT_NORMAL)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (prot_op == SCSI_PROT_READ_STRIP)
|
|
|
|
+ eedp_flags = MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP;
|
|
|
|
+ else if (prot_op == SCSI_PROT_WRITE_INSERT)
|
|
|
|
+ eedp_flags = MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
|
|
|
|
+ else
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ mpi_request->EEDPBlockSize = scmd->device->sector_size;
|
|
|
|
+
|
|
|
|
+ switch (prot_type) {
|
|
|
|
+ case SCSI_PROT_DIF_TYPE1:
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * enable ref/guard checking
|
|
|
|
+ * auto increment ref tag
|
|
|
|
+ */
|
|
|
|
+ mpi_request->EEDPFlags = eedp_flags |
|
|
|
|
+ MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
|
|
|
|
+ MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
|
|
|
|
+ MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
|
|
|
|
+ mpi_request->CDB.EEDP32.PrimaryReferenceTag =
|
|
|
|
+ cpu_to_be32(scsi_get_lba(scmd));
|
|
|
|
+
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SCSI_PROT_DIF_TYPE3:
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * enable guard checking
|
|
|
|
+ */
|
|
|
|
+ mpi_request->EEDPFlags = eedp_flags |
|
|
|
|
+ MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
|
|
|
|
+
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * _scsih_eedp_error_handling - return sense code for EEDP errors
|
|
|
|
+ * @scmd: pointer to scsi command object
|
|
|
|
+ * @ioc_status: ioc status
|
|
|
|
+ *
|
|
|
|
+ * Returns nothing
|
|
|
|
+ */
|
|
|
|
+static void
|
|
|
|
+_scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
|
|
|
|
+{
|
|
|
|
+ u8 ascq;
|
|
|
|
+ u8 sk;
|
|
|
|
+ u8 host_byte;
|
|
|
|
+
|
|
|
|
+ switch (ioc_status) {
|
|
|
|
+ case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
|
|
|
|
+ ascq = 0x01;
|
|
|
|
+ break;
|
|
|
|
+ case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
|
|
|
|
+ ascq = 0x02;
|
|
|
|
+ break;
|
|
|
|
+ case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
|
|
|
|
+ ascq = 0x03;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ ascq = 0x00;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (scmd->sc_data_direction == DMA_TO_DEVICE) {
|
|
|
|
+ sk = ILLEGAL_REQUEST;
|
|
|
|
+ host_byte = DID_ABORT;
|
|
|
|
+ } else {
|
|
|
|
+ sk = ABORTED_COMMAND;
|
|
|
|
+ host_byte = DID_OK;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ scsi_build_sense_buffer(0, scmd->sense_buffer, sk, 0x10, ascq);
|
|
|
|
+ scmd->result = DRIVER_SENSE << 24 | (host_byte << 16) |
|
|
|
|
+ SAM_STAT_CHECK_CONDITION;
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* scsih_qcmd - main scsi request entry point
|
|
* scsih_qcmd - main scsi request entry point
|
|
* @scmd: pointer to scsi command object
|
|
* @scmd: pointer to scsi command object
|
|
@@ -2470,6 +2570,7 @@ scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
|
|
}
|
|
}
|
|
mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
|
|
mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
|
|
memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t));
|
|
memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t));
|
|
|
|
+ _scsih_setup_eedp(scmd, mpi_request);
|
|
mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
|
|
mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
|
|
if (sas_device_priv_data->sas_target->flags &
|
|
if (sas_device_priv_data->sas_target->flags &
|
|
MPT_TARGET_FLAGS_RAID_COMPONENT)
|
|
MPT_TARGET_FLAGS_RAID_COMPONENT)
|
|
@@ -2604,6 +2705,15 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
|
|
case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
|
|
case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
|
|
desc_ioc_state = "scsi ext terminated";
|
|
desc_ioc_state = "scsi ext terminated";
|
|
break;
|
|
break;
|
|
|
|
+ case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
|
|
|
|
+ desc_ioc_state = "eedp guard error";
|
|
|
|
+ break;
|
|
|
|
+ case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
|
|
|
|
+ desc_ioc_state = "eedp ref tag error";
|
|
|
|
+ break;
|
|
|
|
+ case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
|
|
|
|
+ desc_ioc_state = "eedp app tag error";
|
|
|
|
+ break;
|
|
default:
|
|
default:
|
|
desc_ioc_state = "unknown";
|
|
desc_ioc_state = "unknown";
|
|
break;
|
|
break;
|
|
@@ -2939,6 +3049,11 @@ scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
|
|
scmd->result = DID_RESET << 16;
|
|
scmd->result = DID_RESET << 16;
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
|
|
|
|
+ case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
|
|
|
|
+ case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
|
|
|
|
+ _scsih_eedp_error_handling(scmd, ioc_status);
|
|
|
|
+ break;
|
|
case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
|
|
case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
|
|
case MPI2_IOCSTATUS_INVALID_FUNCTION:
|
|
case MPI2_IOCSTATUS_INVALID_FUNCTION:
|
|
case MPI2_IOCSTATUS_INVALID_SGL:
|
|
case MPI2_IOCSTATUS_INVALID_SGL:
|
|
@@ -5503,6 +5618,9 @@ scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
goto out_add_shost_fail;
|
|
goto out_add_shost_fail;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION
|
|
|
|
+ | SHOST_DIF_TYPE3_PROTECTION);
|
|
|
|
+
|
|
/* event thread */
|
|
/* event thread */
|
|
snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
|
|
snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
|
|
"fw_event%d", ioc->id);
|
|
"fw_event%d", ioc->id);
|