]> git.karo-electronics.de Git - linux-beck.git/commitdiff
IB/iser: Implement check_protection
authorSagi Grimberg <sagig@mellanox.com>
Wed, 5 Mar 2014 17:43:50 +0000 (19:43 +0200)
committerRoland Dreier <roland@purestorage.com>
Tue, 18 Mar 2014 05:33:58 +0000 (22:33 -0700)
Once the iSCSI transaction is completed we must implement
check_protection in order to notify on DIF errors that may have
occured.

The routine boils down to calling ib_check_mr_status to get the
signature status of the transaction.

Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Alex Tabachnik <alext@mellanox.com>
Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
drivers/infiniband/ulp/iser/iscsi_iser.c
drivers/infiniband/ulp/iser/iscsi_iser.h
drivers/infiniband/ulp/iser/iser_verbs.c

index a64b87811915707b4280d17f8bf16092011611f1..f13d7e9801f1980b107c52aed0c17894161916c5 100644 (file)
@@ -306,6 +306,18 @@ static void iscsi_iser_cleanup_task(struct iscsi_task *task)
        }
 }
 
+static u8 iscsi_iser_check_protection(struct iscsi_task *task, sector_t *sector)
+{
+       struct iscsi_iser_task *iser_task = task->dd_data;
+
+       if (iser_task->dir[ISER_DIR_IN])
+               return iser_check_task_pi_status(iser_task, ISER_DIR_IN,
+                                                sector);
+       else
+               return iser_check_task_pi_status(iser_task, ISER_DIR_OUT,
+                                                sector);
+}
+
 static struct iscsi_cls_conn *
 iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
 {
@@ -742,6 +754,7 @@ static struct iscsi_transport iscsi_iser_transport = {
        .xmit_task              = iscsi_iser_task_xmit,
        .cleanup_task           = iscsi_iser_cleanup_task,
        .alloc_pdu              = iscsi_iser_pdu_alloc,
+       .check_protection       = iscsi_iser_check_protection,
        /* recovery */
        .session_recovery_timedout = iscsi_session_recovery_timedout,
 
index fce54092d30058e206e5041fd9bff60559713608..95f291fca17886ddf2a26360ef1d844c9cfd417a 100644 (file)
@@ -483,4 +483,6 @@ int iser_create_fmr_pool(struct iser_conn *ib_conn, unsigned cmds_max);
 void iser_free_fmr_pool(struct iser_conn *ib_conn);
 int iser_create_fastreg_pool(struct iser_conn *ib_conn, unsigned cmds_max);
 void iser_free_fastreg_pool(struct iser_conn *ib_conn);
+u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task,
+                            enum iser_data_dir cmd_dir, sector_t *sector);
 #endif
index 0404c71761f9f245f57c0c949d6115962395bdff..abbb6ec90d143f628d17f7e38836861db479066c 100644 (file)
@@ -1153,3 +1153,50 @@ static void iser_cq_callback(struct ib_cq *cq, void *cq_context)
 
        tasklet_schedule(&device->cq_tasklet[cq_index]);
 }
+
+u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task,
+                            enum iser_data_dir cmd_dir, sector_t *sector)
+{
+       struct iser_mem_reg *reg = &iser_task->rdma_regd[cmd_dir].reg;
+       struct fast_reg_descriptor *desc = reg->mem_h;
+       unsigned long sector_size = iser_task->sc->device->sector_size;
+       struct ib_mr_status mr_status;
+       int ret;
+
+       if (desc && desc->reg_indicators & ISER_FASTREG_PROTECTED) {
+               desc->reg_indicators &= ~ISER_FASTREG_PROTECTED;
+               ret = ib_check_mr_status(desc->pi_ctx->sig_mr,
+                                        IB_MR_CHECK_SIG_STATUS, &mr_status);
+               if (ret) {
+                       pr_err("ib_check_mr_status failed, ret %d\n", ret);
+                       goto err;
+               }
+
+               if (mr_status.fail_status & IB_MR_CHECK_SIG_STATUS) {
+                       sector_t sector_off = mr_status.sig_err.sig_err_offset;
+
+                       do_div(sector_off, sector_size + 8);
+                       *sector = scsi_get_lba(iser_task->sc) + sector_off;
+
+                       pr_err("PI error found type %d at sector %lx "
+                              "expected %x vs actual %x\n",
+                              mr_status.sig_err.err_type, *sector,
+                              mr_status.sig_err.expected,
+                              mr_status.sig_err.actual);
+
+                       switch (mr_status.sig_err.err_type) {
+                       case IB_SIG_BAD_GUARD:
+                               return 0x1;
+                       case IB_SIG_BAD_REFTAG:
+                               return 0x3;
+                       case IB_SIG_BAD_APPTAG:
+                               return 0x2;
+                       }
+               }
+       }
+
+       return 0;
+err:
+       /* Not alot we can do here, return ambiguous guard error */
+       return 0x1;
+}