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>
	
	
This commit is contained in:
		
					parent
					
						
							
								0e8cd71cec
							
						
					
				
			
			
				commit
				
					
						49a47f2caf
					
				
			
		
					 3 changed files with 88 additions and 47 deletions
				
			
		|  | @ -4235,8 +4235,9 @@ static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn, | ||||||
|  * @callback:  lport initialization callback for tcm_qla2xxx code |  * @callback:  lport initialization callback for tcm_qla2xxx code | ||||||
|  * @target_lport_ptr: pointer for tcm_qla2xxx specific lport data |  * @target_lport_ptr: pointer for tcm_qla2xxx specific lport data | ||||||
|  */ |  */ | ||||||
| int qlt_lport_register(struct qla_tgt_func_tmpl *qla_tgt_ops, u64 wwpn, | int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn, | ||||||
| 	int (*callback)(struct scsi_qla_host *), void *target_lport_ptr) | 		       u64 npiv_wwpn, u64 npiv_wwnn, | ||||||
|  | 		       int (*callback)(struct scsi_qla_host *, void *, u64, u64)) | ||||||
| { | { | ||||||
| 	struct qla_tgt *tgt; | 	struct qla_tgt *tgt; | ||||||
| 	struct scsi_qla_host *vha; | 	struct scsi_qla_host *vha; | ||||||
|  | @ -4259,7 +4260,7 @@ int qlt_lport_register(struct qla_tgt_func_tmpl *qla_tgt_ops, u64 wwpn, | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		spin_lock_irqsave(&ha->hardware_lock, flags); | 		spin_lock_irqsave(&ha->hardware_lock, flags); | ||||||
| 		if (host->active_mode & MODE_TARGET) { | 		if ((!npiv_wwpn || !npiv_wwnn) && host->active_mode & MODE_TARGET) { | ||||||
| 			pr_debug("MODE_TARGET already active on qla2xxx(%d)\n", | 			pr_debug("MODE_TARGET already active on qla2xxx(%d)\n", | ||||||
| 			    host->host_no); | 			    host->host_no); | ||||||
| 			spin_unlock_irqrestore(&ha->hardware_lock, flags); | 			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, | ||||||
| 			    " qla2xxx scsi_host\n"); | 			    " qla2xxx scsi_host\n"); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 		qlt_lport_dump(vha, wwpn, b); | 		qlt_lport_dump(vha, phys_wwpn, b); | ||||||
| 
 | 
 | ||||||
| 		if (memcmp(vha->port_name, b, WWN_SIZE)) { | 		if (memcmp(vha->port_name, b, WWN_SIZE)) { | ||||||
| 			scsi_host_put(host); | 			scsi_host_put(host); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 		/*
 |  | ||||||
| 		 * Setup passed parameters ahead of invoking callback |  | ||||||
| 		 */ |  | ||||||
| 		ha->tgt.tgt_ops = qla_tgt_ops; |  | ||||||
| 		vha->vha_tgt.target_lport_ptr = target_lport_ptr; |  | ||||||
| 		rc = (*callback)(vha); |  | ||||||
| 		if (rc != 0) { |  | ||||||
| 			ha->tgt.tgt_ops = NULL; |  | ||||||
| 			vha->vha_tgt.target_lport_ptr = NULL; |  | ||||||
| 			scsi_host_put(host); |  | ||||||
| 		} |  | ||||||
| 		mutex_unlock(&qla_tgt_mutex); | 		mutex_unlock(&qla_tgt_mutex); | ||||||
|  | 
 | ||||||
|  | 		rc = (*callback)(vha, target_lport_ptr, npiv_wwpn, npiv_wwnn); | ||||||
|  | 		if (rc != 0) | ||||||
|  | 			scsi_host_put(host); | ||||||
|  | 
 | ||||||
| 		return rc; | 		return rc; | ||||||
| 	} | 	} | ||||||
| 	mutex_unlock(&qla_tgt_mutex); | 	mutex_unlock(&qla_tgt_mutex); | ||||||
|  |  | ||||||
|  | @ -932,8 +932,8 @@ void qlt_disable_vha(struct scsi_qla_host *); | ||||||
|  */ |  */ | ||||||
| extern int qlt_add_target(struct qla_hw_data *, struct scsi_qla_host *); | extern int qlt_add_target(struct qla_hw_data *, struct scsi_qla_host *); | ||||||
| extern int qlt_remove_target(struct qla_hw_data *, struct scsi_qla_host *); | extern int qlt_remove_target(struct qla_hw_data *, struct scsi_qla_host *); | ||||||
| extern int qlt_lport_register(struct qla_tgt_func_tmpl *, u64, | extern int qlt_lport_register(void *, u64, u64, u64, | ||||||
| 			int (*callback)(struct scsi_qla_host *), void *); | 			int (*callback)(struct scsi_qla_host *, void *, u64, u64)); | ||||||
| extern void qlt_lport_deregister(struct scsi_qla_host *); | extern void qlt_lport_deregister(struct scsi_qla_host *); | ||||||
| extern void qlt_unreg_sess(struct qla_tgt_sess *); | extern void qlt_unreg_sess(struct qla_tgt_sess *); | ||||||
| extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *); | extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *); | ||||||
|  |  | ||||||
|  | @ -1559,14 +1559,18 @@ static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int tcm_qla2xxx_lport_register_cb(struct scsi_qla_host *vha) | static int tcm_qla2xxx_lport_register_cb(struct scsi_qla_host *vha, | ||||||
|  | 					 void *target_lport_ptr, | ||||||
|  | 					 u64 npiv_wwpn, u64 npiv_wwnn) | ||||||
| { | { | ||||||
| 	struct tcm_qla2xxx_lport *lport; | 	struct qla_hw_data *ha = vha->hw; | ||||||
|  | 	struct tcm_qla2xxx_lport *lport = | ||||||
|  | 			(struct tcm_qla2xxx_lport *)target_lport_ptr; | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Setup local pointer to vha, NPIV VP pointer (if present) and | 	 * Setup tgt_ops, local pointer to vha and target_lport_ptr | ||||||
| 	 * vha->tcm_lport pointer |  | ||||||
| 	 */ | 	 */ | ||||||
| 	lport = (struct tcm_qla2xxx_lport *)vha->vha_tgt.target_lport_ptr; | 	ha->tgt.tgt_ops = &tcm_qla2xxx_template; | ||||||
|  | 	vha->vha_tgt.target_lport_ptr = target_lport_ptr; | ||||||
| 	lport->qla_vha = vha; | 	lport->qla_vha = vha; | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -1598,8 +1602,8 @@ static struct se_wwn *tcm_qla2xxx_make_lport( | ||||||
| 	if (ret != 0) | 	if (ret != 0) | ||||||
| 		goto out; | 		goto out; | ||||||
| 
 | 
 | ||||||
| 	ret = qlt_lport_register(&tcm_qla2xxx_template, wwpn, | 	ret = qlt_lport_register(lport, wwpn, 0, 0, | ||||||
| 				tcm_qla2xxx_lport_register_cb, lport); | 				 tcm_qla2xxx_lport_register_cb); | ||||||
| 	if (ret != 0) | 	if (ret != 0) | ||||||
| 		goto out_lport; | 		goto out_lport; | ||||||
| 
 | 
 | ||||||
|  | @ -1637,19 +1641,69 @@ static void tcm_qla2xxx_drop_lport(struct se_wwn *wwn) | ||||||
| 	kfree(lport); | 	kfree(lport); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha, | ||||||
|  | 					      void *target_lport_ptr, | ||||||
|  | 					      u64 npiv_wwpn, u64 npiv_wwnn) | ||||||
|  | { | ||||||
|  | 	struct fc_vport *vport; | ||||||
|  | 	struct Scsi_Host *sh = base_vha->host; | ||||||
|  | 	struct scsi_qla_host *npiv_vha; | ||||||
|  | 	struct tcm_qla2xxx_lport *lport = | ||||||
|  | 			(struct tcm_qla2xxx_lport *)target_lport_ptr; | ||||||
|  | 	struct fc_vport_identifiers vport_id; | ||||||
|  | 
 | ||||||
|  | 	if (!qla_tgt_mode_enabled(base_vha)) { | ||||||
|  | 		pr_err("qla2xxx base_vha not enabled for target mode\n"); | ||||||
|  | 		return -EPERM; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	memset(&vport_id, 0, sizeof(vport_id)); | ||||||
|  | 	vport_id.port_name = npiv_wwpn; | ||||||
|  | 	vport_id.node_name = npiv_wwnn; | ||||||
|  | 	vport_id.roles = FC_PORT_ROLE_FCP_INITIATOR; | ||||||
|  | 	vport_id.vport_type = FC_PORTTYPE_NPIV; | ||||||
|  | 	vport_id.disable = false; | ||||||
|  | 
 | ||||||
|  | 	vport = fc_vport_create(sh, 0, &vport_id); | ||||||
|  | 	if (!vport) { | ||||||
|  | 		pr_err("fc_vport_create failed for qla2xxx_npiv\n"); | ||||||
|  | 		return -ENODEV; | ||||||
|  | 	} | ||||||
|  | 	/*
 | ||||||
|  | 	 * Setup local pointer to NPIV vhba + target_lport_ptr | ||||||
|  | 	 */ | ||||||
|  | 	npiv_vha = (struct scsi_qla_host *)vport->dd_data; | ||||||
|  | 	npiv_vha->vha_tgt.target_lport_ptr = target_lport_ptr; | ||||||
|  | 	lport->qla_vha = npiv_vha; | ||||||
|  | 
 | ||||||
|  | 	scsi_host_get(npiv_vha->host); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| static struct se_wwn *tcm_qla2xxx_npiv_make_lport( | static struct se_wwn *tcm_qla2xxx_npiv_make_lport( | ||||||
| 	struct target_fabric_configfs *tf, | 	struct target_fabric_configfs *tf, | ||||||
| 	struct config_group *group, | 	struct config_group *group, | ||||||
| 	const char *name) | 	const char *name) | ||||||
| { | { | ||||||
| 	struct tcm_qla2xxx_lport *lport; | 	struct tcm_qla2xxx_lport *lport; | ||||||
| 	u64 npiv_wwpn, npiv_wwnn; | 	u64 phys_wwpn, npiv_wwpn, npiv_wwnn; | ||||||
|  | 	char *p, tmp[128]; | ||||||
| 	int ret; | 	int ret; | ||||||
| 	struct scsi_qla_host *vha = NULL; |  | ||||||
| 	struct qla_hw_data *ha = NULL; |  | ||||||
| 	scsi_qla_host_t *base_vha = NULL; |  | ||||||
| 
 | 
 | ||||||
| 	if (tcm_qla2xxx_npiv_parse_wwn(name, strlen(name)+1, | 	snprintf(tmp, 128, "%s", name); | ||||||
|  | 
 | ||||||
|  | 	p = strchr(tmp, '@'); | ||||||
|  | 	if (!p) { | ||||||
|  | 		pr_err("Unable to locate NPIV '@' seperator\n"); | ||||||
|  | 		return ERR_PTR(-EINVAL); | ||||||
|  | 	} | ||||||
|  | 	*p++ = '\0'; | ||||||
|  | 
 | ||||||
|  | 	if (tcm_qla2xxx_parse_wwn(tmp, &phys_wwpn, 1) < 0) | ||||||
|  | 		return ERR_PTR(-EINVAL); | ||||||
|  | 
 | ||||||
|  | 	if (tcm_qla2xxx_npiv_parse_wwn(p, strlen(p)+1, | ||||||
| 				       &npiv_wwpn, &npiv_wwnn) < 0) | 				       &npiv_wwpn, &npiv_wwnn) < 0) | ||||||
| 		return ERR_PTR(-EINVAL); | 		return ERR_PTR(-EINVAL); | ||||||
| 
 | 
 | ||||||
|  | @ -1668,21 +1722,11 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport( | ||||||
| 	if (ret != 0) | 	if (ret != 0) | ||||||
| 		goto out; | 		goto out; | ||||||
| 
 | 
 | ||||||
| 	ret = qlt_lport_register(&tcm_qla2xxx_template, npiv_wwpn, | 	ret = qlt_lport_register(lport, phys_wwpn, npiv_wwpn, npiv_wwnn, | ||||||
| 				tcm_qla2xxx_lport_register_cb, lport); | 				 tcm_qla2xxx_lport_register_npiv_cb); | ||||||
| 
 |  | ||||||
| 	if (ret != 0) | 	if (ret != 0) | ||||||
| 		goto out_lport; | 		goto out_lport; | ||||||
| 
 | 
 | ||||||
| 	vha = lport->qla_vha; |  | ||||||
| 	ha = vha->hw; |  | ||||||
| 	base_vha = pci_get_drvdata(ha->pdev); |  | ||||||
| 
 |  | ||||||
| 	if (!qla_tgt_mode_enabled(base_vha)) { |  | ||||||
| 		ret = -EPERM; |  | ||||||
| 		goto out_lport; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return &lport->lport_wwn; | 	return &lport->lport_wwn; | ||||||
| out_lport: | out_lport: | ||||||
| 	vfree(lport->lport_loopid_map); | 	vfree(lport->lport_loopid_map); | ||||||
|  | @ -1696,14 +1740,16 @@ static void tcm_qla2xxx_npiv_drop_lport(struct se_wwn *wwn) | ||||||
| { | { | ||||||
| 	struct tcm_qla2xxx_lport *lport = container_of(wwn, | 	struct tcm_qla2xxx_lport *lport = container_of(wwn, | ||||||
| 			struct tcm_qla2xxx_lport, lport_wwn); | 			struct tcm_qla2xxx_lport, lport_wwn); | ||||||
| 	struct scsi_qla_host *vha = lport->qla_vha; | 	struct scsi_qla_host *npiv_vha = lport->qla_vha; | ||||||
| 	struct Scsi_Host *sh = vha->host; | 	struct qla_hw_data *ha = npiv_vha->hw; | ||||||
|  | 	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); | ||||||
|  | 
 | ||||||
|  | 	scsi_host_put(npiv_vha->host); | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Notify libfc that we want to release the vha->fc_vport | 	 * Notify libfc that we want to release the vha->fc_vport | ||||||
| 	 */ | 	 */ | ||||||
| 	fc_vport_terminate(vha->fc_vport); | 	fc_vport_terminate(npiv_vha->fc_vport); | ||||||
| 
 | 	scsi_host_put(base_vha->host); | ||||||
| 	scsi_host_put(sh); |  | ||||||
| 	kfree(lport); | 	kfree(lport); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Nicholas Bellinger
				Nicholas Bellinger