summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libiscsi.c
diff options
context:
space:
mode:
authorSagi Grimberg <sagig@mellanox.com>2014-03-05 12:43:49 -0500
committerRoland Dreier <roland@purestorage.com>2014-03-18 01:33:58 -0400
commit55e51eda4820ec5a1c1fc8693a51029f74eac2b9 (patch)
tree77198a5b21bff21aecc44f625b620efd2342d2f9 /drivers/scsi/libiscsi.c
parent177e31bd5a40999028f6694623ceea1bec5abff6 (diff)
SCSI/libiscsi: Add check_protection callback for transports
iSCSI needs to be at least aware that a task involves protection information. In case it does, after the transaction completed libiscsi will ask the transport to check the protection status of the transaction. Unlike transport errors, DIF errors should not prevent successful completion of the transaction from the transport point of view, but should be escelated to scsi mid-layer when constructing the scsi result and sense data. check_protection routine will return the ascq corresponding to the DIF error that occured (or 0 if no error happened). return ascq: - 0x1: GUARD_CHECK_FAILED - 0x2: APPTAG_CHECK_FAILED - 0x3: REFTAG_CHECK_FAILED Signed-off-by: Sagi Grimberg <sagig@mellanox.com> Signed-off-by: Alex Tabachnik <alext@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r--drivers/scsi/libiscsi.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 40462415291e..3c11acf67849 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -395,6 +395,10 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
395 if (rc) 395 if (rc)
396 return rc; 396 return rc;
397 } 397 }
398
399 if (scsi_get_prot_op(sc) != SCSI_PROT_NORMAL)
400 task->protected = true;
401
398 if (sc->sc_data_direction == DMA_TO_DEVICE) { 402 if (sc->sc_data_direction == DMA_TO_DEVICE) {
399 unsigned out_len = scsi_out(sc)->length; 403 unsigned out_len = scsi_out(sc)->length;
400 struct iscsi_r2t_info *r2t = &task->unsol_r2t; 404 struct iscsi_r2t_info *r2t = &task->unsol_r2t;
@@ -823,6 +827,33 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
823 827
824 sc->result = (DID_OK << 16) | rhdr->cmd_status; 828 sc->result = (DID_OK << 16) | rhdr->cmd_status;
825 829
830 if (task->protected) {
831 sector_t sector;
832 u8 ascq;
833
834 /**
835 * Transports that didn't implement check_protection
836 * callback but still published T10-PI support to scsi-mid
837 * deserve this BUG_ON.
838 **/
839 BUG_ON(!session->tt->check_protection);
840
841 ascq = session->tt->check_protection(task, &sector);
842 if (ascq) {
843 sc->result = DRIVER_SENSE << 24 |
844 SAM_STAT_CHECK_CONDITION;
845 scsi_build_sense_buffer(1, sc->sense_buffer,
846 ILLEGAL_REQUEST, 0x10, ascq);
847 sc->sense_buffer[7] = 0xc; /* Additional sense length */
848 sc->sense_buffer[8] = 0; /* Information desc type */
849 sc->sense_buffer[9] = 0xa; /* Additional desc length */
850 sc->sense_buffer[10] = 0x80; /* Validity bit */
851
852 put_unaligned_be64(sector, &sc->sense_buffer[12]);
853 goto out;
854 }
855 }
856
826 if (rhdr->response != ISCSI_STATUS_CMD_COMPLETED) { 857 if (rhdr->response != ISCSI_STATUS_CMD_COMPLETED) {
827 sc->result = DID_ERROR << 16; 858 sc->result = DID_ERROR << 16;
828 goto out; 859 goto out;
@@ -1567,6 +1598,7 @@ static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn,
1567 task->have_checked_conn = false; 1598 task->have_checked_conn = false;
1568 task->last_timeout = jiffies; 1599 task->last_timeout = jiffies;
1569 task->last_xfer = jiffies; 1600 task->last_xfer = jiffies;
1601 task->protected = false;
1570 INIT_LIST_HEAD(&task->running); 1602 INIT_LIST_HEAD(&task->running);
1571 return task; 1603 return task;
1572} 1604}