diff options
| author | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-01-14 23:38:58 -0500 |
|---|---|---|
| committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-01-18 21:22:12 -0500 |
| commit | 49a47f2cafbe4ca3839f8ae99c6fdeffd5fcaf45 (patch) | |
| tree | 51f53fe13179948bce86f60535d4259071735f51 | |
| parent | 0e8cd71ceca4c15ef544e3af01248bc869c28d8f (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.c | 25 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_target.h | 4 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/tcm_qla2xxx.c | 106 |
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 | */ |
| 4238 | int qlt_lport_register(struct qla_tgt_func_tmpl *qla_tgt_ops, u64 wwpn, | 4238 | int 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 | */ |
| 933 | extern int qlt_add_target(struct qla_hw_data *, struct scsi_qla_host *); | 933 | extern int qlt_add_target(struct qla_hw_data *, struct scsi_qla_host *); |
| 934 | extern int qlt_remove_target(struct qla_hw_data *, struct scsi_qla_host *); | 934 | extern int qlt_remove_target(struct qla_hw_data *, struct scsi_qla_host *); |
| 935 | extern int qlt_lport_register(struct qla_tgt_func_tmpl *, u64, | 935 | extern 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)); |
| 937 | extern void qlt_lport_deregister(struct scsi_qla_host *); | 937 | extern void qlt_lport_deregister(struct scsi_qla_host *); |
| 938 | extern void qlt_unreg_sess(struct qla_tgt_sess *); | 938 | extern void qlt_unreg_sess(struct qla_tgt_sess *); |
| 939 | extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *); | 939 | extern 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 | ||
| 1562 | 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) | ||
| 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 | ||
| 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 | |||
| 1640 | static struct se_wwn *tcm_qla2xxx_npiv_make_lport( | 1684 | static 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; |
| 1687 | out_lport: | 1731 | out_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 | ||
