diff options
| -rw-r--r-- | drivers/infiniband/ulp/iser/iscsi_iser.c | 13 | ||||
| -rw-r--r-- | drivers/infiniband/ulp/iser/iscsi_iser.h | 2 | ||||
| -rw-r--r-- | drivers/infiniband/ulp/iser/iser_verbs.c | 47 |
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 | ||
| 309 | static 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 | |||
| 309 | static struct iscsi_cls_conn * | 321 | static struct iscsi_cls_conn * |
| 310 | iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) | 322 | iscsi_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); | |||
| 483 | void iser_free_fmr_pool(struct iser_conn *ib_conn); | 483 | void iser_free_fmr_pool(struct iser_conn *ib_conn); |
| 484 | int iser_create_fastreg_pool(struct iser_conn *ib_conn, unsigned cmds_max); | 484 | int iser_create_fastreg_pool(struct iser_conn *ib_conn, unsigned cmds_max); |
| 485 | void iser_free_fastreg_pool(struct iser_conn *ib_conn); | 485 | void iser_free_fastreg_pool(struct iser_conn *ib_conn); |
| 486 | u8 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 | |||
| 1157 | u8 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; | ||
| 1199 | err: | ||
| 1200 | /* Not alot we can do here, return ambiguous guard error */ | ||
| 1201 | return 0x1; | ||
| 1202 | } | ||
