aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c13
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.h2
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c47
3 files changed, 62 insertions, 0 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index a64b87811915..f13d7e9801f1 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -306,6 +306,18 @@ static void iscsi_iser_cleanup_task(struct iscsi_task *task)
306 } 306 }
307} 307}
308 308
309static u8 iscsi_iser_check_protection(struct iscsi_task *task, sector_t *sector)
310{
311 struct iscsi_iser_task *iser_task = task->dd_data;
312
313 if (iser_task->dir[ISER_DIR_IN])
314 return iser_check_task_pi_status(iser_task, ISER_DIR_IN,
315 sector);
316 else
317 return iser_check_task_pi_status(iser_task, ISER_DIR_OUT,
318 sector);
319}
320
309static struct iscsi_cls_conn * 321static struct iscsi_cls_conn *
310iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) 322iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
311{ 323{
@@ -742,6 +754,7 @@ static struct iscsi_transport iscsi_iser_transport = {
742 .xmit_task = iscsi_iser_task_xmit, 754 .xmit_task = iscsi_iser_task_xmit,
743 .cleanup_task = iscsi_iser_cleanup_task, 755 .cleanup_task = iscsi_iser_cleanup_task,
744 .alloc_pdu = iscsi_iser_pdu_alloc, 756 .alloc_pdu = iscsi_iser_pdu_alloc,
757 .check_protection = iscsi_iser_check_protection,
745 /* recovery */ 758 /* recovery */
746 .session_recovery_timedout = iscsi_session_recovery_timedout, 759 .session_recovery_timedout = iscsi_session_recovery_timedout,
747 760
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index fce54092d300..95f291fca178 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -483,4 +483,6 @@ int iser_create_fmr_pool(struct iser_conn *ib_conn, unsigned cmds_max);
483void iser_free_fmr_pool(struct iser_conn *ib_conn); 483void iser_free_fmr_pool(struct iser_conn *ib_conn);
484int iser_create_fastreg_pool(struct iser_conn *ib_conn, unsigned cmds_max); 484int iser_create_fastreg_pool(struct iser_conn *ib_conn, unsigned cmds_max);
485void iser_free_fastreg_pool(struct iser_conn *ib_conn); 485void iser_free_fastreg_pool(struct iser_conn *ib_conn);
486u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task,
487 enum iser_data_dir cmd_dir, sector_t *sector);
486#endif 488#endif
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index 0404c71761f9..abbb6ec90d14 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -1153,3 +1153,50 @@ static void iser_cq_callback(struct ib_cq *cq, void *cq_context)
1153 1153
1154 tasklet_schedule(&device->cq_tasklet[cq_index]); 1154 tasklet_schedule(&device->cq_tasklet[cq_index]);
1155} 1155}
1156
1157u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task,
1158 enum iser_data_dir cmd_dir, sector_t *sector)
1159{
1160 struct iser_mem_reg *reg = &iser_task->rdma_regd[cmd_dir].reg;
1161 struct fast_reg_descriptor *desc = reg->mem_h;
1162 unsigned long sector_size = iser_task->sc->device->sector_size;
1163 struct ib_mr_status mr_status;
1164 int ret;
1165
1166 if (desc && desc->reg_indicators & ISER_FASTREG_PROTECTED) {
1167 desc->reg_indicators &= ~ISER_FASTREG_PROTECTED;
1168 ret = ib_check_mr_status(desc->pi_ctx->sig_mr,
1169 IB_MR_CHECK_SIG_STATUS, &mr_status);
1170 if (ret) {
1171 pr_err("ib_check_mr_status failed, ret %d\n", ret);
1172 goto err;
1173 }
1174
1175 if (mr_status.fail_status & IB_MR_CHECK_SIG_STATUS) {
1176 sector_t sector_off = mr_status.sig_err.sig_err_offset;
1177
1178 do_div(sector_off, sector_size + 8);
1179 *sector = scsi_get_lba(iser_task->sc) + sector_off;
1180
1181 pr_err("PI error found type %d at sector %lx "
1182 "expected %x vs actual %x\n",
1183 mr_status.sig_err.err_type, *sector,
1184 mr_status.sig_err.expected,
1185 mr_status.sig_err.actual);
1186
1187 switch (mr_status.sig_err.err_type) {
1188 case IB_SIG_BAD_GUARD:
1189 return 0x1;
1190 case IB_SIG_BAD_REFTAG:
1191 return 0x3;
1192 case IB_SIG_BAD_APPTAG:
1193 return 0x2;
1194 }
1195 }
1196 }
1197
1198 return 0;
1199err:
1200 /* Not alot we can do here, return ambiguous guard error */
1201 return 0x1;
1202}