From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx> This patch moves struct scsi_qla_host scanning logic into qla_target.c code using qla_tgt_lport_register() and qla_tgt_lport_deregister(), and drops the problematic usage of pci_get_drvdata() in tcm_qla2xxx code. Both are driven by generic fabric configfs code in tcm_qla2xxx, and register walks a list of qla_target.c local entries added at qla2xxx PCI probe_one time to search for matching TFO->make_wwn() input. Once a matching FC wwpn has been found, the passed (*callback) will be invoked by qla_tgt_lport_register() while holding qla_tgt_mutex to finish lport setup in tcm_qla2xxx code. It also currrently assumes physical port WWPNs (eg: not NPIV), so virtual port handling will need to be added later. Cc: Christoph Hellwig <hch@xxxxxx> Cc: Roland Dreier <roland@xxxxxxxxxxxxxxx> Signed-off-by: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx> --- drivers/scsi/qla2xxx/qla_target.c | 117 +++++++++++++++++++++ drivers/scsi/qla2xxx/qla_target.h | 3 + drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c | 117 +++++---------------- 3 files changed, 146 insertions(+), 91 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 857a8e2..963bd45 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -118,6 +118,8 @@ static struct kmem_cache *qla_tgt_cmd_cachep; static struct kmem_cache *qla_tgt_mgmt_cmd_cachep; static mempool_t *qla_tgt_mgmt_cmd_mempool; static struct workqueue_struct *qla_tgt_wq; +static DEFINE_MUTEX(qla_tgt_mutex); +static LIST_HEAD(qla_tgt_glist); /* * From qla2xxx/qla_iobc.c and used by various qla_target.c logic */ @@ -4912,6 +4914,10 @@ int qla_tgt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha) } } + mutex_lock(&qla_tgt_mutex); + list_add_tail(&tgt->tgt_list_entry, &qla_tgt_glist); + mutex_unlock(&qla_tgt_mutex); + return 0; } @@ -4924,6 +4930,10 @@ int qla_tgt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha) return 0; } + mutex_lock(&qla_tgt_mutex); + list_del(&ha->qla_tgt->tgt_list_entry); + mutex_unlock(&qla_tgt_mutex); + ql_dbg(ql_dbg_tgt, vha, 0xe037, "Unregistering target for host %ld(%p)", vha->host_no, ha); qla_tgt_release(ha->qla_tgt); @@ -4931,6 +4941,113 @@ int qla_tgt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha) return 0; } +/** qla_tgt_lport_register() - Register lport with external module + * + * @qla_tgt_ops: Pointer for tcm_qla2xxx qla_tgt_ops + * @wwpn: Passwd FC target WWPN + * @callback: lport initialization callback for tcm_qla2xxx code + * @target_lport_ptr: pointer for tcm_qla2xxx specific lport data + */ +int qla_tgt_lport_register(struct qla_tgt_func_tmpl *qla_tgt_ops, u64 wwpn, + int (*callback)(struct scsi_qla_host *), + void *target_lport_ptr) +{ + struct qla_tgt *tgt; + struct scsi_qla_host *vha; + struct qla_hw_data *ha; + struct Scsi_Host *host; + unsigned long flags; + int i, rc; + u8 b[8]; + + mutex_lock(&qla_tgt_mutex); + list_for_each_entry(tgt, &qla_tgt_glist, tgt_list_entry) { + vha = tgt->vha; + ha = vha->hw; + + host = vha->host; + if (!host) + continue; + + if (ha->tgt_ops != NULL) + continue; + + if (!(host->hostt->supported_mode & MODE_TARGET)) + continue; + + spin_lock_irqsave(&ha->hardware_lock, flags); + if (host->active_mode & MODE_TARGET) { + pr_debug("MODE_TARGET already active on qla2xxx" + "(%d)\n", host->host_no); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + continue; + } + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + if (!scsi_host_get(host)) { + pr_err("Unable to scsi_host_get() for" + " qla2xxx scsi_host\n"); + continue; + } + + pr_debug("qla2xxx HW vha->node_name: "); + for (i = 0; i < 8; i++) + pr_debug("%02x ", vha->node_name[i]); + pr_debug("\n"); + pr_debug("qla2xxx HW vha->port_name: "); + for (i = 0; i < 8; i++) + pr_debug("%02x ", vha->port_name[i]); + pr_debug("\n"); + + pr_debug("qla2xxx passed configfs WWPN: "); + put_unaligned_be64(wwpn, b); + for (i = 0; i < 8; i++) + pr_debug("%02x ", b[i]); + pr_debug("\n"); + + if (memcmp(vha->port_name, b, 8)) { + scsi_host_put(host); + continue; + } + /* + * Setup passed parameters ahead of invoking callback + */ + ha->tgt_ops = qla_tgt_ops; + ha->target_lport_ptr = target_lport_ptr; + rc = (*callback)(vha); + if (rc != 0) { + ha->tgt_ops = NULL; + ha->target_lport_ptr = NULL; + } + mutex_unlock(&qla_tgt_mutex); + return rc; + } + mutex_unlock(&qla_tgt_mutex); + + return -ENODEV; +} +EXPORT_SYMBOL(qla_tgt_lport_register); + +/** qla_tgt_lport_deregister - Degister lport + * + * @vha: Registered scsi_qla_host pointer + */ +void qla_tgt_lport_deregister(struct scsi_qla_host *vha) +{ + struct qla_hw_data *ha = vha->hw; + struct Scsi_Host *sh = vha->host; + /* + * Clear the target_lport_ptr qla_target_template pointer in qla_hw_data + */ + ha->target_lport_ptr = NULL; + ha->tgt_ops = NULL; + /* + * Release the Scsi_Host reference for the underlying qla2xxx host + */ + scsi_host_put(sh); +} +EXPORT_SYMBOL(qla_tgt_lport_deregister); + /* Must be called under HW lock */ void qla_tgt_set_mode(struct scsi_qla_host *vha) { diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 3fee290..95efe44 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -1023,6 +1023,9 @@ void qla_tgt_disable_vha(struct scsi_qla_host *); */ extern int qla_tgt_add_target(struct qla_hw_data *, struct scsi_qla_host *); extern int qla_tgt_remove_target(struct qla_hw_data *, struct scsi_qla_host *); +extern int qla_tgt_lport_register(struct qla_tgt_func_tmpl *, u64, + int (*callback)(struct scsi_qla_host *), void *); +extern void qla_tgt_lport_deregister(struct scsi_qla_host *); extern void qla_tgt_fc_port_added(struct scsi_qla_host *, fc_port_t *); extern void qla_tgt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *); extern void qla_tgt_set_mode(struct scsi_qla_host *ha); diff --git a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c index 5f9b5a5..3634b7f 100644 --- a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c +++ b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c @@ -862,13 +862,8 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = { .find_sess_by_loop_id = tcm_qla2xxx_find_sess_by_loop_id, }; -static int tcm_qla2xxx_init_lport( - struct tcm_qla2xxx_lport *lport, - struct scsi_qla_host *vha, - struct scsi_qla_host *npiv_vp) +static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport) { - struct qla_hw_data *ha = vha->hw; - lport->lport_fcport_map = vmalloc( sizeof(struct tcm_qla2xxx_fc_domain) * 256); if (!lport->lport_fcport_map) { @@ -894,18 +889,20 @@ static int tcm_qla2xxx_init_lport( * 65536); pr_debug("qla2xxx: Allocated lport_loopid_map of %lu bytes\n", sizeof(struct tcm_qla2xxx_fc_loopid) * 65536); + return 0; +} + +static int tcm_qla2xxx_lport_register_cb(struct scsi_qla_host *vha) +{ + struct qla_hw_data *ha = vha->hw; + struct tcm_qla2xxx_lport *lport; /* - * Setup local pointer to vha, NPIV VP pointer (if present) and - * vha->tcm_lport pointer - */ + * Setup local pointer to vha, NPIV VP pointer (if present) and + * vha->tcm_lport pointer + */ + lport = (struct tcm_qla2xxx_lport *)ha->target_lport_ptr; lport->qla_vha = vha; - lport->qla_npiv_vp = npiv_vp; - /* - * Setup the target_lport_ptr and qla2x_tmpl. - */ - ha->target_lport_ptr = lport; - ha->tgt_ops = &tcm_qla2xxx_template; - + return 0; } @@ -915,14 +912,8 @@ static struct se_wwn *tcm_qla2xxx_make_lport( const char *name) { struct tcm_qla2xxx_lport *lport; - struct Scsi_Host *host = NULL; - struct pci_dev *dev = NULL; - struct scsi_qla_host *vha; - struct qla_hw_data *ha; - unsigned long flags; u64 wwpn; - int i, ret = -ENODEV; - u8 b[8]; + int ret = -ENODEV; if (tcm_qla2xxx_parse_wwn(name, &wwpn, 1) < 0) return ERR_PTR(-EINVAL); @@ -935,67 +926,19 @@ static struct se_wwn *tcm_qla2xxx_make_lport( lport->lport_wwpn = wwpn; tcm_qla2xxx_format_wwn(&lport->lport_name[0], TCM_QLA2XXX_NAMELEN, wwpn); - while ((dev = pci_get_device(PCI_VENDOR_ID_QLOGIC, PCI_ANY_ID, - dev)) != NULL) { - - vha = pci_get_drvdata(dev); - if (!vha) - continue; - ha = vha->hw; - if (!ha) - continue; - host = vha->host; - if (!host) - continue; - - if (!(host->hostt->supported_mode & MODE_TARGET)) - continue; - - spin_lock_irqsave(&ha->hardware_lock, flags); - if (host->active_mode & MODE_TARGET) { - pr_debug("MODE_TARGET already active on qla2xxx" - "(%d)\n", host->host_no); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - continue; - } - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - if (!scsi_host_get(host)) { - pr_err("Unable to scsi_host_get() for" - " qla2xxx scsi_host\n"); - ret = -EINVAL; - goto out; - } - - pr_debug("qla2xxx HW vha->node_name: "); - for (i = 0; i < 8; i++) - pr_debug("%02x ", vha->node_name[i]); - pr_debug("\n"); - - pr_debug("qla2xxx HW vha->port_name: "); - for (i = 0; i < 8; i++) - pr_debug("%02x ", vha->port_name[i]); - pr_debug("\n"); - - pr_debug("qla2xxx passed configfs WWPN: "); - put_unaligned_be64(wwpn, b); - for (i = 0; i < 8; i++) - pr_debug("%02x ", b[i]); - pr_debug("\n"); - - if (memcmp(vha->port_name, b, 8)) { - scsi_host_put(host); - continue; - } - pr_debug("qla2xxx: Found matching HW WWPN: %s for lport\n", name); - ret = tcm_qla2xxx_init_lport(lport, vha, NULL); - break; - } - + ret = tcm_qla2xxx_init_lport(lport); if (ret != 0) goto out; + ret = qla_tgt_lport_register(&tcm_qla2xxx_template, wwpn, + tcm_qla2xxx_lport_register_cb, lport); + if (ret != 0) + goto out_lport; + return &lport->lport_wwn; +out_lport: + vfree(lport->lport_loopid_map); + vfree(lport->lport_fcport_map); out: kfree(lport); return ERR_PTR(ret); @@ -1007,7 +950,6 @@ static void tcm_qla2xxx_drop_lport(struct se_wwn *wwn) struct tcm_qla2xxx_lport, lport_wwn); struct scsi_qla_host *vha = lport->qla_vha; struct qla_hw_data *ha = vha->hw; - struct Scsi_Host *sh = vha->host; /* * Call into qla2x_target.c LLD logic to complete the * shutdown of struct qla_tgt after the call to @@ -1015,15 +957,8 @@ static void tcm_qla2xxx_drop_lport(struct se_wwn *wwn) */ if (ha->qla_tgt && !ha->qla_tgt->tgt_stopped) qla_tgt_stop_phase2(ha->qla_tgt); - /* - * Clear the target_lport_ptr qla_target_template pointer in qla_hw_data - */ - ha->target_lport_ptr = NULL; - ha->tgt_ops = NULL; - /* - * Release the Scsi_Host reference for the underlying qla2xxx host - */ - scsi_host_put(sh); + + qla_tgt_lport_deregister(vha); vfree(lport->lport_loopid_map); vfree(lport->lport_fcport_map); @@ -1130,7 +1065,7 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport( pr_debug("qla2xxx_npiv: Found matching NPIV WWPN+WWNN: %s " " for lport\n", name); - tcm_qla2xxx_init_lport(lport, vha, npiv_vp); + tcm_qla2xxx_init_lport(lport); /* * Setup fc_vport_identifiers for NPIV containing * the passed WWPN and WWNN for the new libfc vport. -- 1.7.2.5 -- To unsubscribe from this list: send the line "unsubscribe target-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html