aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2014-04-02 15:52:38 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2014-04-07 04:48:54 -0400
commite70beee783d6977d80eede88a3394f02eabddad1 (patch)
tree225d10e36bf031e9c4eab3de537699b60bb48f1b
parentd84287bcfe624697cd4f3c1df746beb53b86d9c4 (diff)
target: Pass in transport supported PI at session initialization
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>
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.c13
-rw-r--r--drivers/infiniband/ulp/srpt/ib_srpt.c2
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.c2
-rw-r--r--drivers/target/iscsi/iscsi_target.c6
-rw-r--r--drivers/target/iscsi/iscsi_target_login.c4
-rw-r--r--drivers/target/loopback/tcm_loop.c2
-rw-r--r--drivers/target/sbp/sbp_target.c2
-rw-r--r--drivers/target/target_core_transport.c8
-rw-r--r--drivers/target/tcm_fc/tfc_sess.c3
-rw-r--r--drivers/usb/gadget/tcm_usb_gadget.c2
-rw-r--r--drivers/vhost/scsi.c3
-rw-r--r--include/target/iscsi/iscsi_transport.h1
-rw-r--r--include/target/target_core_base.h19
-rw-r--r--include/target/target_core_fabric.h5
14 files changed, 52 insertions, 20 deletions
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index f5cc4affaeb4..c98fdb185931 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -2196,6 +2196,18 @@ isert_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
2196 device->unreg_rdma_mem(isert_cmd, isert_conn); 2196 device->unreg_rdma_mem(isert_cmd, isert_conn);
2197} 2197}
2198 2198
2199static enum target_prot_op
2200isert_get_sup_prot_ops(struct iscsi_conn *conn)
2201{
2202 struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
2203 struct isert_device *device = isert_conn->conn_device;
2204
2205 if (device->pi_capable)
2206 return TARGET_PROT_ALL;
2207
2208 return TARGET_PROT_NORMAL;
2209}
2210
2199static int 2211static int
2200isert_put_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn, 2212isert_put_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
2201 bool nopout_response) 2213 bool nopout_response)
@@ -3252,6 +3264,7 @@ static struct iscsit_transport iser_target_transport = {
3252 .iscsit_queue_data_in = isert_put_datain, 3264 .iscsit_queue_data_in = isert_put_datain,
3253 .iscsit_queue_status = isert_put_response, 3265 .iscsit_queue_status = isert_put_response,
3254 .iscsit_aborted_task = isert_aborted_task, 3266 .iscsit_aborted_task = isert_aborted_task,
3267 .iscsit_get_sup_prot_ops = isert_get_sup_prot_ops,
3255}; 3268};
3256 3269
3257static int __init isert_init(void) 3270static int __init isert_init(void)
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index f03aafdc3572..bcfb398a6639 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -2580,7 +2580,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
2580 goto destroy_ib; 2580 goto destroy_ib;
2581 } 2581 }
2582 2582
2583 ch->sess = transport_init_session(); 2583 ch->sess = transport_init_session(TARGET_PROT_NORMAL);
2584 if (IS_ERR(ch->sess)) { 2584 if (IS_ERR(ch->sess)) {
2585 rej->reason = __constant_cpu_to_be32( 2585 rej->reason = __constant_cpu_to_be32(
2586 SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); 2586 SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index b23a0ffe140e..68fb66fdb757 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -1482,7 +1482,7 @@ static int tcm_qla2xxx_check_initiator_node_acl(
1482 } 1482 }
1483 se_tpg = &tpg->se_tpg; 1483 se_tpg = &tpg->se_tpg;
1484 1484
1485 se_sess = transport_init_session(); 1485 se_sess = transport_init_session(TARGET_PROT_NORMAL);
1486 if (IS_ERR(se_sess)) { 1486 if (IS_ERR(se_sess)) {
1487 pr_err("Unable to initialize struct se_session\n"); 1487 pr_err("Unable to initialize struct se_session\n");
1488 return PTR_ERR(se_sess); 1488 return PTR_ERR(se_sess);
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 96aee439c9fd..78cab13bbb1b 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -511,6 +511,11 @@ static void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
511 __iscsit_free_cmd(cmd, scsi_cmd, true); 511 __iscsit_free_cmd(cmd, scsi_cmd, true);
512} 512}
513 513
514static enum target_prot_op iscsit_get_sup_prot_ops(struct iscsi_conn *conn)
515{
516 return TARGET_PROT_NORMAL;
517}
518
514static struct iscsit_transport iscsi_target_transport = { 519static struct iscsit_transport iscsi_target_transport = {
515 .name = "iSCSI/TCP", 520 .name = "iSCSI/TCP",
516 .transport_type = ISCSI_TCP, 521 .transport_type = ISCSI_TCP,
@@ -526,6 +531,7 @@ static struct iscsit_transport iscsi_target_transport = {
526 .iscsit_queue_data_in = iscsit_queue_rsp, 531 .iscsit_queue_data_in = iscsit_queue_rsp,
527 .iscsit_queue_status = iscsit_queue_rsp, 532 .iscsit_queue_status = iscsit_queue_rsp,
528 .iscsit_aborted_task = iscsit_aborted_task, 533 .iscsit_aborted_task = iscsit_aborted_task,
534 .iscsit_get_sup_prot_ops = iscsit_get_sup_prot_ops,
529}; 535};
530 536
531static int __init iscsi_target_init_module(void) 537static int __init iscsi_target_init_module(void)
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index e29279e6b577..8739b98f6f93 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -259,6 +259,7 @@ static int iscsi_login_zero_tsih_s1(
259{ 259{
260 struct iscsi_session *sess = NULL; 260 struct iscsi_session *sess = NULL;
261 struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf; 261 struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf;
262 enum target_prot_op sup_pro_ops;
262 int ret; 263 int ret;
263 264
264 sess = kzalloc(sizeof(struct iscsi_session), GFP_KERNEL); 265 sess = kzalloc(sizeof(struct iscsi_session), GFP_KERNEL);
@@ -320,8 +321,9 @@ static int iscsi_login_zero_tsih_s1(
320 kfree(sess); 321 kfree(sess);
321 return -ENOMEM; 322 return -ENOMEM;
322 } 323 }
324 sup_pro_ops = conn->conn_transport->iscsit_get_sup_prot_ops(conn);
323 325
324 sess->se_sess = transport_init_session(); 326 sess->se_sess = transport_init_session(sup_pro_ops);
325 if (IS_ERR(sess->se_sess)) { 327 if (IS_ERR(sess->se_sess)) {
326 iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, 328 iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
327 ISCSI_LOGIN_STATUS_NO_RESOURCES); 329 ISCSI_LOGIN_STATUS_NO_RESOURCES);
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index bdc1ad82d293..c886ad1c39fb 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -1018,7 +1018,7 @@ static int tcm_loop_make_nexus(
1018 /* 1018 /*
1019 * Initialize the struct se_session pointer 1019 * Initialize the struct se_session pointer
1020 */ 1020 */
1021 tl_nexus->se_sess = transport_init_session(); 1021 tl_nexus->se_sess = transport_init_session(TARGET_PROT_ALL);
1022 if (IS_ERR(tl_nexus->se_sess)) { 1022 if (IS_ERR(tl_nexus->se_sess)) {
1023 ret = PTR_ERR(tl_nexus->se_sess); 1023 ret = PTR_ERR(tl_nexus->se_sess);
1024 goto out; 1024 goto out;
diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c
index ad04ea928e4f..e7e93727553c 100644
--- a/drivers/target/sbp/sbp_target.c
+++ b/drivers/target/sbp/sbp_target.c
@@ -210,7 +210,7 @@ static struct sbp_session *sbp_session_create(
210 return ERR_PTR(-ENOMEM); 210 return ERR_PTR(-ENOMEM);
211 } 211 }
212 212
213 sess->se_sess = transport_init_session(); 213 sess->se_sess = transport_init_session(TARGET_PROT_NORMAL);
214 if (IS_ERR(sess->se_sess)) { 214 if (IS_ERR(sess->se_sess)) {
215 pr_err("failed to init se_session\n"); 215 pr_err("failed to init se_session\n");
216 216
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 9393544fb471..9c820ba5ae82 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -235,7 +235,7 @@ void transport_subsystem_check_init(void)
235 sub_api_initialized = 1; 235 sub_api_initialized = 1;
236} 236}
237 237
238struct se_session *transport_init_session(void) 238struct se_session *transport_init_session(enum target_prot_op sup_prot_ops)
239{ 239{
240 struct se_session *se_sess; 240 struct se_session *se_sess;
241 241
@@ -251,6 +251,7 @@ struct se_session *transport_init_session(void)
251 INIT_LIST_HEAD(&se_sess->sess_wait_list); 251 INIT_LIST_HEAD(&se_sess->sess_wait_list);
252 spin_lock_init(&se_sess->sess_cmd_lock); 252 spin_lock_init(&se_sess->sess_cmd_lock);
253 kref_init(&se_sess->sess_kref); 253 kref_init(&se_sess->sess_kref);
254 se_sess->sup_prot_ops = sup_prot_ops;
254 255
255 return se_sess; 256 return se_sess;
256} 257}
@@ -288,12 +289,13 @@ int transport_alloc_session_tags(struct se_session *se_sess,
288EXPORT_SYMBOL(transport_alloc_session_tags); 289EXPORT_SYMBOL(transport_alloc_session_tags);
289 290
290struct se_session *transport_init_session_tags(unsigned int tag_num, 291struct se_session *transport_init_session_tags(unsigned int tag_num,
291 unsigned int tag_size) 292 unsigned int tag_size,
293 enum target_prot_op sup_prot_ops)
292{ 294{
293 struct se_session *se_sess; 295 struct se_session *se_sess;
294 int rc; 296 int rc;
295 297
296 se_sess = transport_init_session(); 298 se_sess = transport_init_session(sup_prot_ops);
297 if (IS_ERR(se_sess)) 299 if (IS_ERR(se_sess))
298 return se_sess; 300 return se_sess;
299 301
diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c
index ae52c08dad09..04751422178c 100644
--- a/drivers/target/tcm_fc/tfc_sess.c
+++ b/drivers/target/tcm_fc/tfc_sess.c
@@ -211,7 +211,8 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id,
211 return NULL; 211 return NULL;
212 212
213 sess->se_sess = transport_init_session_tags(TCM_FC_DEFAULT_TAGS, 213 sess->se_sess = transport_init_session_tags(TCM_FC_DEFAULT_TAGS,
214 sizeof(struct ft_cmd)); 214 sizeof(struct ft_cmd),
215 TARGET_PROT_NORMAL);
215 if (IS_ERR(sess->se_sess)) { 216 if (IS_ERR(sess->se_sess)) {
216 kfree(sess); 217 kfree(sess);
217 return NULL; 218 return NULL;
diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c
index f9afa4a4ec3c..f34b6df3572b 100644
--- a/drivers/usb/gadget/tcm_usb_gadget.c
+++ b/drivers/usb/gadget/tcm_usb_gadget.c
@@ -1731,7 +1731,7 @@ static int tcm_usbg_make_nexus(struct usbg_tpg *tpg, char *name)
1731 pr_err("Unable to allocate struct tcm_vhost_nexus\n"); 1731 pr_err("Unable to allocate struct tcm_vhost_nexus\n");
1732 goto err_unlock; 1732 goto err_unlock;
1733 } 1733 }
1734 tv_nexus->tvn_se_sess = transport_init_session(); 1734 tv_nexus->tvn_se_sess = transport_init_session(TARGET_PROT_NORMAL);
1735 if (IS_ERR(tv_nexus->tvn_se_sess)) 1735 if (IS_ERR(tv_nexus->tvn_se_sess))
1736 goto err_free; 1736 goto err_free;
1737 1737
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 4a473355020f..cf50ce93975b 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -1745,7 +1745,8 @@ static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tpg,
1745 */ 1745 */
1746 tv_nexus->tvn_se_sess = transport_init_session_tags( 1746 tv_nexus->tvn_se_sess = transport_init_session_tags(
1747 TCM_VHOST_DEFAULT_TAGS, 1747 TCM_VHOST_DEFAULT_TAGS,
1748 sizeof(struct tcm_vhost_cmd)); 1748 sizeof(struct tcm_vhost_cmd),
1749 TARGET_PROT_NORMAL);
1749 if (IS_ERR(tv_nexus->tvn_se_sess)) { 1750 if (IS_ERR(tv_nexus->tvn_se_sess)) {
1750 mutex_unlock(&tpg->tv_tpg_mutex); 1751 mutex_unlock(&tpg->tv_tpg_mutex);
1751 kfree(tv_nexus); 1752 kfree(tv_nexus);
diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h
index 8d19339292b8..33b487b5da92 100644
--- a/include/target/iscsi/iscsi_transport.h
+++ b/include/target/iscsi/iscsi_transport.h
@@ -22,6 +22,7 @@ struct iscsit_transport {
22 int (*iscsit_queue_data_in)(struct iscsi_conn *, struct iscsi_cmd *); 22 int (*iscsit_queue_data_in)(struct iscsi_conn *, struct iscsi_cmd *);
23 int (*iscsit_queue_status)(struct iscsi_conn *, struct iscsi_cmd *); 23 int (*iscsit_queue_status)(struct iscsi_conn *, struct iscsi_cmd *);
24 void (*iscsit_aborted_task)(struct iscsi_conn *, struct iscsi_cmd *); 24 void (*iscsit_aborted_task)(struct iscsi_conn *, struct iscsi_cmd *);
25 enum target_prot_op (*iscsit_get_sup_prot_ops)(struct iscsi_conn *);
25}; 26};
26 27
27static inline void *iscsit_priv_cmd(struct iscsi_cmd *cmd) 28static inline void *iscsit_priv_cmd(struct iscsi_cmd *cmd)
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index ec3e3a3ff4f6..9ec9864ecf38 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -442,15 +442,19 @@ struct se_tmr_req {
442}; 442};
443 443
444enum target_prot_op { 444enum target_prot_op {
445 TARGET_PROT_NORMAL = 0, 445 TARGET_PROT_NORMAL = 0,
446 TARGET_PROT_DIN_INSERT, 446 TARGET_PROT_DIN_INSERT = (1 << 0),
447 TARGET_PROT_DOUT_INSERT, 447 TARGET_PROT_DOUT_INSERT = (1 << 1),
448 TARGET_PROT_DIN_STRIP, 448 TARGET_PROT_DIN_STRIP = (1 << 2),
449 TARGET_PROT_DOUT_STRIP, 449 TARGET_PROT_DOUT_STRIP = (1 << 3),
450 TARGET_PROT_DIN_PASS, 450 TARGET_PROT_DIN_PASS = (1 << 4),
451 TARGET_PROT_DOUT_PASS, 451 TARGET_PROT_DOUT_PASS = (1 << 5),
452}; 452};
453 453
454#define TARGET_PROT_ALL TARGET_PROT_DIN_INSERT | TARGET_PROT_DOUT_INSERT | \
455 TARGET_PROT_DIN_STRIP | TARGET_PROT_DOUT_STRIP | \
456 TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS
457
454enum target_prot_type { 458enum target_prot_type {
455 TARGET_DIF_TYPE0_PROT, 459 TARGET_DIF_TYPE0_PROT,
456 TARGET_DIF_TYPE1_PROT, 460 TARGET_DIF_TYPE1_PROT,
@@ -605,6 +609,7 @@ struct se_node_acl {
605struct se_session { 609struct se_session {
606 unsigned sess_tearing_down:1; 610 unsigned sess_tearing_down:1;
607 u64 sess_bin_isid; 611 u64 sess_bin_isid;
612 enum target_prot_op sup_prot_ops;
608 struct se_node_acl *se_node_acl; 613 struct se_node_acl *se_node_acl;
609 struct se_portal_group *se_tpg; 614 struct se_portal_group *se_tpg;
610 void *fabric_sess_ptr; 615 void *fabric_sess_ptr;
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
index 1d1043644b9b..22a4e98eec80 100644
--- a/include/target/target_core_fabric.h
+++ b/include/target/target_core_fabric.h
@@ -84,10 +84,11 @@ struct target_core_fabric_ops {
84 void (*fabric_drop_nodeacl)(struct se_node_acl *); 84 void (*fabric_drop_nodeacl)(struct se_node_acl *);
85}; 85};
86 86
87struct se_session *transport_init_session(void); 87struct se_session *transport_init_session(enum target_prot_op);
88int transport_alloc_session_tags(struct se_session *, unsigned int, 88int transport_alloc_session_tags(struct se_session *, unsigned int,
89 unsigned int); 89 unsigned int);
90struct se_session *transport_init_session_tags(unsigned int, unsigned int); 90struct se_session *transport_init_session_tags(unsigned int, unsigned int,
91 enum target_prot_op);
91void __transport_register_session(struct se_portal_group *, 92void __transport_register_session(struct se_portal_group *,
92 struct se_node_acl *, struct se_session *, void *); 93 struct se_node_acl *, struct se_session *, void *);
93void transport_register_session(struct se_portal_group *, 94void transport_register_session(struct se_portal_group *,