aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/ulp/iser/iscsi_iser.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/ulp/iser/iscsi_iser.c')
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c105
1 files changed, 61 insertions, 44 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 25f195ef44b0..eb7973957a6e 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -99,6 +99,7 @@ MODULE_PARM_DESC(pi_enable, "Enable T10-PI offload support (default:disabled)");
99module_param_named(pi_guard, iser_pi_guard, int, 0644); 99module_param_named(pi_guard, iser_pi_guard, int, 0644);
100MODULE_PARM_DESC(pi_guard, "T10-PI guard_type, 0:CRC|1:IP_CSUM (default:CRC)"); 100MODULE_PARM_DESC(pi_guard, "T10-PI guard_type, 0:CRC|1:IP_CSUM (default:CRC)");
101 101
102static struct workqueue_struct *release_wq;
102struct iser_global ig; 103struct iser_global ig;
103 104
104void 105void
@@ -337,24 +338,6 @@ iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
337 return cls_conn; 338 return cls_conn;
338} 339}
339 340
340static void
341iscsi_iser_conn_destroy(struct iscsi_cls_conn *cls_conn)
342{
343 struct iscsi_conn *conn = cls_conn->dd_data;
344 struct iser_conn *ib_conn = conn->dd_data;
345
346 iscsi_conn_teardown(cls_conn);
347 /*
348 * Userspace will normally call the stop callback and
349 * already have freed the ib_conn, but if it goofed up then
350 * we free it here.
351 */
352 if (ib_conn) {
353 ib_conn->iscsi_conn = NULL;
354 iser_conn_put(ib_conn, 1); /* deref iscsi/ib conn unbinding */
355 }
356}
357
358static int 341static int
359iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session, 342iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session,
360 struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, 343 struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
@@ -392,29 +375,39 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session,
392 conn->dd_data = ib_conn; 375 conn->dd_data = ib_conn;
393 ib_conn->iscsi_conn = conn; 376 ib_conn->iscsi_conn = conn;
394 377
395 iser_conn_get(ib_conn); /* ref iscsi/ib conn binding */
396 return 0; 378 return 0;
397} 379}
398 380
381static int
382iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn)
383{
384 struct iscsi_conn *iscsi_conn;
385 struct iser_conn *ib_conn;
386
387 iscsi_conn = cls_conn->dd_data;
388 ib_conn = iscsi_conn->dd_data;
389 reinit_completion(&ib_conn->stop_completion);
390
391 return iscsi_conn_start(cls_conn);
392}
393
399static void 394static void
400iscsi_iser_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) 395iscsi_iser_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
401{ 396{
402 struct iscsi_conn *conn = cls_conn->dd_data; 397 struct iscsi_conn *conn = cls_conn->dd_data;
403 struct iser_conn *ib_conn = conn->dd_data; 398 struct iser_conn *ib_conn = conn->dd_data;
404 399
400 iser_dbg("stopping iscsi_conn: %p, ib_conn: %p\n", conn, ib_conn);
401 iscsi_conn_stop(cls_conn, flag);
402
405 /* 403 /*
406 * Userspace may have goofed up and not bound the connection or 404 * Userspace may have goofed up and not bound the connection or
407 * might have only partially setup the connection. 405 * might have only partially setup the connection.
408 */ 406 */
409 if (ib_conn) { 407 if (ib_conn) {
410 iscsi_conn_stop(cls_conn, flag); 408 conn->dd_data = NULL;
411 /* 409 complete(&ib_conn->stop_completion);
412 * There is no unbind event so the stop callback
413 * must release the ref from the bind.
414 */
415 iser_conn_put(ib_conn, 1); /* deref iscsi/ib conn unbinding */
416 } 410 }
417 conn->dd_data = NULL;
418} 411}
419 412
420static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session) 413static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session)
@@ -515,28 +508,28 @@ iscsi_iser_set_param(struct iscsi_cls_conn *cls_conn,
515 case ISCSI_PARAM_HDRDGST_EN: 508 case ISCSI_PARAM_HDRDGST_EN:
516 sscanf(buf, "%d", &value); 509 sscanf(buf, "%d", &value);
517 if (value) { 510 if (value) {
518 iser_err("DataDigest wasn't negotiated to None"); 511 iser_err("DataDigest wasn't negotiated to None\n");
519 return -EPROTO; 512 return -EPROTO;
520 } 513 }
521 break; 514 break;
522 case ISCSI_PARAM_DATADGST_EN: 515 case ISCSI_PARAM_DATADGST_EN:
523 sscanf(buf, "%d", &value); 516 sscanf(buf, "%d", &value);
524 if (value) { 517 if (value) {
525 iser_err("DataDigest wasn't negotiated to None"); 518 iser_err("DataDigest wasn't negotiated to None\n");
526 return -EPROTO; 519 return -EPROTO;
527 } 520 }
528 break; 521 break;
529 case ISCSI_PARAM_IFMARKER_EN: 522 case ISCSI_PARAM_IFMARKER_EN:
530 sscanf(buf, "%d", &value); 523 sscanf(buf, "%d", &value);
531 if (value) { 524 if (value) {
532 iser_err("IFMarker wasn't negotiated to No"); 525 iser_err("IFMarker wasn't negotiated to No\n");
533 return -EPROTO; 526 return -EPROTO;
534 } 527 }
535 break; 528 break;
536 case ISCSI_PARAM_OFMARKER_EN: 529 case ISCSI_PARAM_OFMARKER_EN:
537 sscanf(buf, "%d", &value); 530 sscanf(buf, "%d", &value);
538 if (value) { 531 if (value) {
539 iser_err("OFMarker wasn't negotiated to No"); 532 iser_err("OFMarker wasn't negotiated to No\n");
540 return -EPROTO; 533 return -EPROTO;
541 } 534 }
542 break; 535 break;
@@ -652,19 +645,20 @@ iscsi_iser_ep_disconnect(struct iscsi_endpoint *ep)
652 struct iser_conn *ib_conn; 645 struct iser_conn *ib_conn;
653 646
654 ib_conn = ep->dd_data; 647 ib_conn = ep->dd_data;
655 if (ib_conn->iscsi_conn) 648 iser_info("ep %p ib conn %p state %d\n", ep, ib_conn, ib_conn->state);
656 /*
657 * Must suspend xmit path if the ep is bound to the
658 * iscsi_conn, so we know we are not accessing the ib_conn
659 * when we free it.
660 *
661 * This may not be bound if the ep poll failed.
662 */
663 iscsi_suspend_tx(ib_conn->iscsi_conn);
664
665
666 iser_info("ib conn %p state %d\n", ib_conn, ib_conn->state);
667 iser_conn_terminate(ib_conn); 649 iser_conn_terminate(ib_conn);
650
651 /*
652 * if iser_conn and iscsi_conn are bound, we must wait iscsi_conn_stop
653 * call and ISER_CONN_DOWN state before freeing the iser resources.
654 * otherwise we are safe to free resources immediately.
655 */
656 if (ib_conn->iscsi_conn) {
657 INIT_WORK(&ib_conn->release_work, iser_release_work);
658 queue_work(release_wq, &ib_conn->release_work);
659 } else {
660 iser_conn_release(ib_conn);
661 }
668} 662}
669 663
670static umode_t iser_attr_is_visible(int param_type, int param) 664static umode_t iser_attr_is_visible(int param_type, int param)
@@ -748,13 +742,13 @@ static struct iscsi_transport iscsi_iser_transport = {
748 /* connection management */ 742 /* connection management */
749 .create_conn = iscsi_iser_conn_create, 743 .create_conn = iscsi_iser_conn_create,
750 .bind_conn = iscsi_iser_conn_bind, 744 .bind_conn = iscsi_iser_conn_bind,
751 .destroy_conn = iscsi_iser_conn_destroy, 745 .destroy_conn = iscsi_conn_teardown,
752 .attr_is_visible = iser_attr_is_visible, 746 .attr_is_visible = iser_attr_is_visible,
753 .set_param = iscsi_iser_set_param, 747 .set_param = iscsi_iser_set_param,
754 .get_conn_param = iscsi_conn_get_param, 748 .get_conn_param = iscsi_conn_get_param,
755 .get_ep_param = iscsi_iser_get_ep_param, 749 .get_ep_param = iscsi_iser_get_ep_param,
756 .get_session_param = iscsi_session_get_param, 750 .get_session_param = iscsi_session_get_param,
757 .start_conn = iscsi_conn_start, 751 .start_conn = iscsi_iser_conn_start,
758 .stop_conn = iscsi_iser_conn_stop, 752 .stop_conn = iscsi_iser_conn_stop,
759 /* iscsi host params */ 753 /* iscsi host params */
760 .get_host_param = iscsi_host_get_param, 754 .get_host_param = iscsi_host_get_param,
@@ -801,6 +795,12 @@ static int __init iser_init(void)
801 mutex_init(&ig.connlist_mutex); 795 mutex_init(&ig.connlist_mutex);
802 INIT_LIST_HEAD(&ig.connlist); 796 INIT_LIST_HEAD(&ig.connlist);
803 797
798 release_wq = alloc_workqueue("release workqueue", 0, 0);
799 if (!release_wq) {
800 iser_err("failed to allocate release workqueue\n");
801 return -ENOMEM;
802 }
803
804 iscsi_iser_scsi_transport = iscsi_register_transport( 804 iscsi_iser_scsi_transport = iscsi_register_transport(
805 &iscsi_iser_transport); 805 &iscsi_iser_transport);
806 if (!iscsi_iser_scsi_transport) { 806 if (!iscsi_iser_scsi_transport) {
@@ -819,7 +819,24 @@ register_transport_failure:
819 819
820static void __exit iser_exit(void) 820static void __exit iser_exit(void)
821{ 821{
822 struct iser_conn *ib_conn, *n;
823 int connlist_empty;
824
822 iser_dbg("Removing iSER datamover...\n"); 825 iser_dbg("Removing iSER datamover...\n");
826 destroy_workqueue(release_wq);
827
828 mutex_lock(&ig.connlist_mutex);
829 connlist_empty = list_empty(&ig.connlist);
830 mutex_unlock(&ig.connlist_mutex);
831
832 if (!connlist_empty) {
833 iser_err("Error cleanup stage completed but we still have iser "
834 "connections, destroying them anyway.\n");
835 list_for_each_entry_safe(ib_conn, n, &ig.connlist, conn_list) {
836 iser_conn_release(ib_conn);
837 }
838 }
839
823 iscsi_unregister_transport(&iscsi_iser_transport); 840 iscsi_unregister_transport(&iscsi_iser_transport);
824 kmem_cache_destroy(ig.desc_cache); 841 kmem_cache_destroy(ig.desc_cache);
825} 842}