[PATCH 1/2] qla2xxx: Add target lport register/deregister callers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux