diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/tcm_qla2xxx.c')
-rw-r--r-- | drivers/scsi/qla2xxx/tcm_qla2xxx.c | 180 |
1 files changed, 122 insertions, 58 deletions
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 7eb19be35d46..75a141bbe74d 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c | |||
@@ -53,16 +53,6 @@ | |||
53 | struct workqueue_struct *tcm_qla2xxx_free_wq; | 53 | struct workqueue_struct *tcm_qla2xxx_free_wq; |
54 | struct workqueue_struct *tcm_qla2xxx_cmd_wq; | 54 | struct workqueue_struct *tcm_qla2xxx_cmd_wq; |
55 | 55 | ||
56 | static int tcm_qla2xxx_check_true(struct se_portal_group *se_tpg) | ||
57 | { | ||
58 | return 1; | ||
59 | } | ||
60 | |||
61 | static int tcm_qla2xxx_check_false(struct se_portal_group *se_tpg) | ||
62 | { | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | /* | 56 | /* |
67 | * Parse WWN. | 57 | * Parse WWN. |
68 | * If strict, we require lower-case hex and colon separators to be sure | 58 | * If strict, we require lower-case hex and colon separators to be sure |
@@ -174,7 +164,7 @@ static int tcm_qla2xxx_npiv_parse_wwn( | |||
174 | *wwnn = 0; | 164 | *wwnn = 0; |
175 | 165 | ||
176 | /* count may include a LF at end of string */ | 166 | /* count may include a LF at end of string */ |
177 | if (name[cnt-1] == '\n') | 167 | if (name[cnt-1] == '\n' || name[cnt-1] == 0) |
178 | cnt--; | 168 | cnt--; |
179 | 169 | ||
180 | /* validate we have enough characters for WWPN */ | 170 | /* validate we have enough characters for WWPN */ |
@@ -777,6 +767,9 @@ static void tcm_qla2xxx_put_session(struct se_session *se_sess) | |||
777 | 767 | ||
778 | static void tcm_qla2xxx_put_sess(struct qla_tgt_sess *sess) | 768 | static void tcm_qla2xxx_put_sess(struct qla_tgt_sess *sess) |
779 | { | 769 | { |
770 | if (!sess) | ||
771 | return; | ||
772 | |||
780 | assert_spin_locked(&sess->vha->hw->hardware_lock); | 773 | assert_spin_locked(&sess->vha->hw->hardware_lock); |
781 | kref_put(&sess->se_sess->sess_kref, tcm_qla2xxx_release_session); | 774 | kref_put(&sess->se_sess->sess_kref, tcm_qla2xxx_release_session); |
782 | } | 775 | } |
@@ -957,7 +950,6 @@ static ssize_t tcm_qla2xxx_tpg_store_enable( | |||
957 | struct tcm_qla2xxx_lport *lport = container_of(se_wwn, | 950 | struct tcm_qla2xxx_lport *lport = container_of(se_wwn, |
958 | struct tcm_qla2xxx_lport, lport_wwn); | 951 | struct tcm_qla2xxx_lport, lport_wwn); |
959 | struct scsi_qla_host *vha = lport->qla_vha; | 952 | struct scsi_qla_host *vha = lport->qla_vha; |
960 | struct qla_hw_data *ha = vha->hw; | ||
961 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | 953 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, |
962 | struct tcm_qla2xxx_tpg, se_tpg); | 954 | struct tcm_qla2xxx_tpg, se_tpg); |
963 | unsigned long op; | 955 | unsigned long op; |
@@ -977,12 +969,12 @@ static ssize_t tcm_qla2xxx_tpg_store_enable( | |||
977 | atomic_set(&tpg->lport_tpg_enabled, 1); | 969 | atomic_set(&tpg->lport_tpg_enabled, 1); |
978 | qlt_enable_vha(vha); | 970 | qlt_enable_vha(vha); |
979 | } else { | 971 | } else { |
980 | if (!ha->tgt.qla_tgt) { | 972 | if (!vha->vha_tgt.qla_tgt) { |
981 | pr_err("truct qla_hw_data *ha->tgt.qla_tgt is NULL\n"); | 973 | pr_err("struct qla_hw_data *vha->vha_tgt.qla_tgt is NULL\n"); |
982 | return -ENODEV; | 974 | return -ENODEV; |
983 | } | 975 | } |
984 | atomic_set(&tpg->lport_tpg_enabled, 0); | 976 | atomic_set(&tpg->lport_tpg_enabled, 0); |
985 | qlt_stop_phase1(ha->tgt.qla_tgt); | 977 | qlt_stop_phase1(vha->vha_tgt.qla_tgt); |
986 | } | 978 | } |
987 | 979 | ||
988 | return count; | 980 | return count; |
@@ -1011,7 +1003,7 @@ static struct se_portal_group *tcm_qla2xxx_make_tpg( | |||
1011 | if (kstrtoul(name + 5, 10, &tpgt) || tpgt > USHRT_MAX) | 1003 | if (kstrtoul(name + 5, 10, &tpgt) || tpgt > USHRT_MAX) |
1012 | return ERR_PTR(-EINVAL); | 1004 | return ERR_PTR(-EINVAL); |
1013 | 1005 | ||
1014 | if (!lport->qla_npiv_vp && (tpgt != 1)) { | 1006 | if ((tpgt != 1)) { |
1015 | pr_err("In non NPIV mode, a single TPG=1 is used for HW port mappings\n"); | 1007 | pr_err("In non NPIV mode, a single TPG=1 is used for HW port mappings\n"); |
1016 | return ERR_PTR(-ENOSYS); | 1008 | return ERR_PTR(-ENOSYS); |
1017 | } | 1009 | } |
@@ -1038,11 +1030,8 @@ static struct se_portal_group *tcm_qla2xxx_make_tpg( | |||
1038 | kfree(tpg); | 1030 | kfree(tpg); |
1039 | return NULL; | 1031 | return NULL; |
1040 | } | 1032 | } |
1041 | /* | 1033 | |
1042 | * Setup local TPG=1 pointer for non NPIV mode. | 1034 | lport->tpg_1 = tpg; |
1043 | */ | ||
1044 | if (lport->qla_npiv_vp == NULL) | ||
1045 | lport->tpg_1 = tpg; | ||
1046 | 1035 | ||
1047 | return &tpg->se_tpg; | 1036 | return &tpg->se_tpg; |
1048 | } | 1037 | } |
@@ -1053,19 +1042,17 @@ static void tcm_qla2xxx_drop_tpg(struct se_portal_group *se_tpg) | |||
1053 | struct tcm_qla2xxx_tpg, se_tpg); | 1042 | struct tcm_qla2xxx_tpg, se_tpg); |
1054 | struct tcm_qla2xxx_lport *lport = tpg->lport; | 1043 | struct tcm_qla2xxx_lport *lport = tpg->lport; |
1055 | struct scsi_qla_host *vha = lport->qla_vha; | 1044 | struct scsi_qla_host *vha = lport->qla_vha; |
1056 | struct qla_hw_data *ha = vha->hw; | ||
1057 | /* | 1045 | /* |
1058 | * Call into qla2x_target.c LLD logic to shutdown the active | 1046 | * Call into qla2x_target.c LLD logic to shutdown the active |
1059 | * FC Nexuses and disable target mode operation for this qla_hw_data | 1047 | * FC Nexuses and disable target mode operation for this qla_hw_data |
1060 | */ | 1048 | */ |
1061 | if (ha->tgt.qla_tgt && !ha->tgt.qla_tgt->tgt_stop) | 1049 | if (vha->vha_tgt.qla_tgt && !vha->vha_tgt.qla_tgt->tgt_stop) |
1062 | qlt_stop_phase1(ha->tgt.qla_tgt); | 1050 | qlt_stop_phase1(vha->vha_tgt.qla_tgt); |
1063 | 1051 | ||
1064 | core_tpg_deregister(se_tpg); | 1052 | core_tpg_deregister(se_tpg); |
1065 | /* | 1053 | /* |
1066 | * Clear local TPG=1 pointer for non NPIV mode. | 1054 | * Clear local TPG=1 pointer for non NPIV mode. |
1067 | */ | 1055 | */ |
1068 | if (lport->qla_npiv_vp == NULL) | ||
1069 | lport->tpg_1 = NULL; | 1056 | lport->tpg_1 = NULL; |
1070 | 1057 | ||
1071 | kfree(tpg); | 1058 | kfree(tpg); |
@@ -1095,12 +1082,22 @@ static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg( | |||
1095 | tpg->lport = lport; | 1082 | tpg->lport = lport; |
1096 | tpg->lport_tpgt = tpgt; | 1083 | tpg->lport_tpgt = tpgt; |
1097 | 1084 | ||
1085 | /* | ||
1086 | * By default allow READ-ONLY TPG demo-mode access w/ cached dynamic | ||
1087 | * NodeACLs | ||
1088 | */ | ||
1089 | tpg->tpg_attrib.generate_node_acls = 1; | ||
1090 | tpg->tpg_attrib.demo_mode_write_protect = 1; | ||
1091 | tpg->tpg_attrib.cache_dynamic_acls = 1; | ||
1092 | tpg->tpg_attrib.demo_mode_login_only = 1; | ||
1093 | |||
1098 | ret = core_tpg_register(&tcm_qla2xxx_npiv_fabric_configfs->tf_ops, wwn, | 1094 | ret = core_tpg_register(&tcm_qla2xxx_npiv_fabric_configfs->tf_ops, wwn, |
1099 | &tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL); | 1095 | &tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL); |
1100 | if (ret < 0) { | 1096 | if (ret < 0) { |
1101 | kfree(tpg); | 1097 | kfree(tpg); |
1102 | return NULL; | 1098 | return NULL; |
1103 | } | 1099 | } |
1100 | lport->tpg_1 = tpg; | ||
1104 | return &tpg->se_tpg; | 1101 | return &tpg->se_tpg; |
1105 | } | 1102 | } |
1106 | 1103 | ||
@@ -1111,13 +1108,12 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id( | |||
1111 | scsi_qla_host_t *vha, | 1108 | scsi_qla_host_t *vha, |
1112 | const uint8_t *s_id) | 1109 | const uint8_t *s_id) |
1113 | { | 1110 | { |
1114 | struct qla_hw_data *ha = vha->hw; | ||
1115 | struct tcm_qla2xxx_lport *lport; | 1111 | struct tcm_qla2xxx_lport *lport; |
1116 | struct se_node_acl *se_nacl; | 1112 | struct se_node_acl *se_nacl; |
1117 | struct tcm_qla2xxx_nacl *nacl; | 1113 | struct tcm_qla2xxx_nacl *nacl; |
1118 | u32 key; | 1114 | u32 key; |
1119 | 1115 | ||
1120 | lport = ha->tgt.target_lport_ptr; | 1116 | lport = vha->vha_tgt.target_lport_ptr; |
1121 | if (!lport) { | 1117 | if (!lport) { |
1122 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); | 1118 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); |
1123 | dump_stack(); | 1119 | dump_stack(); |
@@ -1221,13 +1217,12 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_loop_id( | |||
1221 | scsi_qla_host_t *vha, | 1217 | scsi_qla_host_t *vha, |
1222 | const uint16_t loop_id) | 1218 | const uint16_t loop_id) |
1223 | { | 1219 | { |
1224 | struct qla_hw_data *ha = vha->hw; | ||
1225 | struct tcm_qla2xxx_lport *lport; | 1220 | struct tcm_qla2xxx_lport *lport; |
1226 | struct se_node_acl *se_nacl; | 1221 | struct se_node_acl *se_nacl; |
1227 | struct tcm_qla2xxx_nacl *nacl; | 1222 | struct tcm_qla2xxx_nacl *nacl; |
1228 | struct tcm_qla2xxx_fc_loopid *fc_loopid; | 1223 | struct tcm_qla2xxx_fc_loopid *fc_loopid; |
1229 | 1224 | ||
1230 | lport = ha->tgt.target_lport_ptr; | 1225 | lport = vha->vha_tgt.target_lport_ptr; |
1231 | if (!lport) { | 1226 | if (!lport) { |
1232 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); | 1227 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); |
1233 | dump_stack(); | 1228 | dump_stack(); |
@@ -1341,6 +1336,7 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess) | |||
1341 | { | 1336 | { |
1342 | struct qla_tgt *tgt = sess->tgt; | 1337 | struct qla_tgt *tgt = sess->tgt; |
1343 | struct qla_hw_data *ha = tgt->ha; | 1338 | struct qla_hw_data *ha = tgt->ha; |
1339 | scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); | ||
1344 | struct se_session *se_sess; | 1340 | struct se_session *se_sess; |
1345 | struct se_node_acl *se_nacl; | 1341 | struct se_node_acl *se_nacl; |
1346 | struct tcm_qla2xxx_lport *lport; | 1342 | struct tcm_qla2xxx_lport *lport; |
@@ -1357,7 +1353,7 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess) | |||
1357 | se_nacl = se_sess->se_node_acl; | 1353 | se_nacl = se_sess->se_node_acl; |
1358 | nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); | 1354 | nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); |
1359 | 1355 | ||
1360 | lport = ha->tgt.target_lport_ptr; | 1356 | lport = vha->vha_tgt.target_lport_ptr; |
1361 | if (!lport) { | 1357 | if (!lport) { |
1362 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); | 1358 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); |
1363 | dump_stack(); | 1359 | dump_stack(); |
@@ -1391,7 +1387,7 @@ static int tcm_qla2xxx_check_initiator_node_acl( | |||
1391 | unsigned char port_name[36]; | 1387 | unsigned char port_name[36]; |
1392 | unsigned long flags; | 1388 | unsigned long flags; |
1393 | 1389 | ||
1394 | lport = ha->tgt.target_lport_ptr; | 1390 | lport = vha->vha_tgt.target_lport_ptr; |
1395 | if (!lport) { | 1391 | if (!lport) { |
1396 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); | 1392 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); |
1397 | dump_stack(); | 1393 | dump_stack(); |
@@ -1455,7 +1451,8 @@ static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id, | |||
1455 | { | 1451 | { |
1456 | struct qla_tgt *tgt = sess->tgt; | 1452 | struct qla_tgt *tgt = sess->tgt; |
1457 | struct qla_hw_data *ha = tgt->ha; | 1453 | struct qla_hw_data *ha = tgt->ha; |
1458 | struct tcm_qla2xxx_lport *lport = ha->tgt.target_lport_ptr; | 1454 | scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); |
1455 | struct tcm_qla2xxx_lport *lport = vha->vha_tgt.target_lport_ptr; | ||
1459 | struct se_node_acl *se_nacl = sess->se_sess->se_node_acl; | 1456 | struct se_node_acl *se_nacl = sess->se_sess->se_node_acl; |
1460 | struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl, | 1457 | struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl, |
1461 | struct tcm_qla2xxx_nacl, se_node_acl); | 1458 | struct tcm_qla2xxx_nacl, se_node_acl); |
@@ -1562,15 +1559,18 @@ static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport) | |||
1562 | return 0; | 1559 | return 0; |
1563 | } | 1560 | } |
1564 | 1561 | ||
1565 | static int tcm_qla2xxx_lport_register_cb(struct scsi_qla_host *vha) | 1562 | static int tcm_qla2xxx_lport_register_cb(struct scsi_qla_host *vha, |
1563 | void *target_lport_ptr, | ||
1564 | u64 npiv_wwpn, u64 npiv_wwnn) | ||
1566 | { | 1565 | { |
1567 | struct qla_hw_data *ha = vha->hw; | 1566 | struct qla_hw_data *ha = vha->hw; |
1568 | struct tcm_qla2xxx_lport *lport; | 1567 | struct tcm_qla2xxx_lport *lport = |
1568 | (struct tcm_qla2xxx_lport *)target_lport_ptr; | ||
1569 | /* | 1569 | /* |
1570 | * Setup local pointer to vha, NPIV VP pointer (if present) and | 1570 | * Setup tgt_ops, local pointer to vha and target_lport_ptr |
1571 | * vha->tcm_lport pointer | ||
1572 | */ | 1571 | */ |
1573 | lport = (struct tcm_qla2xxx_lport *)ha->tgt.target_lport_ptr; | 1572 | ha->tgt.tgt_ops = &tcm_qla2xxx_template; |
1573 | vha->vha_tgt.target_lport_ptr = target_lport_ptr; | ||
1574 | lport->qla_vha = vha; | 1574 | lport->qla_vha = vha; |
1575 | 1575 | ||
1576 | return 0; | 1576 | return 0; |
@@ -1602,8 +1602,8 @@ static struct se_wwn *tcm_qla2xxx_make_lport( | |||
1602 | if (ret != 0) | 1602 | if (ret != 0) |
1603 | goto out; | 1603 | goto out; |
1604 | 1604 | ||
1605 | ret = qlt_lport_register(&tcm_qla2xxx_template, wwpn, | 1605 | ret = qlt_lport_register(lport, wwpn, 0, 0, |
1606 | tcm_qla2xxx_lport_register_cb, lport); | 1606 | tcm_qla2xxx_lport_register_cb); |
1607 | if (ret != 0) | 1607 | if (ret != 0) |
1608 | goto out_lport; | 1608 | goto out_lport; |
1609 | 1609 | ||
@@ -1621,7 +1621,6 @@ static void tcm_qla2xxx_drop_lport(struct se_wwn *wwn) | |||
1621 | struct tcm_qla2xxx_lport *lport = container_of(wwn, | 1621 | struct tcm_qla2xxx_lport *lport = container_of(wwn, |
1622 | struct tcm_qla2xxx_lport, lport_wwn); | 1622 | struct tcm_qla2xxx_lport, lport_wwn); |
1623 | struct scsi_qla_host *vha = lport->qla_vha; | 1623 | struct scsi_qla_host *vha = lport->qla_vha; |
1624 | struct qla_hw_data *ha = vha->hw; | ||
1625 | struct se_node_acl *node; | 1624 | struct se_node_acl *node; |
1626 | u32 key = 0; | 1625 | u32 key = 0; |
1627 | 1626 | ||
@@ -1630,8 +1629,8 @@ static void tcm_qla2xxx_drop_lport(struct se_wwn *wwn) | |||
1630 | * shutdown of struct qla_tgt after the call to | 1629 | * shutdown of struct qla_tgt after the call to |
1631 | * qlt_stop_phase1() from tcm_qla2xxx_drop_tpg() above.. | 1630 | * qlt_stop_phase1() from tcm_qla2xxx_drop_tpg() above.. |
1632 | */ | 1631 | */ |
1633 | if (ha->tgt.qla_tgt && !ha->tgt.qla_tgt->tgt_stopped) | 1632 | if (vha->vha_tgt.qla_tgt && !vha->vha_tgt.qla_tgt->tgt_stopped) |
1634 | qlt_stop_phase2(ha->tgt.qla_tgt); | 1633 | qlt_stop_phase2(vha->vha_tgt.qla_tgt); |
1635 | 1634 | ||
1636 | qlt_lport_deregister(vha); | 1635 | qlt_lport_deregister(vha); |
1637 | 1636 | ||
@@ -1642,17 +1641,70 @@ static void tcm_qla2xxx_drop_lport(struct se_wwn *wwn) | |||
1642 | kfree(lport); | 1641 | kfree(lport); |
1643 | } | 1642 | } |
1644 | 1643 | ||
1644 | static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha, | ||
1645 | void *target_lport_ptr, | ||
1646 | u64 npiv_wwpn, u64 npiv_wwnn) | ||
1647 | { | ||
1648 | struct fc_vport *vport; | ||
1649 | struct Scsi_Host *sh = base_vha->host; | ||
1650 | struct scsi_qla_host *npiv_vha; | ||
1651 | struct tcm_qla2xxx_lport *lport = | ||
1652 | (struct tcm_qla2xxx_lport *)target_lport_ptr; | ||
1653 | struct fc_vport_identifiers vport_id; | ||
1654 | |||
1655 | if (!qla_tgt_mode_enabled(base_vha)) { | ||
1656 | pr_err("qla2xxx base_vha not enabled for target mode\n"); | ||
1657 | return -EPERM; | ||
1658 | } | ||
1659 | |||
1660 | memset(&vport_id, 0, sizeof(vport_id)); | ||
1661 | vport_id.port_name = npiv_wwpn; | ||
1662 | vport_id.node_name = npiv_wwnn; | ||
1663 | vport_id.roles = FC_PORT_ROLE_FCP_INITIATOR; | ||
1664 | vport_id.vport_type = FC_PORTTYPE_NPIV; | ||
1665 | vport_id.disable = false; | ||
1666 | |||
1667 | vport = fc_vport_create(sh, 0, &vport_id); | ||
1668 | if (!vport) { | ||
1669 | pr_err("fc_vport_create failed for qla2xxx_npiv\n"); | ||
1670 | return -ENODEV; | ||
1671 | } | ||
1672 | /* | ||
1673 | * Setup local pointer to NPIV vhba + target_lport_ptr | ||
1674 | */ | ||
1675 | npiv_vha = (struct scsi_qla_host *)vport->dd_data; | ||
1676 | npiv_vha->vha_tgt.target_lport_ptr = target_lport_ptr; | ||
1677 | lport->qla_vha = npiv_vha; | ||
1678 | |||
1679 | scsi_host_get(npiv_vha->host); | ||
1680 | return 0; | ||
1681 | } | ||
1682 | |||
1683 | |||
1645 | static struct se_wwn *tcm_qla2xxx_npiv_make_lport( | 1684 | static struct se_wwn *tcm_qla2xxx_npiv_make_lport( |
1646 | struct target_fabric_configfs *tf, | 1685 | struct target_fabric_configfs *tf, |
1647 | struct config_group *group, | 1686 | struct config_group *group, |
1648 | const char *name) | 1687 | const char *name) |
1649 | { | 1688 | { |
1650 | struct tcm_qla2xxx_lport *lport; | 1689 | struct tcm_qla2xxx_lport *lport; |
1651 | u64 npiv_wwpn, npiv_wwnn; | 1690 | u64 phys_wwpn, npiv_wwpn, npiv_wwnn; |
1691 | char *p, tmp[128]; | ||
1652 | int ret; | 1692 | int ret; |
1653 | 1693 | ||
1654 | if (tcm_qla2xxx_npiv_parse_wwn(name, strlen(name)+1, | 1694 | snprintf(tmp, 128, "%s", name); |
1655 | &npiv_wwpn, &npiv_wwnn) < 0) | 1695 | |
1696 | p = strchr(tmp, '@'); | ||
1697 | if (!p) { | ||
1698 | pr_err("Unable to locate NPIV '@' seperator\n"); | ||
1699 | return ERR_PTR(-EINVAL); | ||
1700 | } | ||
1701 | *p++ = '\0'; | ||
1702 | |||
1703 | if (tcm_qla2xxx_parse_wwn(tmp, &phys_wwpn, 1) < 0) | ||
1704 | return ERR_PTR(-EINVAL); | ||
1705 | |||
1706 | if (tcm_qla2xxx_npiv_parse_wwn(p, strlen(p)+1, | ||
1707 | &npiv_wwpn, &npiv_wwnn) < 0) | ||
1656 | return ERR_PTR(-EINVAL); | 1708 | return ERR_PTR(-EINVAL); |
1657 | 1709 | ||
1658 | lport = kzalloc(sizeof(struct tcm_qla2xxx_lport), GFP_KERNEL); | 1710 | lport = kzalloc(sizeof(struct tcm_qla2xxx_lport), GFP_KERNEL); |
@@ -1666,12 +1718,19 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport( | |||
1666 | TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn); | 1718 | TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn); |
1667 | sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn); | 1719 | sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn); |
1668 | 1720 | ||
1669 | /* FIXME: tcm_qla2xxx_npiv_make_lport */ | 1721 | ret = tcm_qla2xxx_init_lport(lport); |
1670 | ret = -ENOSYS; | ||
1671 | if (ret != 0) | 1722 | if (ret != 0) |
1672 | goto out; | 1723 | goto out; |
1673 | 1724 | ||
1725 | ret = qlt_lport_register(lport, phys_wwpn, npiv_wwpn, npiv_wwnn, | ||
1726 | tcm_qla2xxx_lport_register_npiv_cb); | ||
1727 | if (ret != 0) | ||
1728 | goto out_lport; | ||
1729 | |||
1674 | return &lport->lport_wwn; | 1730 | return &lport->lport_wwn; |
1731 | out_lport: | ||
1732 | vfree(lport->lport_loopid_map); | ||
1733 | btree_destroy32(&lport->lport_fcport_map); | ||
1675 | out: | 1734 | out: |
1676 | kfree(lport); | 1735 | kfree(lport); |
1677 | return ERR_PTR(ret); | 1736 | return ERR_PTR(ret); |
@@ -1681,14 +1740,16 @@ static void tcm_qla2xxx_npiv_drop_lport(struct se_wwn *wwn) | |||
1681 | { | 1740 | { |
1682 | struct tcm_qla2xxx_lport *lport = container_of(wwn, | 1741 | struct tcm_qla2xxx_lport *lport = container_of(wwn, |
1683 | struct tcm_qla2xxx_lport, lport_wwn); | 1742 | struct tcm_qla2xxx_lport, lport_wwn); |
1684 | struct scsi_qla_host *vha = lport->qla_vha; | 1743 | struct scsi_qla_host *npiv_vha = lport->qla_vha; |
1685 | struct Scsi_Host *sh = vha->host; | 1744 | struct qla_hw_data *ha = npiv_vha->hw; |
1745 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); | ||
1746 | |||
1747 | scsi_host_put(npiv_vha->host); | ||
1686 | /* | 1748 | /* |
1687 | * Notify libfc that we want to release the lport->npiv_vport | 1749 | * Notify libfc that we want to release the vha->fc_vport |
1688 | */ | 1750 | */ |
1689 | fc_vport_terminate(lport->npiv_vport); | 1751 | fc_vport_terminate(npiv_vha->fc_vport); |
1690 | 1752 | scsi_host_put(base_vha->host); | |
1691 | scsi_host_put(sh); | ||
1692 | kfree(lport); | 1753 | kfree(lport); |
1693 | } | 1754 | } |
1694 | 1755 | ||
@@ -1769,14 +1830,16 @@ static struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = { | |||
1769 | .tpg_get_pr_transport_id = tcm_qla2xxx_get_pr_transport_id, | 1830 | .tpg_get_pr_transport_id = tcm_qla2xxx_get_pr_transport_id, |
1770 | .tpg_get_pr_transport_id_len = tcm_qla2xxx_get_pr_transport_id_len, | 1831 | .tpg_get_pr_transport_id_len = tcm_qla2xxx_get_pr_transport_id_len, |
1771 | .tpg_parse_pr_out_transport_id = tcm_qla2xxx_parse_pr_out_transport_id, | 1832 | .tpg_parse_pr_out_transport_id = tcm_qla2xxx_parse_pr_out_transport_id, |
1772 | .tpg_check_demo_mode = tcm_qla2xxx_check_false, | 1833 | .tpg_check_demo_mode = tcm_qla2xxx_check_demo_mode, |
1773 | .tpg_check_demo_mode_cache = tcm_qla2xxx_check_true, | 1834 | .tpg_check_demo_mode_cache = tcm_qla2xxx_check_demo_mode_cache, |
1774 | .tpg_check_demo_mode_write_protect = tcm_qla2xxx_check_true, | 1835 | .tpg_check_demo_mode_write_protect = tcm_qla2xxx_check_demo_mode, |
1775 | .tpg_check_prod_mode_write_protect = tcm_qla2xxx_check_false, | 1836 | .tpg_check_prod_mode_write_protect = |
1837 | tcm_qla2xxx_check_prod_write_protect, | ||
1776 | .tpg_check_demo_mode_login_only = tcm_qla2xxx_check_demo_mode_login_only, | 1838 | .tpg_check_demo_mode_login_only = tcm_qla2xxx_check_demo_mode_login_only, |
1777 | .tpg_alloc_fabric_acl = tcm_qla2xxx_alloc_fabric_acl, | 1839 | .tpg_alloc_fabric_acl = tcm_qla2xxx_alloc_fabric_acl, |
1778 | .tpg_release_fabric_acl = tcm_qla2xxx_release_fabric_acl, | 1840 | .tpg_release_fabric_acl = tcm_qla2xxx_release_fabric_acl, |
1779 | .tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index, | 1841 | .tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index, |
1842 | .check_stop_free = tcm_qla2xxx_check_stop_free, | ||
1780 | .release_cmd = tcm_qla2xxx_release_cmd, | 1843 | .release_cmd = tcm_qla2xxx_release_cmd, |
1781 | .put_session = tcm_qla2xxx_put_session, | 1844 | .put_session = tcm_qla2xxx_put_session, |
1782 | .shutdown_session = tcm_qla2xxx_shutdown_session, | 1845 | .shutdown_session = tcm_qla2xxx_shutdown_session, |
@@ -1871,7 +1934,8 @@ static int tcm_qla2xxx_register_configfs(void) | |||
1871 | * Setup default attribute lists for various npiv_fabric->tf_cit_tmpl | 1934 | * Setup default attribute lists for various npiv_fabric->tf_cit_tmpl |
1872 | */ | 1935 | */ |
1873 | npiv_fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = tcm_qla2xxx_wwn_attrs; | 1936 | npiv_fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = tcm_qla2xxx_wwn_attrs; |
1874 | npiv_fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = NULL; | 1937 | npiv_fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = |
1938 | tcm_qla2xxx_tpg_attrs; | ||
1875 | npiv_fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL; | 1939 | npiv_fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL; |
1876 | npiv_fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL; | 1940 | npiv_fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL; |
1877 | npiv_fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL; | 1941 | npiv_fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL; |