aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuinn Tran <quinn.tran@qlogic.com>2015-12-17 14:57:04 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2016-01-07 16:57:46 -0500
commit7560151b6b3c1f4432c1c5b5b6496070d1f38484 (patch)
treeb929486880b266742d07197ab54fc0933afe8831
parent193b50b9d54a4fcb723a8005b29d8dd5518e3ae2 (diff)
qla2xxx: Remove dependency on hardware_lock to reduce lock contention.
Sessions management (add, deleted, modify) currently are serialized through the hardware_lock. Hardware_lock is a high traffic lock. This lock is accessed by both the transmit & receive sides. Sessions management is now moved off to another lock call sess_lock. This is done to reduce lock contention and increase traffic throughput. Signed-off-by: Quinn Tran <quinn.tran@qlogic.com> Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c1
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c132
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.c28
4 files changed, 106 insertions, 56 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 734524f5cf7d..216a944c1ca5 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2929,6 +2929,7 @@ struct qlt_hw_data {
2929 uint32_t num_qfull_cmds_dropped; 2929 uint32_t num_qfull_cmds_dropped;
2930 spinlock_t q_full_lock; 2930 spinlock_t q_full_lock;
2931 uint32_t leak_exchg_thresh_hold; 2931 uint32_t leak_exchg_thresh_hold;
2932 spinlock_t sess_lock;
2932}; 2933};
2933 2934
2934#define MAX_QFULL_CMDS_ALLOC 8192 2935#define MAX_QFULL_CMDS_ALLOC 8192
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 00ea902b2a42..0484acb3ff16 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2336,6 +2336,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
2336 ha->tgt.enable_class_2 = ql2xenableclass2; 2336 ha->tgt.enable_class_2 = ql2xenableclass2;
2337 INIT_LIST_HEAD(&ha->tgt.q_full_list); 2337 INIT_LIST_HEAD(&ha->tgt.q_full_list);
2338 spin_lock_init(&ha->tgt.q_full_lock); 2338 spin_lock_init(&ha->tgt.q_full_lock);
2339 spin_lock_init(&ha->tgt.sess_lock);
2339 2340
2340 /* Clear our data area */ 2341 /* Clear our data area */
2341 ha->bars = bars; 2342 ha->bars = bars;
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 104d129d9e11..6136987df164 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -636,7 +636,7 @@ static void qlt_free_session_done(struct work_struct *work)
636 wake_up_all(&tgt->waitQ); 636 wake_up_all(&tgt->waitQ);
637} 637}
638 638
639/* ha->hardware_lock supposed to be held on entry */ 639/* ha->tgt.sess_lock supposed to be held on entry */
640void qlt_unreg_sess(struct qla_tgt_sess *sess) 640void qlt_unreg_sess(struct qla_tgt_sess *sess)
641{ 641{
642 struct scsi_qla_host *vha = sess->vha; 642 struct scsi_qla_host *vha = sess->vha;
@@ -652,7 +652,7 @@ void qlt_unreg_sess(struct qla_tgt_sess *sess)
652} 652}
653EXPORT_SYMBOL(qlt_unreg_sess); 653EXPORT_SYMBOL(qlt_unreg_sess);
654 654
655/* ha->hardware_lock supposed to be held on entry */ 655
656static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd) 656static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
657{ 657{
658 struct qla_hw_data *ha = vha->hw; 658 struct qla_hw_data *ha = vha->hw;
@@ -662,12 +662,15 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
662 int res = 0; 662 int res = 0;
663 struct imm_ntfy_from_isp *n = (struct imm_ntfy_from_isp *)iocb; 663 struct imm_ntfy_from_isp *n = (struct imm_ntfy_from_isp *)iocb;
664 struct atio_from_isp *a = (struct atio_from_isp *)iocb; 664 struct atio_from_isp *a = (struct atio_from_isp *)iocb;
665 unsigned long flags;
665 666
666 loop_id = le16_to_cpu(n->u.isp24.nport_handle); 667 loop_id = le16_to_cpu(n->u.isp24.nport_handle);
667 if (loop_id == 0xFFFF) { 668 if (loop_id == 0xFFFF) {
668 /* Global event */ 669 /* Global event */
669 atomic_inc(&vha->vha_tgt.qla_tgt->tgt_global_resets_count); 670 atomic_inc(&vha->vha_tgt.qla_tgt->tgt_global_resets_count);
671 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
670 qlt_clear_tgt_db(vha->vha_tgt.qla_tgt); 672 qlt_clear_tgt_db(vha->vha_tgt.qla_tgt);
673 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
671#if 0 /* FIXME: do we need to choose a session here? */ 674#if 0 /* FIXME: do we need to choose a session here? */
672 if (!list_empty(&ha->tgt.qla_tgt->sess_list)) { 675 if (!list_empty(&ha->tgt.qla_tgt->sess_list)) {
673 sess = list_entry(ha->tgt.qla_tgt->sess_list.next, 676 sess = list_entry(ha->tgt.qla_tgt->sess_list.next,
@@ -694,7 +697,9 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
694 sess = NULL; 697 sess = NULL;
695#endif 698#endif
696 } else { 699 } else {
700 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
697 sess = ha->tgt.tgt_ops->find_sess_by_loop_id(vha, loop_id); 701 sess = ha->tgt.tgt_ops->find_sess_by_loop_id(vha, loop_id);
702 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
698 } 703 }
699 704
700 ql_dbg(ql_dbg_tgt, vha, 0xe000, 705 ql_dbg(ql_dbg_tgt, vha, 0xe000,
@@ -716,7 +721,7 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
716 iocb, QLA24XX_MGMT_SEND_NACK); 721 iocb, QLA24XX_MGMT_SEND_NACK);
717} 722}
718 723
719/* ha->hardware_lock supposed to be held on entry */ 724/* ha->tgt.sess_lock supposed to be held on entry */
720static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess, 725static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess,
721 bool immediate) 726 bool immediate)
722{ 727{
@@ -760,7 +765,7 @@ static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess,
760 sess->expires - jiffies); 765 sess->expires - jiffies);
761} 766}
762 767
763/* ha->hardware_lock supposed to be held on entry */ 768/* ha->tgt.sess_lock supposed to be held on entry */
764static void qlt_clear_tgt_db(struct qla_tgt *tgt) 769static void qlt_clear_tgt_db(struct qla_tgt *tgt)
765{ 770{
766 struct qla_tgt_sess *sess; 771 struct qla_tgt_sess *sess;
@@ -820,7 +825,7 @@ out_free_id_list:
820 return res; 825 return res;
821} 826}
822 827
823/* ha->hardware_lock supposed to be held on entry */ 828/* ha->tgt.sess_lock supposed to be held on entry */
824static void qlt_undelete_sess(struct qla_tgt_sess *sess) 829static void qlt_undelete_sess(struct qla_tgt_sess *sess)
825{ 830{
826 BUG_ON(sess->deleted != QLA_SESS_DELETION_PENDING); 831 BUG_ON(sess->deleted != QLA_SESS_DELETION_PENDING);
@@ -838,7 +843,7 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
838 struct qla_tgt_sess *sess; 843 struct qla_tgt_sess *sess;
839 unsigned long flags, elapsed; 844 unsigned long flags, elapsed;
840 845
841 spin_lock_irqsave(&ha->hardware_lock, flags); 846 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
842 while (!list_empty(&tgt->del_sess_list)) { 847 while (!list_empty(&tgt->del_sess_list)) {
843 sess = list_entry(tgt->del_sess_list.next, typeof(*sess), 848 sess = list_entry(tgt->del_sess_list.next, typeof(*sess),
844 del_list_entry); 849 del_list_entry);
@@ -859,7 +864,7 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
859 break; 864 break;
860 } 865 }
861 } 866 }
862 spin_unlock_irqrestore(&ha->hardware_lock, flags); 867 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
863} 868}
864 869
865/* 870/*
@@ -877,7 +882,7 @@ static struct qla_tgt_sess *qlt_create_sess(
877 unsigned char be_sid[3]; 882 unsigned char be_sid[3];
878 883
879 /* Check to avoid double sessions */ 884 /* Check to avoid double sessions */
880 spin_lock_irqsave(&ha->hardware_lock, flags); 885 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
881 list_for_each_entry(sess, &vha->vha_tgt.qla_tgt->sess_list, 886 list_for_each_entry(sess, &vha->vha_tgt.qla_tgt->sess_list,
882 sess_list_entry) { 887 sess_list_entry) {
883 if (!memcmp(sess->port_name, fcport->port_name, WWN_SIZE)) { 888 if (!memcmp(sess->port_name, fcport->port_name, WWN_SIZE)) {
@@ -892,7 +897,7 @@ static struct qla_tgt_sess *qlt_create_sess(
892 897
893 /* Cannot undelete at this point */ 898 /* Cannot undelete at this point */
894 if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { 899 if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
895 spin_unlock_irqrestore(&ha->hardware_lock, 900 spin_unlock_irqrestore(&ha->tgt.sess_lock,
896 flags); 901 flags);
897 return NULL; 902 return NULL;
898 } 903 }
@@ -909,12 +914,12 @@ static struct qla_tgt_sess *qlt_create_sess(
909 914
910 qlt_do_generation_tick(vha, &sess->generation); 915 qlt_do_generation_tick(vha, &sess->generation);
911 916
912 spin_unlock_irqrestore(&ha->hardware_lock, flags); 917 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
913 918
914 return sess; 919 return sess;
915 } 920 }
916 } 921 }
917 spin_unlock_irqrestore(&ha->hardware_lock, flags); 922 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
918 923
919 sess = kzalloc(sizeof(*sess), GFP_KERNEL); 924 sess = kzalloc(sizeof(*sess), GFP_KERNEL);
920 if (!sess) { 925 if (!sess) {
@@ -959,7 +964,7 @@ static struct qla_tgt_sess *qlt_create_sess(
959 } 964 }
960 /* 965 /*
961 * Take an extra reference to ->sess_kref here to handle qla_tgt_sess 966 * Take an extra reference to ->sess_kref here to handle qla_tgt_sess
962 * access across ->hardware_lock reaquire. 967 * access across ->tgt.sess_lock reaquire.
963 */ 968 */
964 kref_get(&sess->se_sess->sess_kref); 969 kref_get(&sess->se_sess->sess_kref);
965 970
@@ -967,11 +972,11 @@ static struct qla_tgt_sess *qlt_create_sess(
967 BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name)); 972 BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name));
968 memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name)); 973 memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name));
969 974
970 spin_lock_irqsave(&ha->hardware_lock, flags); 975 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
971 list_add_tail(&sess->sess_list_entry, &vha->vha_tgt.qla_tgt->sess_list); 976 list_add_tail(&sess->sess_list_entry, &vha->vha_tgt.qla_tgt->sess_list);
972 vha->vha_tgt.qla_tgt->sess_count++; 977 vha->vha_tgt.qla_tgt->sess_count++;
973 qlt_do_generation_tick(vha, &sess->generation); 978 qlt_do_generation_tick(vha, &sess->generation);
974 spin_unlock_irqrestore(&ha->hardware_lock, flags); 979 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
975 980
976 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b, 981 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b,
977 "qla_target(%d): %ssession for wwn %8phC (loop_id %d, " 982 "qla_target(%d): %ssession for wwn %8phC (loop_id %d, "
@@ -1002,23 +1007,23 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
1002 if (qla_ini_mode_enabled(vha)) 1007 if (qla_ini_mode_enabled(vha))
1003 return; 1008 return;
1004 1009
1005 spin_lock_irqsave(&ha->hardware_lock, flags); 1010 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
1006 if (tgt->tgt_stop) { 1011 if (tgt->tgt_stop) {
1007 spin_unlock_irqrestore(&ha->hardware_lock, flags); 1012 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
1008 return; 1013 return;
1009 } 1014 }
1010 sess = qlt_find_sess_by_port_name(tgt, fcport->port_name); 1015 sess = qlt_find_sess_by_port_name(tgt, fcport->port_name);
1011 if (!sess) { 1016 if (!sess) {
1012 spin_unlock_irqrestore(&ha->hardware_lock, flags); 1017 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
1013 1018
1014 mutex_lock(&vha->vha_tgt.tgt_mutex); 1019 mutex_lock(&vha->vha_tgt.tgt_mutex);
1015 sess = qlt_create_sess(vha, fcport, false); 1020 sess = qlt_create_sess(vha, fcport, false);
1016 mutex_unlock(&vha->vha_tgt.tgt_mutex); 1021 mutex_unlock(&vha->vha_tgt.tgt_mutex);
1017 1022
1018 spin_lock_irqsave(&ha->hardware_lock, flags); 1023 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
1019 } else if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { 1024 } else if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
1020 /* Point of no return */ 1025 /* Point of no return */
1021 spin_unlock_irqrestore(&ha->hardware_lock, flags); 1026 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
1022 return; 1027 return;
1023 } else { 1028 } else {
1024 kref_get(&sess->se_sess->sess_kref); 1029 kref_get(&sess->se_sess->sess_kref);
@@ -1047,7 +1052,7 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
1047 sess->local = 0; 1052 sess->local = 0;
1048 } 1053 }
1049 ha->tgt.tgt_ops->put_sess(sess); 1054 ha->tgt.tgt_ops->put_sess(sess);
1050 spin_unlock_irqrestore(&ha->hardware_lock, flags); 1055 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
1051} 1056}
1052 1057
1053/* 1058/*
@@ -1059,6 +1064,7 @@ qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen)
1059{ 1064{
1060 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; 1065 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
1061 struct qla_tgt_sess *sess; 1066 struct qla_tgt_sess *sess;
1067 unsigned long flags;
1062 1068
1063 if (!vha->hw->tgt.tgt_ops) 1069 if (!vha->hw->tgt.tgt_ops)
1064 return; 1070 return;
@@ -1066,15 +1072,19 @@ qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen)
1066 if (!tgt) 1072 if (!tgt)
1067 return; 1073 return;
1068 1074
1075 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
1069 if (tgt->tgt_stop) { 1076 if (tgt->tgt_stop) {
1077 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
1070 return; 1078 return;
1071 } 1079 }
1072 sess = qlt_find_sess_by_port_name(tgt, fcport->port_name); 1080 sess = qlt_find_sess_by_port_name(tgt, fcport->port_name);
1073 if (!sess) { 1081 if (!sess) {
1082 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
1074 return; 1083 return;
1075 } 1084 }
1076 1085
1077 if (max_gen - sess->generation < 0) { 1086 if (max_gen - sess->generation < 0) {
1087 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
1078 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf092, 1088 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf092,
1079 "Ignoring stale deletion request for se_sess %p / sess %p" 1089 "Ignoring stale deletion request for se_sess %p / sess %p"
1080 " for port %8phC, req_gen %d, sess_gen %d\n", 1090 " for port %8phC, req_gen %d, sess_gen %d\n",
@@ -1087,6 +1097,7 @@ qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen)
1087 1097
1088 sess->local = 1; 1098 sess->local = 1;
1089 qlt_schedule_sess_for_deletion(sess, false); 1099 qlt_schedule_sess_for_deletion(sess, false);
1100 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
1090} 1101}
1091 1102
1092static inline int test_tgt_sess_count(struct qla_tgt *tgt) 1103static inline int test_tgt_sess_count(struct qla_tgt *tgt)
@@ -1144,10 +1155,10 @@ int qlt_stop_phase1(struct qla_tgt *tgt)
1144 * Lock is needed, because we still can get an incoming packet. 1155 * Lock is needed, because we still can get an incoming packet.
1145 */ 1156 */
1146 mutex_lock(&vha->vha_tgt.tgt_mutex); 1157 mutex_lock(&vha->vha_tgt.tgt_mutex);
1147 spin_lock_irqsave(&ha->hardware_lock, flags); 1158 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
1148 tgt->tgt_stop = 1; 1159 tgt->tgt_stop = 1;
1149 qlt_clear_tgt_db(tgt); 1160 qlt_clear_tgt_db(tgt);
1150 spin_unlock_irqrestore(&ha->hardware_lock, flags); 1161 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
1151 mutex_unlock(&vha->vha_tgt.tgt_mutex); 1162 mutex_unlock(&vha->vha_tgt.tgt_mutex);
1152 mutex_unlock(&qla_tgt_mutex); 1163 mutex_unlock(&qla_tgt_mutex);
1153 1164
@@ -1595,6 +1606,7 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
1595 uint32_t tag = abts->exchange_addr_to_abort; 1606 uint32_t tag = abts->exchange_addr_to_abort;
1596 uint8_t s_id[3]; 1607 uint8_t s_id[3];
1597 int rc; 1608 int rc;
1609 unsigned long flags;
1598 1610
1599 if (le32_to_cpu(abts->fcp_hdr_le.parameter) & ABTS_PARAM_ABORT_SEQ) { 1611 if (le32_to_cpu(abts->fcp_hdr_le.parameter) & ABTS_PARAM_ABORT_SEQ) {
1600 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf053, 1612 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf053,
@@ -1622,6 +1634,7 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
1622 s_id[1] = abts->fcp_hdr_le.s_id[1]; 1634 s_id[1] = abts->fcp_hdr_le.s_id[1];
1623 s_id[2] = abts->fcp_hdr_le.s_id[0]; 1635 s_id[2] = abts->fcp_hdr_le.s_id[0];
1624 1636
1637 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
1625 sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id); 1638 sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id);
1626 if (!sess) { 1639 if (!sess) {
1627 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf012, 1640 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf012,
@@ -1629,12 +1642,17 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
1629 vha->vp_idx); 1642 vha->vp_idx);
1630 rc = qlt_sched_sess_work(vha->vha_tgt.qla_tgt, 1643 rc = qlt_sched_sess_work(vha->vha_tgt.qla_tgt,
1631 QLA_TGT_SESS_WORK_ABORT, abts, sizeof(*abts)); 1644 QLA_TGT_SESS_WORK_ABORT, abts, sizeof(*abts));
1645
1646 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
1647
1632 if (rc != 0) { 1648 if (rc != 0) {
1633 qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, 1649 qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED,
1634 false); 1650 false);
1635 } 1651 }
1636 return; 1652 return;
1637 } 1653 }
1654 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
1655
1638 1656
1639 if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { 1657 if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
1640 qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false); 1658 qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false);
@@ -3765,9 +3783,9 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
3765 /* 3783 /*
3766 * Drop extra session reference from qla_tgt_handle_cmd_for_atio*( 3784 * Drop extra session reference from qla_tgt_handle_cmd_for_atio*(
3767 */ 3785 */
3768 spin_lock_irqsave(&ha->hardware_lock, flags); 3786 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
3769 ha->tgt.tgt_ops->put_sess(sess); 3787 ha->tgt.tgt_ops->put_sess(sess);
3770 spin_unlock_irqrestore(&ha->hardware_lock, flags); 3788 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
3771 return; 3789 return;
3772 3790
3773out_term: 3791out_term:
@@ -3782,8 +3800,11 @@ out_term:
3782 3800
3783 qlt_decr_num_pend_cmds(vha); 3801 qlt_decr_num_pend_cmds(vha);
3784 percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag); 3802 percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
3785 ha->tgt.tgt_ops->put_sess(sess);
3786 spin_unlock_irqrestore(&ha->hardware_lock, flags); 3803 spin_unlock_irqrestore(&ha->hardware_lock, flags);
3804
3805 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
3806 ha->tgt.tgt_ops->put_sess(sess);
3807 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
3787} 3808}
3788 3809
3789static void qlt_do_work(struct work_struct *work) 3810static void qlt_do_work(struct work_struct *work)
@@ -4091,13 +4112,18 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb)
4091 struct qla_tgt_sess *sess; 4112 struct qla_tgt_sess *sess;
4092 uint32_t lun, unpacked_lun; 4113 uint32_t lun, unpacked_lun;
4093 int fn; 4114 int fn;
4115 unsigned long flags;
4094 4116
4095 tgt = vha->vha_tgt.qla_tgt; 4117 tgt = vha->vha_tgt.qla_tgt;
4096 4118
4097 lun = a->u.isp24.fcp_cmnd.lun; 4119 lun = a->u.isp24.fcp_cmnd.lun;
4098 fn = a->u.isp24.fcp_cmnd.task_mgmt_flags; 4120 fn = a->u.isp24.fcp_cmnd.task_mgmt_flags;
4121
4122 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
4099 sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, 4123 sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha,
4100 a->u.isp24.fcp_hdr.s_id); 4124 a->u.isp24.fcp_hdr.s_id);
4125 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
4126
4101 unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun); 4127 unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun);
4102 4128
4103 if (!sess) { 4129 if (!sess) {
@@ -4161,10 +4187,14 @@ static int qlt_abort_task(struct scsi_qla_host *vha,
4161 struct qla_hw_data *ha = vha->hw; 4187 struct qla_hw_data *ha = vha->hw;
4162 struct qla_tgt_sess *sess; 4188 struct qla_tgt_sess *sess;
4163 int loop_id; 4189 int loop_id;
4190 unsigned long flags;
4164 4191
4165 loop_id = GET_TARGET_ID(ha, (struct atio_from_isp *)iocb); 4192 loop_id = GET_TARGET_ID(ha, (struct atio_from_isp *)iocb);
4166 4193
4194 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
4167 sess = ha->tgt.tgt_ops->find_sess_by_loop_id(vha, loop_id); 4195 sess = ha->tgt.tgt_ops->find_sess_by_loop_id(vha, loop_id);
4196 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
4197
4168 if (sess == NULL) { 4198 if (sess == NULL) {
4169 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf025, 4199 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf025,
4170 "qla_target(%d): task abort for unexisting " 4200 "qla_target(%d): task abort for unexisting "
@@ -4311,6 +4341,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
4311 uint16_t wd3_lo; 4341 uint16_t wd3_lo;
4312 int res = 0; 4342 int res = 0;
4313 qlt_plogi_ack_t *pla; 4343 qlt_plogi_ack_t *pla;
4344 unsigned long flags;
4314 4345
4315 wwn = wwn_to_u64(iocb->u.isp24.port_name); 4346 wwn = wwn_to_u64(iocb->u.isp24.port_name);
4316 4347
@@ -4334,9 +4365,12 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
4334 /* Mark all stale commands in qla_tgt_wq for deletion */ 4365 /* Mark all stale commands in qla_tgt_wq for deletion */
4335 abort_cmds_for_s_id(vha, &port_id); 4366 abort_cmds_for_s_id(vha, &port_id);
4336 4367
4337 if (wwn) 4368 if (wwn) {
4369 spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
4338 sess = qlt_find_sess_invalidate_other(tgt, wwn, 4370 sess = qlt_find_sess_invalidate_other(tgt, wwn,
4339 port_id, loop_id, &conflict_sess); 4371 port_id, loop_id, &conflict_sess);
4372 spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock, flags);
4373 }
4340 4374
4341 if (IS_SW_RESV_ADDR(port_id) || (!sess && !conflict_sess)) { 4375 if (IS_SW_RESV_ADDR(port_id) || (!sess && !conflict_sess)) {
4342 res = 1; 4376 res = 1;
@@ -4387,9 +4421,12 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
4387 case ELS_PRLI: 4421 case ELS_PRLI:
4388 wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo); 4422 wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo);
4389 4423
4390 if (wwn) 4424 if (wwn) {
4425 spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
4391 sess = qlt_find_sess_invalidate_other(tgt, wwn, port_id, 4426 sess = qlt_find_sess_invalidate_other(tgt, wwn, port_id,
4392 loop_id, &conflict_sess); 4427 loop_id, &conflict_sess);
4428 spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock, flags);
4429 }
4393 4430
4394 if (conflict_sess) { 4431 if (conflict_sess) {
4395 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf09b, 4432 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf09b,
@@ -5068,9 +5105,12 @@ static int __qlt_send_busy(struct scsi_qla_host *vha,
5068 struct qla_hw_data *ha = vha->hw; 5105 struct qla_hw_data *ha = vha->hw;
5069 request_t *pkt; 5106 request_t *pkt;
5070 struct qla_tgt_sess *sess = NULL; 5107 struct qla_tgt_sess *sess = NULL;
5108 unsigned long flags;
5071 5109
5110 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
5072 sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, 5111 sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha,
5073 atio->u.isp24.fcp_hdr.s_id); 5112 atio->u.isp24.fcp_hdr.s_id);
5113 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
5074 if (!sess) { 5114 if (!sess) {
5075 qlt_send_term_exchange(vha, NULL, atio, 1); 5115 qlt_send_term_exchange(vha, NULL, atio, 1);
5076 return 0; 5116 return 0;
@@ -5771,15 +5811,15 @@ static void qlt_abort_work(struct qla_tgt *tgt,
5771 struct scsi_qla_host *vha = tgt->vha; 5811 struct scsi_qla_host *vha = tgt->vha;
5772 struct qla_hw_data *ha = vha->hw; 5812 struct qla_hw_data *ha = vha->hw;
5773 struct qla_tgt_sess *sess = NULL; 5813 struct qla_tgt_sess *sess = NULL;
5774 unsigned long flags; 5814 unsigned long flags = 0, flags2 = 0;
5775 uint32_t be_s_id; 5815 uint32_t be_s_id;
5776 uint8_t s_id[3]; 5816 uint8_t s_id[3];
5777 int rc; 5817 int rc;
5778 5818
5779 spin_lock_irqsave(&ha->hardware_lock, flags); 5819 spin_lock_irqsave(&ha->tgt.sess_lock, flags2);
5780 5820
5781 if (tgt->tgt_stop) 5821 if (tgt->tgt_stop)
5782 goto out_term; 5822 goto out_term2;
5783 5823
5784 s_id[0] = prm->abts.fcp_hdr_le.s_id[2]; 5824 s_id[0] = prm->abts.fcp_hdr_le.s_id[2];
5785 s_id[1] = prm->abts.fcp_hdr_le.s_id[1]; 5825 s_id[1] = prm->abts.fcp_hdr_le.s_id[1];
@@ -5788,39 +5828,47 @@ static void qlt_abort_work(struct qla_tgt *tgt,
5788 sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, 5828 sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha,
5789 (unsigned char *)&be_s_id); 5829 (unsigned char *)&be_s_id);
5790 if (!sess) { 5830 if (!sess) {
5791 spin_unlock_irqrestore(&ha->hardware_lock, flags); 5831 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
5792 5832
5793 sess = qlt_make_local_sess(vha, s_id); 5833 sess = qlt_make_local_sess(vha, s_id);
5794 /* sess has got an extra creation ref */ 5834 /* sess has got an extra creation ref */
5795 5835
5796 spin_lock_irqsave(&ha->hardware_lock, flags); 5836 spin_lock_irqsave(&ha->tgt.sess_lock, flags2);
5797 if (!sess) 5837 if (!sess)
5798 goto out_term; 5838 goto out_term2;
5799 } else { 5839 } else {
5800 if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { 5840 if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
5801 sess = NULL; 5841 sess = NULL;
5802 goto out_term; 5842 goto out_term2;
5803 } 5843 }
5804 5844
5805 kref_get(&sess->se_sess->sess_kref); 5845 kref_get(&sess->se_sess->sess_kref);
5806 } 5846 }
5807 5847
5848 spin_lock_irqsave(&ha->hardware_lock, flags);
5849
5808 if (tgt->tgt_stop) 5850 if (tgt->tgt_stop)
5809 goto out_term; 5851 goto out_term;
5810 5852
5811 rc = __qlt_24xx_handle_abts(vha, &prm->abts, sess); 5853 rc = __qlt_24xx_handle_abts(vha, &prm->abts, sess);
5812 if (rc != 0) 5854 if (rc != 0)
5813 goto out_term; 5855 goto out_term;
5856 spin_unlock_irqrestore(&ha->hardware_lock, flags);
5814 5857
5815 ha->tgt.tgt_ops->put_sess(sess); 5858 ha->tgt.tgt_ops->put_sess(sess);
5816 spin_unlock_irqrestore(&ha->hardware_lock, flags); 5859 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
5817 return; 5860 return;
5818 5861
5862out_term2:
5863 spin_lock_irqsave(&ha->hardware_lock, flags);
5864
5819out_term: 5865out_term:
5820 qlt_24xx_send_abts_resp(vha, &prm->abts, FCP_TMF_REJECTED, false); 5866 qlt_24xx_send_abts_resp(vha, &prm->abts, FCP_TMF_REJECTED, false);
5867 spin_unlock_irqrestore(&ha->hardware_lock, flags);
5868
5821 if (sess) 5869 if (sess)
5822 ha->tgt.tgt_ops->put_sess(sess); 5870 ha->tgt.tgt_ops->put_sess(sess);
5823 spin_unlock_irqrestore(&ha->hardware_lock, flags); 5871 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
5824} 5872}
5825 5873
5826static void qlt_tmr_work(struct qla_tgt *tgt, 5874static void qlt_tmr_work(struct qla_tgt *tgt,
@@ -5837,7 +5885,7 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
5837 int fn; 5885 int fn;
5838 void *iocb; 5886 void *iocb;
5839 5887
5840 spin_lock_irqsave(&ha->hardware_lock, flags); 5888 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
5841 5889
5842 if (tgt->tgt_stop) 5890 if (tgt->tgt_stop)
5843 goto out_term; 5891 goto out_term;
@@ -5845,12 +5893,12 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
5845 s_id = prm->tm_iocb2.u.isp24.fcp_hdr.s_id; 5893 s_id = prm->tm_iocb2.u.isp24.fcp_hdr.s_id;
5846 sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id); 5894 sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id);
5847 if (!sess) { 5895 if (!sess) {
5848 spin_unlock_irqrestore(&ha->hardware_lock, flags); 5896 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
5849 5897
5850 sess = qlt_make_local_sess(vha, s_id); 5898 sess = qlt_make_local_sess(vha, s_id);
5851 /* sess has got an extra creation ref */ 5899 /* sess has got an extra creation ref */
5852 5900
5853 spin_lock_irqsave(&ha->hardware_lock, flags); 5901 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
5854 if (!sess) 5902 if (!sess)
5855 goto out_term; 5903 goto out_term;
5856 } else { 5904 } else {
@@ -5872,14 +5920,14 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
5872 goto out_term; 5920 goto out_term;
5873 5921
5874 ha->tgt.tgt_ops->put_sess(sess); 5922 ha->tgt.tgt_ops->put_sess(sess);
5875 spin_unlock_irqrestore(&ha->hardware_lock, flags); 5923 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
5876 return; 5924 return;
5877 5925
5878out_term: 5926out_term:
5879 qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 1); 5927 qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 0);
5880 if (sess) 5928 if (sess)
5881 ha->tgt.tgt_ops->put_sess(sess); 5929 ha->tgt.tgt_ops->put_sess(sess);
5882 spin_unlock_irqrestore(&ha->hardware_lock, flags); 5930 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
5883} 5931}
5884 5932
5885static void qlt_sess_work_fn(struct work_struct *work) 5933static void qlt_sess_work_fn(struct work_struct *work)
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index cdd53c652b05..2881509072d9 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -344,9 +344,9 @@ static int tcm_qla2xxx_shutdown_session(struct se_session *se_sess)
344 BUG_ON(!sess); 344 BUG_ON(!sess);
345 vha = sess->vha; 345 vha = sess->vha;
346 346
347 spin_lock_irqsave(&vha->hw->hardware_lock, flags); 347 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
348 target_sess_cmd_list_set_waiting(se_sess); 348 target_sess_cmd_list_set_waiting(se_sess);
349 spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); 349 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
350 350
351 return 1; 351 return 1;
352} 352}
@@ -360,9 +360,9 @@ static void tcm_qla2xxx_close_session(struct se_session *se_sess)
360 BUG_ON(!sess); 360 BUG_ON(!sess);
361 vha = sess->vha; 361 vha = sess->vha;
362 362
363 spin_lock_irqsave(&vha->hw->hardware_lock, flags); 363 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
364 qlt_unreg_sess(sess); 364 qlt_unreg_sess(sess);
365 spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); 365 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
366} 366}
367 367
368static u32 tcm_qla2xxx_sess_get_index(struct se_session *se_sess) 368static u32 tcm_qla2xxx_sess_get_index(struct se_session *se_sess)
@@ -647,7 +647,7 @@ static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd)
647static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *, 647static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *,
648 struct tcm_qla2xxx_nacl *, struct qla_tgt_sess *); 648 struct tcm_qla2xxx_nacl *, struct qla_tgt_sess *);
649/* 649/*
650 * Expected to be called with struct qla_hw_data->hardware_lock held 650 * Expected to be called with struct qla_hw_data->tgt.sess_lock held
651 */ 651 */
652static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct qla_tgt_sess *sess) 652static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct qla_tgt_sess *sess)
653{ 653{
@@ -701,13 +701,13 @@ static void tcm_qla2xxx_put_sess(struct qla_tgt_sess *sess)
701 if (!sess) 701 if (!sess)
702 return; 702 return;
703 703
704 assert_spin_locked(&sess->vha->hw->hardware_lock); 704 assert_spin_locked(&sess->vha->hw->tgt.sess_lock);
705 kref_put(&sess->se_sess->sess_kref, tcm_qla2xxx_release_session); 705 kref_put(&sess->se_sess->sess_kref, tcm_qla2xxx_release_session);
706} 706}
707 707
708static void tcm_qla2xxx_shutdown_sess(struct qla_tgt_sess *sess) 708static void tcm_qla2xxx_shutdown_sess(struct qla_tgt_sess *sess)
709{ 709{
710 assert_spin_locked(&sess->vha->hw->hardware_lock); 710 assert_spin_locked(&sess->vha->hw->tgt.sess_lock);
711 target_sess_cmd_list_set_waiting(sess->se_sess); 711 target_sess_cmd_list_set_waiting(sess->se_sess);
712} 712}
713 713
@@ -1081,7 +1081,7 @@ static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg(
1081} 1081}
1082 1082
1083/* 1083/*
1084 * Expected to be called with struct qla_hw_data->hardware_lock held 1084 * Expected to be called with struct qla_hw_data->tgt.sess_lock held
1085 */ 1085 */
1086static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id( 1086static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id(
1087 scsi_qla_host_t *vha, 1087 scsi_qla_host_t *vha,
@@ -1120,7 +1120,7 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id(
1120} 1120}
1121 1121
1122/* 1122/*
1123 * Expected to be called with struct qla_hw_data->hardware_lock held 1123 * Expected to be called with struct qla_hw_data->tgt.sess_lock held
1124 */ 1124 */
1125static void tcm_qla2xxx_set_sess_by_s_id( 1125static void tcm_qla2xxx_set_sess_by_s_id(
1126 struct tcm_qla2xxx_lport *lport, 1126 struct tcm_qla2xxx_lport *lport,
@@ -1186,7 +1186,7 @@ static void tcm_qla2xxx_set_sess_by_s_id(
1186} 1186}
1187 1187
1188/* 1188/*
1189 * Expected to be called with struct qla_hw_data->hardware_lock held 1189 * Expected to be called with struct qla_hw_data->tgt.sess_lock held
1190 */ 1190 */
1191static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_loop_id( 1191static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_loop_id(
1192 scsi_qla_host_t *vha, 1192 scsi_qla_host_t *vha,
@@ -1225,7 +1225,7 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_loop_id(
1225} 1225}
1226 1226
1227/* 1227/*
1228 * Expected to be called with struct qla_hw_data->hardware_lock held 1228 * Expected to be called with struct qla_hw_data->tgt.sess_lock held
1229 */ 1229 */
1230static void tcm_qla2xxx_set_sess_by_loop_id( 1230static void tcm_qla2xxx_set_sess_by_loop_id(
1231 struct tcm_qla2xxx_lport *lport, 1231 struct tcm_qla2xxx_lport *lport,
@@ -1289,7 +1289,7 @@ static void tcm_qla2xxx_set_sess_by_loop_id(
1289} 1289}
1290 1290
1291/* 1291/*
1292 * Should always be called with qla_hw_data->hardware_lock held. 1292 * Should always be called with qla_hw_data->tgt.sess_lock held.
1293 */ 1293 */
1294static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *lport, 1294static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *lport,
1295 struct tcm_qla2xxx_nacl *nacl, struct qla_tgt_sess *sess) 1295 struct tcm_qla2xxx_nacl *nacl, struct qla_tgt_sess *sess)
@@ -1405,12 +1405,12 @@ static int tcm_qla2xxx_check_initiator_node_acl(
1405 * And now setup the new se_nacl and session pointers into our HW lport 1405 * And now setup the new se_nacl and session pointers into our HW lport
1406 * mappings for fabric S_ID and LOOP_ID. 1406 * mappings for fabric S_ID and LOOP_ID.
1407 */ 1407 */
1408 spin_lock_irqsave(&ha->hardware_lock, flags); 1408 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
1409 tcm_qla2xxx_set_sess_by_s_id(lport, se_nacl, nacl, se_sess, 1409 tcm_qla2xxx_set_sess_by_s_id(lport, se_nacl, nacl, se_sess,
1410 qla_tgt_sess, s_id); 1410 qla_tgt_sess, s_id);
1411 tcm_qla2xxx_set_sess_by_loop_id(lport, se_nacl, nacl, se_sess, 1411 tcm_qla2xxx_set_sess_by_loop_id(lport, se_nacl, nacl, se_sess,
1412 qla_tgt_sess, loop_id); 1412 qla_tgt_sess, loop_id);
1413 spin_unlock_irqrestore(&ha->hardware_lock, flags); 1413 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
1414 /* 1414 /*
1415 * Finally register the new FC Nexus with TCM 1415 * Finally register the new FC Nexus with TCM
1416 */ 1416 */