target: Pass in transport supported PI at session initialization
authorNicholas Bellinger <nab@linux-iscsi.org>
Wed, 2 Apr 2014 19:52:38 +0000 (12:52 -0700)
committerNicholas Bellinger <nab@linux-iscsi.org>
Mon, 7 Apr 2014 08:48:54 +0000 (01:48 -0700)
In order to support local WRITE_INSERT + READ_STRIP operations for
non PI enabled fabrics, the fabric driver needs to be able signal
what protection offload operations are supported.

This is done at session initialization time so the modes can be
signaled by individual se_wwn + se_portal_group endpoints, as well
as optionally across different transports on the same endpoint.

For iser-target, set TARGET_PROT_ALL if the underlying ib_device
has already signaled PI offload support, and allow this to be
exposed via a new iscsit_transport->iscsit_get_sup_prot_ops()
callback.

For loopback, set TARGET_PROT_ALL to signal SCSI initiator mode
operation.

For all other drivers, set TARGET_PROT_NORMAL to disable fabric
level PI.

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>
14 files changed:
drivers/infiniband/ulp/isert/ib_isert.c
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/loopback/tcm_loop.c
drivers/target/sbp/sbp_target.c
drivers/target/target_core_transport.c
drivers/target/tcm_fc/tfc_sess.c
drivers/usb/gadget/tcm_usb_gadget.c
drivers/vhost/scsi.c
include/target/iscsi/iscsi_transport.h
include/target/target_core_base.h
include/target/target_core_fabric.h

index f5cc4affaeb4d573c506f9aec26c2968346d9140..c98fdb185931644bd3ed92d337f85aa0d2517149 100644 (file)
@@ -2196,6 +2196,18 @@ isert_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
        device->unreg_rdma_mem(isert_cmd, isert_conn);
 }
 
+static enum target_prot_op
+isert_get_sup_prot_ops(struct iscsi_conn *conn)
+{
+       struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
+       struct isert_device *device = isert_conn->conn_device;
+
+       if (device->pi_capable)
+               return TARGET_PROT_ALL;
+
+       return TARGET_PROT_NORMAL;
+}
+
 static int
 isert_put_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
                bool nopout_response)
@@ -3252,6 +3264,7 @@ static struct iscsit_transport iser_target_transport = {
        .iscsit_queue_data_in   = isert_put_datain,
        .iscsit_queue_status    = isert_put_response,
        .iscsit_aborted_task    = isert_aborted_task,
+       .iscsit_get_sup_prot_ops = isert_get_sup_prot_ops,
 };
 
 static int __init isert_init(void)
index f03aafdc3572e3fffb4c39a9385dcef2d511ccd5..bcfb398a6639ec480700a112f3ce3868a5b0dd6b 100644 (file)
@@ -2580,7 +2580,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
                goto destroy_ib;
        }
 
-       ch->sess = transport_init_session();
+       ch->sess = transport_init_session(TARGET_PROT_NORMAL);
        if (IS_ERR(ch->sess)) {
                rej->reason = __constant_cpu_to_be32(
                                SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
index b23a0ffe140ec4b9cf54b4ff8490aba4690148dc..68fb66fdb757fbc98784fad4ff7a5d03c49ee73d 100644 (file)
@@ -1482,7 +1482,7 @@ static int tcm_qla2xxx_check_initiator_node_acl(
        }
        se_tpg = &tpg->se_tpg;
 
-       se_sess = transport_init_session();
+       se_sess = transport_init_session(TARGET_PROT_NORMAL);
        if (IS_ERR(se_sess)) {
                pr_err("Unable to initialize struct se_session\n");
                return PTR_ERR(se_sess);
index 96aee439c9fdb60b91a17b23534861c43eb799e6..78cab13bbb1be3796b0e00af4a0667329ed4a2d8 100644 (file)
@@ -511,6 +511,11 @@ static void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
        __iscsit_free_cmd(cmd, scsi_cmd, true);
 }
 
+static enum target_prot_op iscsit_get_sup_prot_ops(struct iscsi_conn *conn)
+{
+       return TARGET_PROT_NORMAL;
+}
+
 static struct iscsit_transport iscsi_target_transport = {
        .name                   = "iSCSI/TCP",
        .transport_type         = ISCSI_TCP,
@@ -526,6 +531,7 @@ static struct iscsit_transport iscsi_target_transport = {
        .iscsit_queue_data_in   = iscsit_queue_rsp,
        .iscsit_queue_status    = iscsit_queue_rsp,
        .iscsit_aborted_task    = iscsit_aborted_task,
+       .iscsit_get_sup_prot_ops = iscsit_get_sup_prot_ops,
 };
 
 static int __init iscsi_target_init_module(void)
index e29279e6b577dd564e8271f95c171838ead5ca39..8739b98f6f93539b8c6eb95f27d7fde3601b40d7 100644 (file)
@@ -259,6 +259,7 @@ static int iscsi_login_zero_tsih_s1(
 {
        struct iscsi_session *sess = NULL;
        struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf;
+       enum target_prot_op sup_pro_ops;
        int ret;
 
        sess = kzalloc(sizeof(struct iscsi_session), GFP_KERNEL);
@@ -320,8 +321,9 @@ static int iscsi_login_zero_tsih_s1(
                kfree(sess);
                return -ENOMEM;
        }
+       sup_pro_ops = conn->conn_transport->iscsit_get_sup_prot_ops(conn);
 
-       sess->se_sess = transport_init_session();
+       sess->se_sess = transport_init_session(sup_pro_ops);
        if (IS_ERR(sess->se_sess)) {
                iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
                                ISCSI_LOGIN_STATUS_NO_RESOURCES);
index bdc1ad82d2938b13588b20410eeee7dfb4f9e81c..c886ad1c39fb357ddb6e72a384474bdc89b01278 100644 (file)
@@ -1018,7 +1018,7 @@ static int tcm_loop_make_nexus(
        /*
         * Initialize the struct se_session pointer
         */
-       tl_nexus->se_sess = transport_init_session();
+       tl_nexus->se_sess = transport_init_session(TARGET_PROT_ALL);
        if (IS_ERR(tl_nexus->se_sess)) {
                ret = PTR_ERR(tl_nexus->se_sess);
                goto out;
index ad04ea928e4fb1b9400b354a9a8c4a441a38cc58..e7e93727553cef8d3503201f381bd64b3f02d6b3 100644 (file)
@@ -210,7 +210,7 @@ static struct sbp_session *sbp_session_create(
                return ERR_PTR(-ENOMEM);
        }
 
-       sess->se_sess = transport_init_session();
+       sess->se_sess = transport_init_session(TARGET_PROT_NORMAL);
        if (IS_ERR(sess->se_sess)) {
                pr_err("failed to init se_session\n");
 
index 9393544fb471cb22171a49d4193135648e66519b..9c820ba5ae8236e71387a090d6965d9070cd421d 100644 (file)
@@ -235,7 +235,7 @@ void transport_subsystem_check_init(void)
        sub_api_initialized = 1;
 }
 
-struct se_session *transport_init_session(void)
+struct se_session *transport_init_session(enum target_prot_op sup_prot_ops)
 {
        struct se_session *se_sess;
 
@@ -251,6 +251,7 @@ struct se_session *transport_init_session(void)
        INIT_LIST_HEAD(&se_sess->sess_wait_list);
        spin_lock_init(&se_sess->sess_cmd_lock);
        kref_init(&se_sess->sess_kref);
+       se_sess->sup_prot_ops = sup_prot_ops;
 
        return se_sess;
 }
@@ -288,12 +289,13 @@ int transport_alloc_session_tags(struct se_session *se_sess,
 EXPORT_SYMBOL(transport_alloc_session_tags);
 
 struct se_session *transport_init_session_tags(unsigned int tag_num,
-                                              unsigned int tag_size)
+                                              unsigned int tag_size,
+                                              enum target_prot_op sup_prot_ops)
 {
        struct se_session *se_sess;
        int rc;
 
-       se_sess = transport_init_session();
+       se_sess = transport_init_session(sup_prot_ops);
        if (IS_ERR(se_sess))
                return se_sess;
 
index ae52c08dad09071114e730c44b142f49bde1924e..04751422178c2d3a8016ecf8ca7241ed97b495c7 100644 (file)
@@ -211,7 +211,8 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id,
                return NULL;
 
        sess->se_sess = transport_init_session_tags(TCM_FC_DEFAULT_TAGS,
-                                                   sizeof(struct ft_cmd));
+                                                   sizeof(struct ft_cmd),
+                                                   TARGET_PROT_NORMAL);
        if (IS_ERR(sess->se_sess)) {
                kfree(sess);
                return NULL;
index f9afa4a4ec3c9bec744333f0e8646b5ba4b77771..f34b6df3572b7bda3d42eddc6a99305805a4a74f 100644 (file)
@@ -1731,7 +1731,7 @@ static int tcm_usbg_make_nexus(struct usbg_tpg *tpg, char *name)
                pr_err("Unable to allocate struct tcm_vhost_nexus\n");
                goto err_unlock;
        }
-       tv_nexus->tvn_se_sess = transport_init_session();
+       tv_nexus->tvn_se_sess = transport_init_session(TARGET_PROT_NORMAL);
        if (IS_ERR(tv_nexus->tvn_se_sess))
                goto err_free;
 
index 4a473355020f16af894a67fdc556ed0f16e5a10f..cf50ce93975bcddb240c3356b4326aac0fc8c3cb 100644 (file)
@@ -1745,7 +1745,8 @@ static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tpg,
         */
        tv_nexus->tvn_se_sess = transport_init_session_tags(
                                        TCM_VHOST_DEFAULT_TAGS,
-                                       sizeof(struct tcm_vhost_cmd));
+                                       sizeof(struct tcm_vhost_cmd),
+                                       TARGET_PROT_NORMAL);
        if (IS_ERR(tv_nexus->tvn_se_sess)) {
                mutex_unlock(&tpg->tv_tpg_mutex);
                kfree(tv_nexus);
index 8d19339292b829458897d1830c586d699df2892d..33b487b5da92dc76f549df5d09a3852518c14159 100644 (file)
@@ -22,6 +22,7 @@ struct iscsit_transport {
        int (*iscsit_queue_data_in)(struct iscsi_conn *, struct iscsi_cmd *);
        int (*iscsit_queue_status)(struct iscsi_conn *, struct iscsi_cmd *);
        void (*iscsit_aborted_task)(struct iscsi_conn *, struct iscsi_cmd *);
+       enum target_prot_op (*iscsit_get_sup_prot_ops)(struct iscsi_conn *);
 };
 
 static inline void *iscsit_priv_cmd(struct iscsi_cmd *cmd)
index ec3e3a3ff4f6e3d4fc0310a584f98c03cddc0558..9ec9864ecf38629469ef0823baf153c33fb09472 100644 (file)
@@ -442,15 +442,19 @@ struct se_tmr_req {
 };
 
 enum target_prot_op {
-       TARGET_PROT_NORMAL = 0,
-       TARGET_PROT_DIN_INSERT,
-       TARGET_PROT_DOUT_INSERT,
-       TARGET_PROT_DIN_STRIP,
-       TARGET_PROT_DOUT_STRIP,
-       TARGET_PROT_DIN_PASS,
-       TARGET_PROT_DOUT_PASS,
+       TARGET_PROT_NORMAL      = 0,
+       TARGET_PROT_DIN_INSERT  = (1 << 0),
+       TARGET_PROT_DOUT_INSERT = (1 << 1),
+       TARGET_PROT_DIN_STRIP   = (1 << 2),
+       TARGET_PROT_DOUT_STRIP  = (1 << 3),
+       TARGET_PROT_DIN_PASS    = (1 << 4),
+       TARGET_PROT_DOUT_PASS   = (1 << 5),
 };
 
+#define TARGET_PROT_ALL        TARGET_PROT_DIN_INSERT | TARGET_PROT_DOUT_INSERT | \
+                       TARGET_PROT_DIN_STRIP | TARGET_PROT_DOUT_STRIP | \
+                       TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS
+
 enum target_prot_type {
        TARGET_DIF_TYPE0_PROT,
        TARGET_DIF_TYPE1_PROT,
@@ -605,6 +609,7 @@ struct se_node_acl {
 struct se_session {
        unsigned                sess_tearing_down:1;
        u64                     sess_bin_isid;
+       enum target_prot_op     sup_prot_ops;
        struct se_node_acl      *se_node_acl;
        struct se_portal_group *se_tpg;
        void                    *fabric_sess_ptr;
index 1d1043644b9b827e5f3199a6cd407d724ba371ee..22a4e98eec807ecaa93a735ad63fd05ef26809a9 100644 (file)
@@ -84,10 +84,11 @@ struct target_core_fabric_ops {
        void (*fabric_drop_nodeacl)(struct se_node_acl *);
 };
 
-struct se_session *transport_init_session(void);
+struct se_session *transport_init_session(enum target_prot_op);
 int transport_alloc_session_tags(struct se_session *, unsigned int,
                unsigned int);
-struct se_session *transport_init_session_tags(unsigned int, unsigned int);
+struct se_session *transport_init_session_tags(unsigned int, unsigned int,
+               enum target_prot_op);
 void   __transport_register_session(struct se_portal_group *,
                struct se_node_acl *, struct se_session *, void *);
 void   transport_register_session(struct se_portal_group *,