qla_mbx.c

来自「linux 内核源代码」· C语言 代码 · 共 2,658 行 · 第 1/5 页

C
2,658
字号
 *	Kernel context. */intqla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt){	int rval;	mbx_cmd_t mc;	mbx_cmd_t *mcp = &mc;	port_database_t *pd;	struct port_database_24xx *pd24;	dma_addr_t pd_dma;	DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));	pd24 = NULL;	pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);	if (pd  == NULL) {		DEBUG2_3(printk("%s(%ld): failed to allocate Port Database "		    "structure.\n", __func__, ha->host_no));		return QLA_MEMORY_ALLOC_FAILED;	}	memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE));	mcp->mb[0] = MBC_GET_PORT_DATABASE;	if (opt != 0 && !IS_FWI2_CAPABLE(ha))		mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE;	mcp->mb[2] = MSW(pd_dma);	mcp->mb[3] = LSW(pd_dma);	mcp->mb[6] = MSW(MSD(pd_dma));	mcp->mb[7] = LSW(MSD(pd_dma));	mcp->mb[9] = ha->vp_idx;	mcp->out_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;	mcp->in_mb = MBX_0;	if (IS_FWI2_CAPABLE(ha)) {		mcp->mb[1] = fcport->loop_id;		mcp->mb[10] = opt;		mcp->out_mb |= MBX_10|MBX_1;		mcp->in_mb |= MBX_1;	} else if (HAS_EXTENDED_IDS(ha)) {		mcp->mb[1] = fcport->loop_id;		mcp->mb[10] = opt;		mcp->out_mb |= MBX_10|MBX_1;	} else {		mcp->mb[1] = fcport->loop_id << 8 | opt;		mcp->out_mb |= MBX_1;	}	mcp->buf_size = IS_FWI2_CAPABLE(ha) ?	    PORT_DATABASE_24XX_SIZE : PORT_DATABASE_SIZE;	mcp->flags = MBX_DMA_IN;	mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);	rval = qla2x00_mailbox_command(ha, mcp);	if (rval != QLA_SUCCESS)		goto gpd_error_out;	if (IS_FWI2_CAPABLE(ha)) {		pd24 = (struct port_database_24xx *) pd;		/* Check for logged in state. */		if (pd24->current_login_state != PDS_PRLI_COMPLETE &&		    pd24->last_login_state != PDS_PRLI_COMPLETE) {			DEBUG2(printk("%s(%ld): Unable to verify "			    "login-state (%x/%x) for loop_id %x\n",			    __func__, ha->host_no,			    pd24->current_login_state,			    pd24->last_login_state, fcport->loop_id));			rval = QLA_FUNCTION_FAILED;			goto gpd_error_out;		}		/* Names are little-endian. */		memcpy(fcport->node_name, pd24->node_name, WWN_SIZE);		memcpy(fcport->port_name, pd24->port_name, WWN_SIZE);		/* Get port_id of device. */		fcport->d_id.b.domain = pd24->port_id[0];		fcport->d_id.b.area = pd24->port_id[1];		fcport->d_id.b.al_pa = pd24->port_id[2];		fcport->d_id.b.rsvd_1 = 0;		/* If not target must be initiator or unknown type. */		if ((pd24->prli_svc_param_word_3[0] & BIT_4) == 0)			fcport->port_type = FCT_INITIATOR;		else			fcport->port_type = FCT_TARGET;	} else {		/* Check for logged in state. */		if (pd->master_state != PD_STATE_PORT_LOGGED_IN &&		    pd->slave_state != PD_STATE_PORT_LOGGED_IN) {			rval = QLA_FUNCTION_FAILED;			goto gpd_error_out;		}		/* Names are little-endian. */		memcpy(fcport->node_name, pd->node_name, WWN_SIZE);		memcpy(fcport->port_name, pd->port_name, WWN_SIZE);		/* Get port_id of device. */		fcport->d_id.b.domain = pd->port_id[0];		fcport->d_id.b.area = pd->port_id[3];		fcport->d_id.b.al_pa = pd->port_id[2];		fcport->d_id.b.rsvd_1 = 0;		/* Check for device require authentication. */		pd->common_features & BIT_5 ? (fcport->flags |= FCF_AUTH_REQ) :		    (fcport->flags &= ~FCF_AUTH_REQ);		/* If not target must be initiator or unknown type. */		if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)			fcport->port_type = FCT_INITIATOR;		else			fcport->port_type = FCT_TARGET;		/* Passback COS information. */		fcport->supported_classes = (pd->options & BIT_4) ?		    FC_COS_CLASS2: FC_COS_CLASS3;	}gpd_error_out:	dma_pool_free(ha->s_dma_pool, pd, pd_dma);	if (rval != QLA_SUCCESS) {		DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",		    __func__, ha->host_no, rval, mcp->mb[0], mcp->mb[1]));	} else {		DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));	}	return rval;}/* * qla2x00_get_firmware_state *	Get adapter firmware state. * * Input: *	ha = adapter block pointer. *	dptr = pointer for firmware state. *	TARGET_QUEUE_LOCK must be released. *	ADAPTER_STATE_LOCK must be released. * * Returns: *	qla2x00 local function return status code. * * Context: *	Kernel context. */intqla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr){	int rval;	mbx_cmd_t mc;	mbx_cmd_t *mcp = &mc;	DEBUG11(printk("qla2x00_get_firmware_state(%ld): entered.\n",	    ha->host_no));	mcp->mb[0] = MBC_GET_FIRMWARE_STATE;	mcp->out_mb = MBX_0;	mcp->in_mb = MBX_2|MBX_1|MBX_0;	mcp->tov = 30;	mcp->flags = 0;	rval = qla2x00_mailbox_command(ha, mcp);	/* Return firmware state. */	*dptr = mcp->mb[1];	if (rval != QLA_SUCCESS) {		/*EMPTY*/		DEBUG2_3_11(printk("qla2x00_get_firmware_state(%ld): "		    "failed=%x.\n", ha->host_no, rval));	} else {		/*EMPTY*/		DEBUG11(printk("qla2x00_get_firmware_state(%ld): done.\n",		    ha->host_no));	}	return rval;}/* * qla2x00_get_port_name *	Issue get port name mailbox command. *	Returned name is in big endian format. * * Input: *	ha = adapter block pointer. *	loop_id = loop ID of device. *	name = pointer for name. *	TARGET_QUEUE_LOCK must be released. *	ADAPTER_STATE_LOCK must be released. * * Returns: *	qla2x00 local function return status code. * * Context: *	Kernel context. */intqla2x00_get_port_name(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t *name,    uint8_t opt){	int rval;	mbx_cmd_t mc;	mbx_cmd_t *mcp = &mc;	DEBUG11(printk("qla2x00_get_port_name(%ld): entered.\n",	    ha->host_no));	mcp->mb[0] = MBC_GET_PORT_NAME;	mcp->mb[9] = ha->vp_idx;	mcp->out_mb = MBX_9|MBX_1|MBX_0;	if (HAS_EXTENDED_IDS(ha)) {		mcp->mb[1] = loop_id;		mcp->mb[10] = opt;		mcp->out_mb |= MBX_10;	} else {		mcp->mb[1] = loop_id << 8 | opt;	}	mcp->in_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;	mcp->tov = 30;	mcp->flags = 0;	rval = qla2x00_mailbox_command(ha, mcp);	if (rval != QLA_SUCCESS) {		/*EMPTY*/		DEBUG2_3_11(printk("qla2x00_get_port_name(%ld): failed=%x.\n",		    ha->host_no, rval));	} else {		if (name != NULL) {			/* This function returns name in big endian. */			name[0] = MSB(mcp->mb[2]);			name[1] = LSB(mcp->mb[2]);			name[2] = MSB(mcp->mb[3]);			name[3] = LSB(mcp->mb[3]);			name[4] = MSB(mcp->mb[6]);			name[5] = LSB(mcp->mb[6]);			name[6] = MSB(mcp->mb[7]);			name[7] = LSB(mcp->mb[7]);		}		DEBUG11(printk("qla2x00_get_port_name(%ld): done.\n",		    ha->host_no));	}	return rval;}/* * qla2x00_lip_reset *	Issue LIP reset mailbox command. * * Input: *	ha = adapter block pointer. *	TARGET_QUEUE_LOCK must be released. *	ADAPTER_STATE_LOCK must be released. * * Returns: *	qla2x00 local function return status code. * * Context: *	Kernel context. */intqla2x00_lip_reset(scsi_qla_host_t *ha){	int rval;	mbx_cmd_t mc;	mbx_cmd_t *mcp = &mc;	DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));	if (IS_FWI2_CAPABLE(ha)) {		mcp->mb[0] = MBC_LIP_FULL_LOGIN;		mcp->mb[1] = BIT_6;		mcp->mb[2] = 0;		mcp->mb[3] = ha->loop_reset_delay;		mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;	} else {		mcp->mb[0] = MBC_LIP_RESET;		mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;		if (HAS_EXTENDED_IDS(ha)) {			mcp->mb[1] = 0x00ff;			mcp->mb[10] = 0;			mcp->out_mb |= MBX_10;		} else {			mcp->mb[1] = 0xff00;		}		mcp->mb[2] = ha->loop_reset_delay;		mcp->mb[3] = 0;	}	mcp->in_mb = MBX_0;	mcp->tov = 30;	mcp->flags = 0;	rval = qla2x00_mailbox_command(ha, mcp);	if (rval != QLA_SUCCESS) {		/*EMPTY*/		DEBUG2_3_11(printk("%s(%ld): failed=%x.\n",		    __func__, ha->host_no, rval));	} else {		/*EMPTY*/		DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));	}	return rval;}/* * qla2x00_send_sns *	Send SNS command. * * Input: *	ha = adapter block pointer. *	sns = pointer for command. *	cmd_size = command size. *	buf_size = response/command size. *	TARGET_QUEUE_LOCK must be released. *	ADAPTER_STATE_LOCK must be released. * * Returns: *	qla2x00 local function return status code. * * Context: *	Kernel context. */intqla2x00_send_sns(scsi_qla_host_t *ha, dma_addr_t sns_phys_address,    uint16_t cmd_size, size_t buf_size){	int rval;	mbx_cmd_t mc;	mbx_cmd_t *mcp = &mc;	DEBUG11(printk("qla2x00_send_sns(%ld): entered.\n",	    ha->host_no));	DEBUG11(printk("qla2x00_send_sns: retry cnt=%d ratov=%d total "	    "tov=%d.\n", ha->retry_count, ha->login_timeout, mcp->tov));	mcp->mb[0] = MBC_SEND_SNS_COMMAND;	mcp->mb[1] = cmd_size;	mcp->mb[2] = MSW(sns_phys_address);	mcp->mb[3] = LSW(sns_phys_address);	mcp->mb[6] = MSW(MSD(sns_phys_address));	mcp->mb[7] = LSW(MSD(sns_phys_address));	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;	mcp->in_mb = MBX_0|MBX_1;	mcp->buf_size = buf_size;	mcp->flags = MBX_DMA_OUT|MBX_DMA_IN;	mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);	rval = qla2x00_mailbox_command(ha, mcp);	if (rval != QLA_SUCCESS) {		/*EMPTY*/		DEBUG(printk("qla2x00_send_sns(%ld): failed=%x mb[0]=%x "		    "mb[1]=%x.\n", ha->host_no, rval, mcp->mb[0], mcp->mb[1]));		DEBUG2_3_11(printk("qla2x00_send_sns(%ld): failed=%x mb[0]=%x "		    "mb[1]=%x.\n", ha->host_no, rval, mcp->mb[0], mcp->mb[1]));	} else {		/*EMPTY*/		DEBUG11(printk("qla2x00_send_sns(%ld): done.\n", ha->host_no));	}	return rval;}intqla24xx_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,    uint8_t area, uint8_t al_pa, uint16_t *mb, uint8_t opt){	int		rval;	struct logio_entry_24xx *lg;	dma_addr_t	lg_dma;	uint32_t	iop[2];	DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));	lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);	if (lg == NULL) {		DEBUG2_3(printk("%s(%ld): failed to allocate Login IOCB.\n",		    __func__, ha->host_no));		return QLA_MEMORY_ALLOC_FAILED;	}	memset(lg, 0, sizeof(struct logio_entry_24xx));	lg->entry_type = LOGINOUT_PORT_IOCB_TYPE;	lg->entry_count = 1;	lg->nport_handle = cpu_to_le16(loop_id);	lg->control_flags = __constant_cpu_to_le16(LCF_COMMAND_PLOGI);	if (opt & BIT_0)		lg->control_flags |= __constant_cpu_to_le16(LCF_COND_PLOGI);	if (opt & BIT_1)		lg->control_flags |= __constant_cpu_to_le16(LCF_SKIP_PRLI);	lg->port_id[0] = al_pa;	lg->port_id[1] = area;	lg->port_id[2] = domain;	lg->vp_index = cpu_to_le16(ha->vp_idx);	rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0);	if (rval != QLA_SUCCESS) {		DEBUG2_3_11(printk("%s(%ld): failed to issue Login IOCB "		    "(%x).\n", __func__, ha->host_no, rval));	} else if (lg->entry_status != 0) {		DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "		    "-- error status (%x).\n", __func__, ha->host_no,		    lg->entry_status));		rval = QLA_FUNCTION_FAILED;	} else if (lg->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {		iop[0] = le32_to_cpu(lg->io_parameter[0]);		iop[1] = le32_to_cpu(lg->io_parameter[1]);		DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "		    "-- completion status (%x)  ioparam=%x/%x.\n", __func__,		    ha->host_no, le16_to_cpu(lg->comp_status), iop[0],		    iop[1]));		switch (iop[0]) {		case LSC_SCODE_PORTID_USED:			mb[0] = MBS_PORT_ID_USED;			mb[1] = LSW(iop[1]);			break;		case LSC_SCODE_NPORT_USED:			mb[0] = MBS_LOOP_ID_USED;			break;		case LSC_SCODE_NOLINK:		case LSC_SCODE_NOIOCB:		case LSC_SCODE_NOXCB:		case LSC_SCODE_CMD_FAILED:		case LSC_SCODE_NOFABRIC:		case LSC_SCODE_FW_NOT_READY:		case LSC_SCODE_NOT_LOGGED_IN:		case LSC_SCODE_NOPCB:		case LSC_SCODE_ELS_REJECT:		case LSC_SCODE_CMD_PARAM_ERR:		case LSC_SCODE_NONPORT:		case LSC_SCODE_LOGGED_IN:		case LSC_SCODE_NOFLOGI_ACC:		default:			mb[0] = MBS_COMMAND_ERROR;			break;		}	} else {		DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));		iop[0] = le32_to_cpu(lg->io_parameter[0]);		mb[0] = MBS_COMMAND_COMPLETE;		mb[1] = 0;		if (iop[0] & BIT_4) {			if (iop[0] & BIT_8)				mb[1] |= BIT_1;		} else			mb[1] = BIT_0;		/* Passback COS information. */		mb[10] = 0;		if (lg->io_parameter[7] || lg->io_parameter[8])			mb[10] |= BIT_0;	/* Class 2. */		if (lg->io_parameter[9] || lg->io_parameter[10])			mb[10] |= BIT_1;	/* Class 3. */	}	dma_pool_free(ha->s_dma_pool, lg, lg_dma);	return rval;}/* * qla2x00_login_fabric *	Issue login fabric port mailbox command. * * Input: *	ha = adapter block pointer. *	loop_id = device loop ID. *	domain = device domain. *	area = device area. *	al_pa = device AL_PA. *	status = pointer for return status. *	opt = command options. *	TARGET_QUEUE_LOCK must be released. *	ADAPTER_STATE_LOCK must be released. * * Returns: *	qla2x00 local function return status code. * * Context: *	Kernel context. */intqla2x00_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,    uint8_t area, uint8_t al_pa, uint16_t *mb, uint8_t opt){	int rval;	mbx_cmd_t mc;	mbx_cmd_t *mcp = &mc;	DEBUG11(printk("qla2x00_login_fabric(%ld): entered.\n", ha->host_no));	mcp->mb[0] = MBC_LOGIN_FABRIC_PORT;	mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;	if (HAS_EXTENDED_IDS(ha)) {		mcp->mb[1] = loop_id;		mcp->mb[10] = opt;		mcp->out_mb |= MBX_10;	} else {		mcp->mb[1] = (loop_id << 8) | opt;	}	mcp->mb[2] = domain;	mcp->mb[3] = area << 8 | al_pa;	mcp->in_mb = MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;	mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);	mcp->flags = 0;	rval = qla2x00_mailbox_command(ha, mcp);	/* Return mailbox statuses. */	if (mb != NULL) {		mb[0] = mcp->mb[0];		mb[1] = mcp->mb[1];		mb[2] = mcp->mb[2];		mb[6] = mcp->mb[6];		mb[7] = mcp->mb[7];		/* COS retrieved from Get-Port-Database mailbox command. */		mb[10] = 0;	}	if (rval != QLA_SUCCESS) {		/* RLU tmp code: need to change main mailbox_command function to		 * return ok even when the mailbox completion value is not		 * SUCCESS. The caller needs to be responsible to interpret		 * the return values of this mailbox command if we're not

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?