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 + -
显示快捷键?