diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-04-02 17:19:09 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-04-07 04:48:56 -0400 |
commit | 66a3d5bc47d2973820816226e957db9e85285455 (patch) | |
tree | 9af631288b3701492f458d879516a4cda7e658cb /drivers/target | |
parent | 2d3359832513ac62a8bd6d2bffbb2c5bdd29aad3 (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.c | 44 |
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 | } |
1097 | EXPORT_SYMBOL(sbc_execute_unmap); | 1097 | EXPORT_SYMBOL(sbc_execute_unmap); |
1098 | 1098 | ||
1099 | void | ||
1100 | sbc_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 | |||
1099 | static sense_reason_t | 1143 | static sense_reason_t |
1100 | sbc_dif_v1_verify(struct se_device *dev, struct se_dif_v1_tuple *sdt, | 1144 | sbc_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) |