Target/dif: Introduce protection-passthough-only mode

Some transports (iSCSI/iSER/SRP/FC) support hardware INSERT/STRIP
capabilities while other transports like loopback/vhost-scsi need
perform this is software.

This patch allows fabrics using SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC
to signal the early LUN scan handling case where PROTECT CDB bits
are set, but no fabric buffer has been provided.

For transports which use generic new command these buffers have yet
to be allocated.

Also this way, target may support protection information
against legacy initiators (writes are inserted and reads
are stripped).

(Only set prot_pto for loopback during early special case - nab)

Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index fadad7c..a49ef0a 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -212,6 +212,10 @@
 		se_cmd->se_cmd_flags |= SCF_BIDI;
 
 	}
+
+	if (!scsi_prot_sg_count(sc) && scsi_get_prot_op(sc) != SCSI_PROT_NORMAL)
+		se_cmd->prot_pto = true;
+
 	rc = target_submit_cmd_map_sgls(se_cmd, tl_nexus->se_sess, sc->cmnd,
 			&tl_cmd->tl_sense_buf[0], tl_cmd->sc->device->lun,
 			scsi_bufflen(sc), tcm_loop_sam_attr(sc),
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index a1e75dd..c301d9b 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -634,7 +634,7 @@
 {
 	u8 protect = cdb[1] >> 5;
 
-	if (!cmd->t_prot_sg || !cmd->t_prot_nents)
+	if ((!cmd->t_prot_sg || !cmd->t_prot_nents) && cmd->prot_pto)
 		return true;
 
 	switch (dev->dev_attrib.pi_prot_type) {
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 4653d82..0a359fa 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1365,6 +1365,13 @@
 		target_put_sess_cmd(se_sess, se_cmd);
 		return 0;
 	}
+
+	rc = target_setup_cmd_from_cdb(se_cmd, cdb);
+	if (rc != 0) {
+		transport_generic_request_failure(se_cmd, rc);
+		return 0;
+	}
+
 	/*
 	 * Save pointers for SGLs containing protection information,
 	 * if present.
@@ -1374,11 +1381,6 @@
 		se_cmd->t_prot_nents = sgl_prot_count;
 	}
 
-	rc = target_setup_cmd_from_cdb(se_cmd, cdb);
-	if (rc != 0) {
-		transport_generic_request_failure(se_cmd, rc);
-		return 0;
-	}
 	/*
 	 * When a non zero sgl_count has been passed perform SGL passthrough
 	 * mapping for pre-allocated fabric memory instead of having target
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 5ae9249..82cb4ed 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -570,6 +570,7 @@
 	enum target_prot_ho	prot_handover;
 	sense_reason_t		pi_err;
 	sector_t		bad_sector;
+	bool			prot_pto;
 };
 
 struct se_ua {