aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2014-01-14 23:38:58 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2014-01-18 21:22:12 -0500
commit49a47f2cafbe4ca3839f8ae99c6fdeffd5fcaf45 (patch)
tree51f53fe13179948bce86f60535d4259071735f51
parent0e8cd71ceca4c15ef544e3af01248bc869c28d8f (diff)
qla2xxx: Configure NPIV fc_vport via tcm_qla2xxx_npiv_make_lport
This patch changes qla2xxx qlt_lport_register() code to accept target_lport_ptr + npiv_wwpn + npiv_wwnn parameters, and updates tcm_qla2xxx to use the new tcm_qla2xxx_lport_register_npiv_cb() callback for invoking fc_vport_create() from configfs context via tcm_qla2xxx_npiv_make_lport() code. In order for this to work, the qlt_lport_register() callback is now called without holding qla_tgt_mutex, as the fc_vport creation process will call qlt_vport_create() -> qlt_add_target(), which already expects to acquire it. It enforces /sys/kernel/config/target/qla2xxx_npiv/$NPIV_WWPN naming in the following format: $PHYSICAL_WWPN@$NPIV_WWPN:$NPIV_WWNN and assumes the $PHYSICAL_WWPN in question has already had been configured for target mode in non NPIV mode. Finally, it updates existing tcm_qla2xxx_lport_register_cb() logic to setup the non NPIV assignments that have now been moved out of qlt_lport_register() code. Cc: Sawan Chandak <sawan.chandak@qlogic.com> Cc: Quinn Tran <quinn.tran@qlogic.com> Cc: Saurav Kashyap <saurav.kashyap@qlogic.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c25
-rw-r--r--drivers/scsi/qla2xxx/qla_target.h4
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.c106
3 files changed, 88 insertions, 47 deletions
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 34ed246aa0db..b596f8b2cfc0 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -4235,8 +4235,9 @@ static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn,
4235 * @callback: lport initialization callback for tcm_qla2xxx code 4235 * @callback: lport initialization callback for tcm_qla2xxx code
4236 * @target_lport_ptr: pointer for tcm_qla2xxx specific lport data 4236 * @target_lport_ptr: pointer for tcm_qla2xxx specific lport data
4237 */ 4237 */
4238int qlt_lport_register(struct qla_tgt_func_tmpl *qla_tgt_ops, u64 wwpn, 4238int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn,
4239 int (*callback)(struct scsi_qla_host *), void *target_lport_ptr) 4239 u64 npiv_wwpn, u64 npiv_wwnn,
4240 int (*callback)(struct scsi_qla_host *, void *, u64, u64))
4240{ 4241{
4241 struct qla_tgt *tgt; 4242 struct qla_tgt *tgt;
4242 struct scsi_qla_host *vha; 4243 struct scsi_qla_host *vha;
@@ -4259,7 +4260,7 @@ int qlt_lport_register(struct qla_tgt_func_tmpl *qla_tgt_ops, u64 wwpn,
4259 continue; 4260 continue;
4260 4261
4261 spin_lock_irqsave(&ha->hardware_lock, flags); 4262 spin_lock_irqsave(&ha->hardware_lock, flags);
4262 if (host->active_mode & MODE_TARGET) { 4263 if ((!npiv_wwpn || !npiv_wwnn) && host->active_mode & MODE_TARGET) {
4263 pr_debug("MODE_TARGET already active on qla2xxx(%d)\n", 4264 pr_debug("MODE_TARGET already active on qla2xxx(%d)\n",
4264 host->host_no); 4265 host->host_no);
4265 spin_unlock_irqrestore(&ha->hardware_lock, flags); 4266 spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -4273,24 +4274,18 @@ int qlt_lport_register(struct qla_tgt_func_tmpl *qla_tgt_ops, u64 wwpn,
4273 " qla2xxx scsi_host\n"); 4274 " qla2xxx scsi_host\n");
4274 continue; 4275 continue;
4275 } 4276 }
4276 qlt_lport_dump(vha, wwpn, b); 4277 qlt_lport_dump(vha, phys_wwpn, b);
4277 4278
4278 if (memcmp(vha->port_name, b, WWN_SIZE)) { 4279 if (memcmp(vha->port_name, b, WWN_SIZE)) {
4279 scsi_host_put(host); 4280 scsi_host_put(host);
4280 continue; 4281 continue;
4281 } 4282 }
4282 /*
4283 * Setup passed parameters ahead of invoking callback
4284 */
4285 ha->tgt.tgt_ops = qla_tgt_ops;
4286 vha->vha_tgt.target_lport_ptr = target_lport_ptr;
4287 rc = (*callback)(vha);
4288 if (rc != 0) {
4289 ha->tgt.tgt_ops = NULL;
4290 vha->vha_tgt.target_lport_ptr = NULL;
4291 scsi_host_put(host);
4292 }
4293 mutex_unlock(&qla_tgt_mutex); 4283 mutex_unlock(&qla_tgt_mutex);
4284
4285 rc = (*callback)(vha, target_lport_ptr, npiv_wwpn, npiv_wwnn);
4286 if (rc != 0)
4287 scsi_host_put(host);
4288
4294 return rc; 4289 return rc;
4295 } 4290 }
4296 mutex_unlock(&qla_tgt_mutex); 4291 mutex_unlock(&qla_tgt_mutex);
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index b33e411f28a0..1d10eecad499 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -932,8 +932,8 @@ void qlt_disable_vha(struct scsi_qla_host *);
932 */ 932 */
933extern int qlt_add_target(struct qla_hw_data *, struct scsi_qla_host *); 933extern int qlt_add_target(struct qla_hw_data *, struct scsi_qla_host *);
934extern int qlt_remove_target(struct qla_hw_data *, struct scsi_qla_host *); 934extern int qlt_remove_target(struct qla_hw_data *, struct scsi_qla_host *);
935extern int qlt_lport_register(struct qla_tgt_func_tmpl *, u64, 935extern int qlt_lport_register(void *, u64, u64, u64,
936 int (*callback)(struct scsi_qla_host *), void *); 936 int (*callback)(struct scsi_qla_host *, void *, u64, u64));
937extern void qlt_lport_deregister(struct scsi_qla_host *); 937extern void qlt_lport_deregister(struct scsi_qla_host *);
938extern void qlt_unreg_sess(struct qla_tgt_sess *); 938extern void qlt_unreg_sess(struct qla_tgt_sess *);
939extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *); 939extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *);
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 113ca95d47df..75a141bbe74d 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -1559,14 +1559,18 @@ static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport)
1559 return 0; 1559 return 0;
1560} 1560}
1561 1561
1562static int tcm_qla2xxx_lport_register_cb(struct scsi_qla_host *vha) 1562static int tcm_qla2xxx_lport_register_cb(struct scsi_qla_host *vha,
1563 void *target_lport_ptr,
1564 u64 npiv_wwpn, u64 npiv_wwnn)
1563{ 1565{
1564 struct tcm_qla2xxx_lport *lport; 1566 struct qla_hw_data *ha = vha->hw;
1567 struct tcm_qla2xxx_lport *lport =
1568 (struct tcm_qla2xxx_lport *)target_lport_ptr;
1565 /* 1569 /*
1566 * Setup local pointer to vha, NPIV VP pointer (if present) and 1570 * Setup tgt_ops, local pointer to vha and target_lport_ptr
1567 * vha->tcm_lport pointer
1568 */ 1571 */
1569 lport = (struct tcm_qla2xxx_lport *)vha->vha_tgt.target_lport_ptr; 1572 ha->tgt.tgt_ops = &tcm_qla2xxx_template;
1573 vha->vha_tgt.target_lport_ptr = target_lport_ptr;
1570 lport->qla_vha = vha; 1574 lport->qla_vha = vha;
1571 1575
1572 return 0; 1576 return 0;
@@ -1598,8 +1602,8 @@ static struct se_wwn *tcm_qla2xxx_make_lport(
1598 if (ret != 0) 1602 if (ret != 0)
1599 goto out; 1603 goto out;
1600 1604
1601 ret = qlt_lport_register(&tcm_qla2xxx_template, wwpn, 1605 ret = qlt_lport_register(lport, wwpn, 0, 0,
1602 tcm_qla2xxx_lport_register_cb, lport); 1606 tcm_qla2xxx_lport_register_cb);
1603 if (ret != 0) 1607 if (ret != 0)
1604 goto out_lport; 1608 goto out_lport;
1605 1609
@@ -1637,20 +1641,70 @@ static void tcm_qla2xxx_drop_lport(struct se_wwn *wwn)
1637 kfree(lport); 1641 kfree(lport);
1638} 1642}
1639 1643
1644static 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
1640static struct se_wwn *tcm_qla2xxx_npiv_make_lport( 1684static struct se_wwn *tcm_qla2xxx_npiv_make_lport(
1641 struct target_fabric_configfs *tf, 1685 struct target_fabric_configfs *tf,
1642 struct config_group *group, 1686 struct config_group *group,
1643 const char *name) 1687 const char *name)
1644{ 1688{
1645 struct tcm_qla2xxx_lport *lport; 1689 struct tcm_qla2xxx_lport *lport;
1646 u64 npiv_wwpn, npiv_wwnn; 1690 u64 phys_wwpn, npiv_wwpn, npiv_wwnn;
1691 char *p, tmp[128];
1647 int ret; 1692 int ret;
1648 struct scsi_qla_host *vha = NULL;
1649 struct qla_hw_data *ha = NULL;
1650 scsi_qla_host_t *base_vha = NULL;
1651 1693
1652 if (tcm_qla2xxx_npiv_parse_wwn(name, strlen(name)+1, 1694 snprintf(tmp, 128, "%s", name);
1653 &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)
1654 return ERR_PTR(-EINVAL); 1708 return ERR_PTR(-EINVAL);
1655 1709
1656 lport = kzalloc(sizeof(struct tcm_qla2xxx_lport), GFP_KERNEL); 1710 lport = kzalloc(sizeof(struct tcm_qla2xxx_lport), GFP_KERNEL);
@@ -1668,21 +1722,11 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport(
1668 if (ret != 0) 1722 if (ret != 0)
1669 goto out; 1723 goto out;
1670 1724
1671 ret = qlt_lport_register(&tcm_qla2xxx_template, npiv_wwpn, 1725 ret = qlt_lport_register(lport, phys_wwpn, npiv_wwpn, npiv_wwnn,
1672 tcm_qla2xxx_lport_register_cb, lport); 1726 tcm_qla2xxx_lport_register_npiv_cb);
1673
1674 if (ret != 0) 1727 if (ret != 0)
1675 goto out_lport; 1728 goto out_lport;
1676 1729
1677 vha = lport->qla_vha;
1678 ha = vha->hw;
1679 base_vha = pci_get_drvdata(ha->pdev);
1680
1681 if (!qla_tgt_mode_enabled(base_vha)) {
1682 ret = -EPERM;
1683 goto out_lport;
1684 }
1685
1686 return &lport->lport_wwn; 1730 return &lport->lport_wwn;
1687out_lport: 1731out_lport:
1688 vfree(lport->lport_loopid_map); 1732 vfree(lport->lport_loopid_map);
@@ -1696,14 +1740,16 @@ static void tcm_qla2xxx_npiv_drop_lport(struct se_wwn *wwn)
1696{ 1740{
1697 struct tcm_qla2xxx_lport *lport = container_of(wwn, 1741 struct tcm_qla2xxx_lport *lport = container_of(wwn,
1698 struct tcm_qla2xxx_lport, lport_wwn); 1742 struct tcm_qla2xxx_lport, lport_wwn);
1699 struct scsi_qla_host *vha = lport->qla_vha; 1743 struct scsi_qla_host *npiv_vha = lport->qla_vha;
1700 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);
1701 /* 1748 /*
1702 * Notify libfc that we want to release the vha->fc_vport 1749 * Notify libfc that we want to release the vha->fc_vport
1703 */ 1750 */
1704 fc_vport_terminate(vha->fc_vport); 1751 fc_vport_terminate(npiv_vha->fc_vport);
1705 1752 scsi_host_put(base_vha->host);
1706 scsi_host_put(sh);
1707 kfree(lport); 1753 kfree(lport);
1708} 1754}
1709 1755