diff options
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_mid.c | 3 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_target.c | 25 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_target.h | 1 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/tcm_qla2xxx.c | 77 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/tcm_qla2xxx.h | 2 | ||||
| -rw-r--r-- | drivers/target/target_core_sbc.c | 18 | ||||
| -rw-r--r-- | drivers/target/target_core_transport.c | 1 | 
7 files changed, 111 insertions, 16 deletions
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index bd4708a422c..20fd974f903 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -149,6 +149,7 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)  int  qla24xx_disable_vp(scsi_qla_host_t *vha)  { +	unsigned long flags;  	int ret;  	ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL); @@ -156,7 +157,9 @@ qla24xx_disable_vp(scsi_qla_host_t *vha)  	atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);  	/* Remove port id from vp target map */ +	spin_lock_irqsave(&vha->hw->vport_slock, flags);  	qlt_update_vp_map(vha, RESET_AL_PA); +	spin_unlock_irqrestore(&vha->hw->vport_slock, flags);  	qla2x00_mark_vp_devices_dead(vha);  	atomic_set(&vha->vp_state, VP_FAILED); diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 0e09d8f433d..62aa5584f64 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -557,6 +557,7 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha,  	int pmap_len;  	fc_port_t *fcport;  	int global_resets; +	unsigned long flags;  retry:  	global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count); @@ -625,10 +626,10 @@ retry:  	    sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain,  	    fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id); -	sess->s_id = fcport->d_id; -	sess->loop_id = fcport->loop_id; -	sess->conf_compl_supported = !!(fcport->flags & -	    FCF_CONF_COMP_SUPPORTED); +	spin_lock_irqsave(&ha->hardware_lock, flags); +	ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, +				(fcport->flags & FCF_CONF_COMP_SUPPORTED)); +	spin_unlock_irqrestore(&ha->hardware_lock, flags);  	res = true; @@ -740,10 +741,9 @@ static struct qla_tgt_sess *qlt_create_sess(  				qlt_undelete_sess(sess);  			kref_get(&sess->se_sess->sess_kref); -			sess->s_id = fcport->d_id; -			sess->loop_id = fcport->loop_id; -			sess->conf_compl_supported = !!(fcport->flags & -			    FCF_CONF_COMP_SUPPORTED); +			ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, +						(fcport->flags & FCF_CONF_COMP_SUPPORTED)); +  			if (sess->local && !local)  				sess->local = 0;  			spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -796,8 +796,7 @@ static struct qla_tgt_sess *qlt_create_sess(  	 */  	kref_get(&sess->se_sess->sess_kref); -	sess->conf_compl_supported = !!(fcport->flags & -	    FCF_CONF_COMP_SUPPORTED); +	sess->conf_compl_supported = (fcport->flags & FCF_CONF_COMP_SUPPORTED);  	BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name));  	memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name)); @@ -869,10 +868,8 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)  			ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007,  			    "Reappeared sess %p\n", sess);  		} -		sess->s_id = fcport->d_id; -		sess->loop_id = fcport->loop_id; -		sess->conf_compl_supported = !!(fcport->flags & -		    FCF_CONF_COMP_SUPPORTED); +		ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, +					(fcport->flags & FCF_CONF_COMP_SUPPORTED));  	}  	if (sess && sess->local) { diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 170af157121..bad749561ec 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -648,6 +648,7 @@ struct qla_tgt_func_tmpl {  	int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *,  					void *, uint8_t *, uint16_t); +	void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool);  	struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *,  						const uint16_t);  	struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *, diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 2358c16c4c8..3d74f2f39ae 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -237,7 +237,7 @@ static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg)  				struct tcm_qla2xxx_tpg, se_tpg);  	struct tcm_qla2xxx_lport *lport = tpg->lport; -	return &lport->lport_name[0]; +	return lport->lport_naa_name;  }  static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg) @@ -1457,6 +1457,78 @@ static int tcm_qla2xxx_check_initiator_node_acl(  	return 0;  } +static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id, +				    uint16_t loop_id, bool conf_compl_supported) +{ +	struct qla_tgt *tgt = sess->tgt; +	struct qla_hw_data *ha = tgt->ha; +	struct tcm_qla2xxx_lport *lport = ha->tgt.target_lport_ptr; +	struct se_node_acl *se_nacl = sess->se_sess->se_node_acl; +	struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl, +			struct tcm_qla2xxx_nacl, se_node_acl); +	u32 key; + + +	if (sess->loop_id != loop_id || sess->s_id.b24 != s_id.b24) +		pr_info("Updating session %p from port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x loop_id %d -> %d s_id %x:%x:%x -> %x:%x:%x\n", +			sess, +			sess->port_name[0], sess->port_name[1], +			sess->port_name[2], sess->port_name[3], +			sess->port_name[4], sess->port_name[5], +			sess->port_name[6], sess->port_name[7], +			sess->loop_id, loop_id, +			sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa, +			s_id.b.domain, s_id.b.area, s_id.b.al_pa); + +	if (sess->loop_id != loop_id) { +		/* +		 * Because we can shuffle loop IDs around and we +		 * update different sessions non-atomically, we might +		 * have overwritten this session's old loop ID +		 * already, and we might end up overwriting some other +		 * session that will be updated later.  So we have to +		 * be extra careful and we can't warn about those things... +		 */ +		if (lport->lport_loopid_map[sess->loop_id].se_nacl == se_nacl) +			lport->lport_loopid_map[sess->loop_id].se_nacl = NULL; + +		lport->lport_loopid_map[loop_id].se_nacl = se_nacl; + +		sess->loop_id = loop_id; +	} + +	if (sess->s_id.b24 != s_id.b24) { +		key = (((u32) sess->s_id.b.domain << 16) | +		       ((u32) sess->s_id.b.area   <<  8) | +		       ((u32) sess->s_id.b.al_pa)); + +		if (btree_lookup32(&lport->lport_fcport_map, key)) +			WARN(btree_remove32(&lport->lport_fcport_map, key) != se_nacl, +			     "Found wrong se_nacl when updating s_id %x:%x:%x\n", +			     sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa); +		else +			WARN(1, "No lport_fcport_map entry for s_id %x:%x:%x\n", +			     sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa); + +		key = (((u32) s_id.b.domain << 16) | +		       ((u32) s_id.b.area   <<  8) | +		       ((u32) s_id.b.al_pa)); + +		if (btree_lookup32(&lport->lport_fcport_map, key)) { +			WARN(1, "Already have lport_fcport_map entry for s_id %x:%x:%x\n", +			     s_id.b.domain, s_id.b.area, s_id.b.al_pa); +			btree_update32(&lport->lport_fcport_map, key, se_nacl); +		} else { +			btree_insert32(&lport->lport_fcport_map, key, se_nacl, GFP_ATOMIC); +		} + +		sess->s_id = s_id; +		nacl->nport_id = key; +	} + +	sess->conf_compl_supported = conf_compl_supported; +} +  /*   * Calls into tcm_qla2xxx used by qla2xxx LLD I/O path.   */ @@ -1467,6 +1539,7 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {  	.free_cmd		= tcm_qla2xxx_free_cmd,  	.free_mcmd		= tcm_qla2xxx_free_mcmd,  	.free_session		= tcm_qla2xxx_free_session, +	.update_sess		= tcm_qla2xxx_update_sess,  	.check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl,  	.find_sess_by_s_id	= tcm_qla2xxx_find_sess_by_s_id,  	.find_sess_by_loop_id	= tcm_qla2xxx_find_sess_by_loop_id, @@ -1534,6 +1607,7 @@ static struct se_wwn *tcm_qla2xxx_make_lport(  	lport->lport_wwpn = wwpn;  	tcm_qla2xxx_format_wwn(&lport->lport_name[0], TCM_QLA2XXX_NAMELEN,  				wwpn); +	sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) wwpn);  	ret = tcm_qla2xxx_init_lport(lport);  	if (ret != 0) @@ -1601,6 +1675,7 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport(  	lport->lport_npiv_wwnn = npiv_wwnn;  	tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0],  			TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn); +	sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn);  /* FIXME: tcm_qla2xxx_npiv_make_lport */  	ret = -ENOSYS; diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.h b/drivers/scsi/qla2xxx/tcm_qla2xxx.h index 82549810335..9ba075fe978 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.h +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.h @@ -61,6 +61,8 @@ struct tcm_qla2xxx_lport {  	u64 lport_npiv_wwnn;  	/* ASCII formatted WWPN for FC Target Lport */  	char lport_name[TCM_QLA2XXX_NAMELEN]; +	/* ASCII formatted naa WWPN for VPD page 83 etc */ +	char lport_naa_name[TCM_QLA2XXX_NAMELEN];  	/* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */  	char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN];  	/* map for fc_port pointers in 24-bit FC Port ID space */ diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 868f8aa04f1..a6e27d967c7 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -135,6 +135,12 @@ static int sbc_emulate_verify(struct se_cmd *cmd)  	return 0;  } +static int sbc_emulate_noop(struct se_cmd *cmd) +{ +	target_complete_cmd(cmd, GOOD); +	return 0; +} +  static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors)  {  	return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors; @@ -531,6 +537,18 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)  		size = 0;  		cmd->execute_cmd = sbc_emulate_verify;  		break; +	case REZERO_UNIT: +	case SEEK_6: +	case SEEK_10: +		/* +		 * There are still clients out there which use these old SCSI-2 +		 * commands. This mainly happens when running VMs with legacy +		 * guest systems, connected via SCSI command pass-through to +		 * iSCSI targets. Make them happy and return status GOOD. +		 */ +		size = 0; +		cmd->execute_cmd = sbc_emulate_noop; +		break;  	default:  		ret = spc_parse_cdb(cmd, &size);  		if (ret) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index c33baff86aa..9097155e9eb 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1616,7 +1616,6 @@ static void target_complete_tmr_failure(struct work_struct *work)  	se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;  	se_cmd->se_tfo->queue_tm_rsp(se_cmd); -	transport_generic_free_cmd(se_cmd, 0);  }  /**  |