aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2014-04-02 17:19:09 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2014-04-07 04:48:56 -0400
commit66a3d5bc47d2973820816226e957db9e85285455 (patch)
tree9af631288b3701492f458d879516a4cda7e658cb /drivers/target
parent2d3359832513ac62a8bd6d2bffbb2c5bdd29aad3 (diff)
target/sbc: Add sbc_dif_generate software emulation
This patch adds WRITE_INSERT emulation within target-core using TYPE1 / TYPE3 PI modes in sbc_dif_generate() code. This is useful in order for existing legacy fabrics that do not support protection offloads to interact with backend devices that currently have T10 PI enabled. v2 changes: - Rename to sbc_dif_generate() (Sagi) Cc: Martin K. Petersen <martin.petersen@oracle.com> Cc: Sagi Grimberg <sagig@mellanox.com> Cc: Or Gerlitz <ogerlitz@mellanox.com> Cc: Quinn Tran <quinn.tran@qlogic.com> Cc: Giridhar Malavali <giridhar.malavali@qlogic.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/target_core_sbc.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index f2d73dd4f9a3..cc8c0ba53930 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -1096,6 +1096,50 @@ err:
1096} 1096}
1097EXPORT_SYMBOL(sbc_execute_unmap); 1097EXPORT_SYMBOL(sbc_execute_unmap);
1098 1098
1099void
1100sbc_dif_generate(struct se_cmd *cmd)
1101{
1102 struct se_device *dev = cmd->se_dev;
1103 struct se_dif_v1_tuple *sdt;
1104 struct scatterlist *dsg, *psg = cmd->t_prot_sg;
1105 sector_t sector = cmd->t_task_lba;
1106 void *daddr, *paddr;
1107 int i, j, offset = 0;
1108
1109 for_each_sg(cmd->t_data_sg, dsg, cmd->t_data_nents, i) {
1110 daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
1111 paddr = kmap_atomic(sg_page(psg)) + psg->offset;
1112
1113 for (j = 0; j < dsg->length; j += dev->dev_attrib.block_size) {
1114
1115 if (offset >= psg->length) {
1116 kunmap_atomic(paddr);
1117 psg = sg_next(psg);
1118 paddr = kmap_atomic(sg_page(psg)) + psg->offset;
1119 offset = 0;
1120 }
1121
1122 sdt = paddr + offset;
1123 sdt->guard_tag = cpu_to_be16(crc_t10dif(daddr + j,
1124 dev->dev_attrib.block_size));
1125 if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE1_PROT)
1126 sdt->ref_tag = cpu_to_be32(sector & 0xffffffff);
1127 sdt->app_tag = 0;
1128
1129 pr_debug("DIF WRITE INSERT sector: %llu guard_tag: 0x%04x"
1130 " app_tag: 0x%04x ref_tag: %u\n",
1131 (unsigned long long)sector, sdt->guard_tag,
1132 sdt->app_tag, be32_to_cpu(sdt->ref_tag));
1133
1134 sector++;
1135 offset += sizeof(struct se_dif_v1_tuple);
1136 }
1137
1138 kunmap_atomic(paddr);
1139 kunmap_atomic(daddr);
1140 }
1141}
1142
1099static sense_reason_t 1143static sense_reason_t
1100sbc_dif_v1_verify(struct se_device *dev, struct se_dif_v1_tuple *sdt, 1144sbc_dif_v1_verify(struct se_device *dev, struct se_dif_v1_tuple *sdt,
1101 const void *p, sector_t sector, unsigned int ei_lba) 1145 const void *p, sector_t sector, unsigned int ei_lba)