From: Nicholas Bellinger Date: Sat, 28 Feb 2015 06:05:21 +0000 (-0800) Subject: target: Add protected fabric + unprotected device support X-Git-Tag: omap-for-v4.1/fixes-rc1~30^2~51 X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=38b57f82;p=pandora-kernel.git target: Add protected fabric + unprotected device support This patch adds a new target_core_fabric_ops callback for allowing fabric drivers to expose a TPG attribute for signaling when a T10-PI protected fabric wants to function with an un-protected device without T10-PI. This specifically is to allow LIO to perform WRITE_STRIP + READ_INSERT operations when functioning with non T10-PI enabled devices, seperate from any available hw offloads the fabric supports. This is done using a new se_sess->sess_prot_type that is set at fabric session creation time based upon the TPG attribute. It currently cannot be changed for individual sessions after initial creation. Also, update existing target_core_sbc.c code to honor sess_prot_type when setting up cmd->prot_op + cmd->prot_type assignments. (Add unlikely and !! boolean conversion in sbc_check_prot - Sagi) Cc: Martin Petersen Cc: Sagi Grimberg Cc: Christoph Hellwig Cc: Doug Gilbert Signed-off-by: Nicholas Bellinger --- diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 95a7a7444965..9efd1fd985ee 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -581,12 +581,13 @@ sbc_compare_and_write(struct se_cmd *cmd) } static int -sbc_set_prot_op_checks(u8 protect, enum target_prot_type prot_type, +sbc_set_prot_op_checks(u8 protect, bool fabric_prot, enum target_prot_type prot_type, bool is_write, struct se_cmd *cmd) { if (is_write) { - cmd->prot_op = protect ? TARGET_PROT_DOUT_PASS : - TARGET_PROT_DOUT_INSERT; + cmd->prot_op = fabric_prot ? TARGET_PROT_DOUT_STRIP : + protect ? TARGET_PROT_DOUT_PASS : + TARGET_PROT_DOUT_INSERT; switch (protect) { case 0x0: case 0x3: @@ -610,8 +611,9 @@ sbc_set_prot_op_checks(u8 protect, enum target_prot_type prot_type, return -EINVAL; } } else { - cmd->prot_op = protect ? TARGET_PROT_DIN_PASS : - TARGET_PROT_DIN_STRIP; + cmd->prot_op = fabric_prot ? TARGET_PROT_DIN_INSERT : + protect ? TARGET_PROT_DIN_PASS : + TARGET_PROT_DIN_STRIP; switch (protect) { case 0x0: case 0x1: @@ -644,11 +646,15 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb, u32 sectors, bool is_write) { u8 protect = cdb[1] >> 5; + int sp_ops = cmd->se_sess->sup_prot_ops; + int pi_prot_type = dev->dev_attrib.pi_prot_type; + bool fabric_prot = false; if (!cmd->t_prot_sg || !cmd->t_prot_nents) { - if (protect && !dev->dev_attrib.pi_prot_type) { - pr_err("CDB contains protect bit, but device does not" - " advertise PROTECT=1 feature bit\n"); + if (unlikely(protect && + !dev->dev_attrib.pi_prot_type && !cmd->se_sess->sess_prot_type)) { + pr_err("CDB contains protect bit, but device + fabric does" + " not advertise PROTECT=1 feature bit\n"); return TCM_INVALID_CDB_FIELD; } if (cmd->prot_pto) @@ -669,15 +675,28 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb, cmd->reftag_seed = cmd->t_task_lba; break; case TARGET_DIF_TYPE0_PROT: + /* + * See if the fabric supports T10-PI, and the session has been + * configured to allow export PROTECT=1 feature bit with backend + * devices that don't support T10-PI. + */ + fabric_prot = is_write ? + !!(sp_ops & (TARGET_PROT_DOUT_PASS | TARGET_PROT_DOUT_STRIP)) : + !!(sp_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DIN_INSERT)); + + if (fabric_prot && cmd->se_sess->sess_prot_type) { + pi_prot_type = cmd->se_sess->sess_prot_type; + break; + } + /* Fallthrough */ default: return TCM_NO_SENSE; } - if (sbc_set_prot_op_checks(protect, dev->dev_attrib.pi_prot_type, - is_write, cmd)) + if (sbc_set_prot_op_checks(protect, fabric_prot, pi_prot_type, is_write, cmd)) return TCM_INVALID_CDB_FIELD; - cmd->prot_type = dev->dev_attrib.pi_prot_type; + cmd->prot_type = pi_prot_type; cmd->prot_length = dev->prot_length * sectors; /** @@ -1231,6 +1250,9 @@ sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read, unsigned int i, len, left; unsigned int offset = sg_off; + if (!sg) + return; + left = sectors * dev->prot_length; for_each_sg(cmd->t_prot_sg, psg, cmd->t_prot_nents, i) { Reading git-diff-tree failed