diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_mbx.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 410 |
1 files changed, 322 insertions, 88 deletions
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 08f1d01..b4a2339 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -46,17 +46,17 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) struct qla_hw_data *ha = vha->hw; scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); - ql_dbg(ql_dbg_mbx, base_vha, 0x1000, "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1000, "Entered %s.\n", __func__); if (ha->pdev->error_state > pci_channel_io_frozen) { - ql_log(ql_log_warn, base_vha, 0x1001, + ql_log(ql_log_warn, vha, 0x1001, "error_state is greater than pci_channel_io_frozen, " "exiting.\n"); return QLA_FUNCTION_TIMEOUT; } if (vha->device_flags & DFLG_DEV_FAILED) { - ql_log(ql_log_warn, base_vha, 0x1002, + ql_log(ql_log_warn, vha, 0x1002, "Device in failed state, exiting.\n"); return QLA_FUNCTION_TIMEOUT; } @@ -69,7 +69,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) if (ha->flags.pci_channel_io_perm_failure) { - ql_log(ql_log_warn, base_vha, 0x1003, + ql_log(ql_log_warn, vha, 0x1003, "Perm failure on EEH timeout MBX, exiting.\n"); return QLA_FUNCTION_TIMEOUT; } @@ -77,7 +77,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) if (ha->flags.isp82xx_fw_hung) { /* Setting Link-Down error */ mcp->mb[0] = MBS_LINK_DOWN_ERROR; - ql_log(ql_log_warn, base_vha, 0x1004, + ql_log(ql_log_warn, vha, 0x1004, "FW hung = %d.\n", ha->flags.isp82xx_fw_hung); return QLA_FUNCTION_TIMEOUT; } @@ -89,8 +89,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) */ if (!wait_for_completion_timeout(&ha->mbx_cmd_comp, mcp->tov * HZ)) { /* Timeout occurred. Return error. */ - ql_log(ql_log_warn, base_vha, 0x1005, - "Cmd access timeout, Exiting.\n"); + ql_log(ql_log_warn, vha, 0x1005, + "Cmd access timeout, cmd=0x%x, Exiting.\n", + mcp->mb[0]); return QLA_FUNCTION_TIMEOUT; } @@ -98,7 +99,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) /* Save mailbox command for debug */ ha->mcp = mcp; - ql_dbg(ql_dbg_mbx, base_vha, 0x1006, + ql_dbg(ql_dbg_mbx, vha, 0x1006, "Prepare to issue mbox cmd=0x%x.\n", mcp->mb[0]); spin_lock_irqsave(&ha->hardware_lock, flags); @@ -127,28 +128,28 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) iptr++; } - ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1111, + ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1111, "Loaded MBX registers (displayed in bytes) =.\n"); - ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1112, + ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1112, (uint8_t *)mcp->mb, 16); - ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1113, + ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1113, ".\n"); - ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1114, + ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1114, ((uint8_t *)mcp->mb + 0x10), 16); - ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1115, + ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1115, ".\n"); - ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1116, + ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1116, ((uint8_t *)mcp->mb + 0x20), 8); - ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1117, + ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1117, "I/O Address = %p.\n", optr); - ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x100e); + ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, vha, 0x100e); /* Issue set host interrupt command to send cmd out. */ ha->flags.mbox_int = 0; clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); /* Unlock mbx registers and wait for interrupt */ - ql_dbg(ql_dbg_mbx, base_vha, 0x100f, + ql_dbg(ql_dbg_mbx, vha, 0x100f, "Going to unlock irq & waiting for interrupts. " "jiffies=%lx.\n", jiffies); @@ -163,7 +164,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) spin_unlock_irqrestore(&ha->hardware_lock, flags); ha->flags.mbox_busy = 0; - ql_dbg(ql_dbg_mbx, base_vha, 0x1010, + ql_dbg(ql_dbg_mbx, vha, 0x1010, "Pending mailbox timeout, exiting.\n"); rval = QLA_FUNCTION_TIMEOUT; goto premature_exit; @@ -180,7 +181,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); } else { - ql_dbg(ql_dbg_mbx, base_vha, 0x1011, + ql_dbg(ql_dbg_mbx, vha, 0x1011, "Cmd=%x Polling Mode.\n", command); if (IS_QLA82XX(ha)) { @@ -189,7 +190,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) spin_unlock_irqrestore(&ha->hardware_lock, flags); ha->flags.mbox_busy = 0; - ql_dbg(ql_dbg_mbx, base_vha, 0x1012, + ql_dbg(ql_dbg_mbx, vha, 0x1012, "Pending mailbox timeout, exiting.\n"); rval = QLA_FUNCTION_TIMEOUT; goto premature_exit; @@ -214,7 +215,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) command == MBC_LOAD_RISC_RAM_EXTENDED)) msleep(10); } /* while */ - ql_dbg(ql_dbg_mbx, base_vha, 0x1013, + ql_dbg(ql_dbg_mbx, vha, 0x1013, "Waited %d sec.\n", (uint)((jiffies - (wait_time - (mcp->tov * HZ)))/HZ)); } @@ -223,7 +224,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) if (ha->flags.mbox_int) { uint16_t *iptr2; - ql_dbg(ql_dbg_mbx, base_vha, 0x1014, + ql_dbg(ql_dbg_mbx, vha, 0x1014, "Cmd=%x completed.\n", command); /* Got interrupt. Clear the flag. */ @@ -236,7 +237,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) mcp->mb[0] = MBS_LINK_DOWN_ERROR; ha->mcp = NULL; rval = QLA_FUNCTION_FAILED; - ql_log(ql_log_warn, base_vha, 0x1015, + ql_log(ql_log_warn, vha, 0x1015, "FW hung = %d.\n", ha->flags.isp82xx_fw_hung); goto premature_exit; } @@ -268,13 +269,19 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) mb0 = RD_MAILBOX_REG(ha, ®->isp, 0); ictrl = RD_REG_WORD(®->isp.ictrl); } - ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1119, + ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1119, "MBX Command timeout for cmd %x.\n", command); - ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x111a, + ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111a, "iocontrol=%x jiffies=%lx.\n", ictrl, jiffies); - ql_dbg(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x111b, + ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111b, "mb[0] = 0x%x.\n", mb0); - ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, base_vha, 0x1019); + ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1019); + + /* + * Attempt to capture a firmware dump for further analysis + * of the current firmware state + */ + ha->isp_ops->fw_dump(vha, 0); rval = QLA_FUNCTION_TIMEOUT; } @@ -285,7 +292,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) ha->mcp = NULL; if ((abort_active || !io_lock_on) && !IS_NOPOLLING_TYPE(ha)) { - ql_dbg(ql_dbg_mbx, base_vha, 0x101a, + ql_dbg(ql_dbg_mbx, vha, 0x101a, "Checking for additional resp interrupt.\n"); /* polling mode for non isp_abort commands. */ @@ -297,7 +304,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) if (!io_lock_on || (mcp->flags & IOCTL_CMD) || ha->flags.eeh_busy) { /* not in dpc. schedule it for dpc to take over. */ - ql_dbg(ql_dbg_mbx, base_vha, 0x101b, + ql_dbg(ql_dbg_mbx, vha, 0x101b, "Timeout, schedule isp_abort_needed.\n"); if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) && @@ -313,15 +320,16 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) CRB_NIU_XG_PAUSE_CTL_P1); } ql_log(ql_log_info, base_vha, 0x101c, - "Mailbox cmd timeout occured. " - "Scheduling ISP abort eeh_busy=0x%x.\n", - ha->flags.eeh_busy); + "Mailbox cmd timeout occured, cmd=0x%x, " + "mb[0]=0x%x, eeh_busy=0x%x. Scheduling ISP " + "abort.\n", command, mcp->mb[0], + ha->flags.eeh_busy); set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); qla2xxx_wake_dpc(vha); } } else if (!abort_active) { /* call abort directly since we are in the DPC thread */ - ql_dbg(ql_dbg_mbx, base_vha, 0x101d, + ql_dbg(ql_dbg_mbx, vha, 0x101d, "Timeout, calling abort_isp.\n"); if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) && @@ -337,9 +345,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) CRB_NIU_XG_PAUSE_CTL_P1); } ql_log(ql_log_info, base_vha, 0x101e, - "Mailbox cmd timeout occured. " - "Scheduling ISP abort.\n"); - + "Mailbox cmd timeout occured, cmd=0x%x, " + "mb[0]=0x%x. Scheduling ISP abort ", + command, mcp->mb[0]); set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags); clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); /* Allow next mbx cmd to come in. */ @@ -350,7 +358,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) &vha->dpc_flags); } clear_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags); - ql_dbg(ql_dbg_mbx, base_vha, 0x101f, + ql_dbg(ql_dbg_mbx, vha, 0x101f, "Finished abort_isp.\n"); goto mbx_done; } @@ -364,8 +372,8 @@ premature_exit: mbx_done: if (rval) { ql_dbg(ql_dbg_mbx, base_vha, 0x1020, - "**** Failed mbx[0]=%x, mb[1]=%x, mb[2]=%x, cmd=%x ****.\n", - mcp->mb[0], mcp->mb[1], mcp->mb[2], command); + "**** Failed mbx[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x, cmd=%x ****.\n", + mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], command); } else { ql_dbg(ql_dbg_mbx, base_vha, 0x1021, "Done %s.\n", __func__); } @@ -455,7 +463,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) mcp->mb[1] = MSW(risc_addr); mcp->mb[2] = LSW(risc_addr); mcp->mb[3] = 0; - if (IS_QLA81XX(ha)) { + if (IS_QLA81XX(ha) || IS_QLA83XX(ha)) { struct nvram_81xx *nv = ha->nvram; mcp->mb[4] = (nv->enhanced_features & EXTENDED_BB_CREDITS); @@ -508,21 +516,22 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) * Kernel context. */ int -qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor, - uint16_t *subminor, uint16_t *attributes, uint32_t *memory, uint8_t *mpi, - uint32_t *mpi_caps, uint8_t *phy) +qla2x00_get_fw_version(scsi_qla_host_t *vha) { int rval; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; + struct qla_hw_data *ha = vha->hw; ql_dbg(ql_dbg_mbx, vha, 0x1029, "Entered %s.\n", __func__); mcp->mb[0] = MBC_GET_FIRMWARE_VERSION; mcp->out_mb = MBX_0; mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; - if (IS_QLA81XX(vha->hw)) + if (IS_QLA81XX(vha->hw) || IS_QLA8031(ha)) mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8; + if (IS_QLA83XX(vha->hw)) + mcp->in_mb |= MBX_17|MBX_16|MBX_15; mcp->flags = 0; mcp->tov = MBX_TOV_SECONDS; rval = qla2x00_mailbox_command(vha, mcp); @@ -530,23 +539,37 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor, goto failed; /* Return mailbox data. */ - *major = mcp->mb[1]; - *minor = mcp->mb[2]; - *subminor = mcp->mb[3]; - *attributes = mcp->mb[6]; + ha->fw_major_version = mcp->mb[1]; + ha->fw_minor_version = mcp->mb[2]; + ha->fw_subminor_version = mcp->mb[3]; + ha->fw_attributes = mcp->mb[6]; if (IS_QLA2100(vha->hw) || IS_QLA2200(vha->hw)) - *memory = 0x1FFFF; /* Defaults to 128KB. */ + ha->fw_memory_size = 0x1FFFF; /* Defaults to 128KB. */ else - *memory = (mcp->mb[5] << 16) | mcp->mb[4]; - if (IS_QLA81XX(vha->hw)) { - mpi[0] = mcp->mb[10] & 0xff; - mpi[1] = mcp->mb[11] >> 8; - mpi[2] = mcp->mb[11] & 0xff; - *mpi_caps = (mcp->mb[12] << 16) | mcp->mb[13]; - phy[0] = mcp->mb[8] & 0xff; - phy[1] = mcp->mb[9] >> 8; - phy[2] = mcp->mb[9] & 0xff; + ha->fw_memory_size = (mcp->mb[5] << 16) | mcp->mb[4]; + if (IS_QLA81XX(vha->hw) || IS_QLA8031(vha->hw)) { + ha->mpi_version[0] = mcp->mb[10] & 0xff; + ha->mpi_version[1] = mcp->mb[11] >> 8; + ha->mpi_version[2] = mcp->mb[11] & 0xff; + ha->mpi_capabilities = (mcp->mb[12] << 16) | mcp->mb[13]; + ha->phy_version[0] = mcp->mb[8] & 0xff; + ha->phy_version[1] = mcp->mb[9] >> 8; + ha->phy_version[2] = mcp->mb[9] & 0xff; + } + if (IS_QLA83XX(ha)) { + if (mcp->mb[6] & BIT_15) { + ha->fw_attributes_h = mcp->mb[15]; + ha->fw_attributes_ext[0] = mcp->mb[16]; + ha->fw_attributes_ext[1] = mcp->mb[17]; + ql_dbg(ql_dbg_mbx, vha, 0x1139, + "%s: FW_attributes Upper: 0x%x, Lower: 0x%x.\n", + __func__, mcp->mb[15], mcp->mb[6]); + } else + ql_dbg(ql_dbg_mbx, vha, 0x112f, + "%s: FwAttributes [Upper] invalid, MB6:%04x\n", + __func__, mcp->mb[6]); } + failed: if (rval != QLA_SUCCESS) { /*EMPTY*/ @@ -859,6 +882,7 @@ qla2x00_abort_command(srb_t *sp) scsi_qla_host_t *vha = fcport->vha; struct qla_hw_data *ha = vha->hw; struct req_que *req = vha->req; + struct scsi_cmnd *cmd = GET_CMD_SP(sp); ql_dbg(ql_dbg_mbx, vha, 0x103b, "Entered %s.\n", __func__); @@ -881,7 +905,7 @@ qla2x00_abort_command(srb_t *sp) mcp->mb[1] = fcport->loop_id << 8; mcp->mb[2] = (uint16_t)handle; mcp->mb[3] = (uint16_t)(handle >> 16); - mcp->mb[6] = (uint16_t)sp->cmd->device->lun; + mcp->mb[6] = (uint16_t)cmd->device->lun; mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; mcp->in_mb = MBX_0; mcp->tov = MBX_TOV_SECONDS; @@ -1028,7 +1052,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, mcp->mb[9] = vha->vp_idx; mcp->out_mb = MBX_9|MBX_0; mcp->in_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; - if (IS_QLA8XXX_TYPE(vha->hw)) + if (IS_CNA_CAPABLE(vha->hw)) mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10; mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; @@ -1052,7 +1076,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, } else { ql_dbg(ql_dbg_mbx, vha, 0x1048, "Done %s.\n", __func__); - if (IS_QLA8XXX_TYPE(vha->hw)) { + if (IS_CNA_CAPABLE(vha->hw)) { vha->fcoe_vlan_id = mcp->mb[9] & 0xfff; vha->fcoe_fcf_idx = mcp->mb[10]; vha->fcoe_vn_port_mac[5] = mcp->mb[11] >> 8; @@ -1163,7 +1187,7 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size) mcp->mb[6] = MSW(MSD(ha->init_cb_dma)); mcp->mb[7] = LSW(MSD(ha->init_cb_dma)); mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; - if (IS_QLA81XX(ha) && ha->ex_init_cb->ex_version) { + if ((IS_QLA81XX(ha) || IS_QLA83XX(ha)) && ha->ex_init_cb->ex_version) { mcp->mb[1] = BIT_0; mcp->mb[10] = MSW(ha->ex_init_cb_dma); mcp->mb[11] = LSW(ha->ex_init_cb_dma); @@ -1172,7 +1196,11 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size) mcp->mb[14] = sizeof(*ha->ex_init_cb); mcp->out_mb |= MBX_14|MBX_13|MBX_12|MBX_11|MBX_10; } - mcp->in_mb = MBX_0; + /* 1 and 2 should normally be captured. */ + mcp->in_mb = MBX_2|MBX_1|MBX_0; + if (IS_QLA83XX(ha)) + /* mb3 is additional info about the installed SFP. */ + mcp->in_mb |= MBX_3; mcp->buf_size = size; mcp->flags = MBX_DMA_OUT; mcp->tov = MBX_TOV_SECONDS; @@ -1181,7 +1209,8 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size) if (rval != QLA_SUCCESS) { /*EMPTY*/ ql_dbg(ql_dbg_mbx, vha, 0x104d, - "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); + "Failed=%x mb[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x,.\n", + rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3]); } else { /*EMPTY*/ ql_dbg(ql_dbg_mbx, vha, 0x104e, "Done %s.\n", __func__); @@ -1260,6 +1289,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) goto gpd_error_out; if (IS_FWI2_CAPABLE(ha)) { + uint64_t zero = 0; pd24 = (struct port_database_24xx *) pd; /* Check for logged in state. */ @@ -1273,6 +1303,14 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) goto gpd_error_out; } + if (fcport->loop_id == FC_NO_LOOP_ID || + (memcmp(fcport->port_name, (uint8_t *)&zero, 8) && + memcmp(fcport->port_name, pd24->port_name, 8))) { + /* We lost the device mid way. */ + rval = QLA_NOT_LOGGED_IN; + 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); @@ -1289,6 +1327,8 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) else fcport->port_type = FCT_TARGET; } else { + uint64_t zero = 0; + /* Check for logged in state. */ if (pd->master_state != PD_STATE_PORT_LOGGED_IN && pd->slave_state != PD_STATE_PORT_LOGGED_IN) { @@ -1301,6 +1341,14 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) goto gpd_error_out; } + if (fcport->loop_id == FC_NO_LOOP_ID || + (memcmp(fcport->port_name, (uint8_t *)&zero, 8) && + memcmp(fcport->port_name, pd->port_name, 8))) { + /* We lost the device mid way. */ + rval = QLA_NOT_LOGGED_IN; + 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); @@ -1481,7 +1529,7 @@ qla2x00_lip_reset(scsi_qla_host_t *vha) ql_dbg(ql_dbg_mbx, vha, 0x105a, "Entered %s.\n", __func__); - if (IS_QLA8XXX_TYPE(vha->hw)) { + if (IS_CNA_CAPABLE(vha->hw)) { /* Logout across all FCFs. */ mcp->mb[0] = MBC_LIP_FULL_LOGIN; mcp->mb[1] = BIT_1; @@ -1622,7 +1670,8 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, lg->port_id[1] = area; lg->port_id[2] = domain; lg->vp_index = vha->vp_idx; - rval = qla2x00_issue_iocb(vha, lg, lg_dma, 0); + rval = qla2x00_issue_iocb_timeout(vha, lg, lg_dma, 0, + (ha->r_a_tov / 10 * 2) + 2); if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x1063, "Failed to issue login IOCB (%x).\n", rval); @@ -1885,8 +1934,8 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, lg->port_id[1] = area; lg->port_id[2] = domain; lg->vp_index = vha->vp_idx; - - rval = qla2x00_issue_iocb(vha, lg, lg_dma, 0); + rval = qla2x00_issue_iocb_timeout(vha, lg, lg_dma, 0, + (ha->r_a_tov / 10 * 2) + 2); if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x106f, "Failed to issue logout IOCB (%x).\n", rval); @@ -2094,7 +2143,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt, mcp->mb[0] = MBC_GET_RESOURCE_COUNTS; mcp->out_mb = MBX_0; mcp->in_mb = MBX_11|MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; - if (IS_QLA81XX(vha->hw)) + if (IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw)) mcp->in_mb |= MBX_12; mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; @@ -2121,7 +2170,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt, *orig_iocb_cnt = mcp->mb[10]; if (vha->hw->flags.npiv_supported && max_npiv_vports) *max_npiv_vports = mcp->mb[11]; - if (IS_QLA81XX(vha->hw) && max_fcfs) + if ((IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw)) && max_fcfs) *max_fcfs = mcp->mb[12]; } @@ -2686,7 +2735,8 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma, ql_dbg(ql_dbg_mbx, vha, 0x10aa, "Entered %s.\n", __func__); - if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw)) + if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw) && + !IS_QLA83XX(vha->hw)) return QLA_FUNCTION_FAILED; if (unlikely(pci_channel_offline(vha->hw->pdev))) @@ -2828,7 +2878,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, mcp->mb[0] = MBC_PORT_PARAMS; mcp->mb[1] = loop_id; mcp->mb[2] = BIT_0; - if (IS_QLA8XXX_TYPE(vha->hw)) + if (IS_CNA_CAPABLE(vha->hw)) mcp->mb[3] = port_speed & (BIT_5|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0); else mcp->mb[3] = port_speed & (BIT_2|BIT_1|BIT_0); @@ -3298,6 +3348,8 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req) mcp->mb[12] = req->qos; mcp->mb[11] = req->vp_idx; mcp->mb[13] = req->rid; + if (IS_QLA83XX(ha)) + mcp->mb[15] = 0; reg = (struct device_reg_25xxmq *)((void *)(ha->mqiobase) + QLA_QUE_PAGE * req->id); @@ -3311,12 +3363,21 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req) MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; mcp->in_mb = MBX_0; mcp->flags = MBX_DMA_OUT; - mcp->tov = 60; + mcp->tov = MBX_TOV_SECONDS * 2; + + if (IS_QLA81XX(ha) || IS_QLA83XX(ha)) + mcp->in_mb |= MBX_1; + if (IS_QLA83XX(ha)) { + mcp->out_mb |= MBX_15; + /* debug q create issue in SR-IOV */ + mcp->in_mb |= MBX_9 | MBX_8 | MBX_7; + } spin_lock_irqsave(&ha->hardware_lock, flags); if (!(req->options & BIT_0)) { WRT_REG_DWORD(®->req_q_in, 0); - WRT_REG_DWORD(®->req_q_out, 0); + if (!IS_QLA83XX(ha)) + WRT_REG_DWORD(®->req_q_out, 0); } req->req_q_in = ®->req_q_in; req->req_q_out = ®->req_q_out; @@ -3354,6 +3415,8 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) mcp->mb[5] = rsp->length; mcp->mb[14] = rsp->msix->entry; mcp->mb[13] = rsp->rid; + if (IS_QLA83XX(ha)) + mcp->mb[15] = 0; reg = (struct device_reg_25xxmq *)((void *)(ha->mqiobase) + QLA_QUE_PAGE * rsp->id); @@ -3367,12 +3430,23 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) |MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; mcp->in_mb = MBX_0; mcp->flags = MBX_DMA_OUT; - mcp->tov = 60; + mcp->tov = MBX_TOV_SECONDS * 2; + + if (IS_QLA81XX(ha)) { + mcp->out_mb |= MBX_12|MBX_11|MBX_10; + mcp->in_mb |= MBX_1; + } else if (IS_QLA83XX(ha)) { + mcp->out_mb |= MBX_15|MBX_12|MBX_11|MBX_10; + mcp->in_mb |= MBX_1; + /* debug q create issue in SR-IOV */ + mcp->in_mb |= MBX_9 | MBX_8 | MBX_7; + } spin_lock_irqsave(&ha->hardware_lock, flags); if (!(rsp->options & BIT_0)) { WRT_REG_DWORD(®->rsp_q_out, 0); - WRT_REG_DWORD(®->rsp_q_in, 0); + if (!IS_QLA83XX(ha)) + WRT_REG_DWORD(®->rsp_q_in, 0); } spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -3424,7 +3498,7 @@ qla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size) ql_dbg(ql_dbg_mbx, vha, 0x10dc, "Entered %s.\n", __func__); - if (!IS_QLA81XX(vha->hw)) + if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw)) return QLA_FUNCTION_FAILED; mcp->mb[0] = MBC_FLASH_ACCESS_CTRL; @@ -3454,7 +3528,7 @@ qla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_QLA81XX(vha->hw)) + if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx, vha, 0x10df, "Entered %s.\n", __func__); @@ -3486,7 +3560,7 @@ qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_QLA81XX(vha->hw)) + if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx, vha, 0x10e2, "Entered %s.\n", __func__); @@ -3641,7 +3715,7 @@ qla2x00_get_xgmac_stats(scsi_qla_host_t *vha, dma_addr_t stats_dma, ql_dbg(ql_dbg_mbx, vha, 0x10ee, "Entered %s.\n", __func__); - if (!IS_QLA8XXX_TYPE(vha->hw)) + if (!IS_CNA_CAPABLE(vha->hw)) return QLA_FUNCTION_FAILED; mcp->mb[0] = MBC_GET_XGMAC_STATS; @@ -3680,7 +3754,7 @@ qla2x00_get_dcbx_params(scsi_qla_host_t *vha, dma_addr_t tlv_dma, ql_dbg(ql_dbg_mbx, vha, 0x10f1, "Entered %s.\n", __func__); - if (!IS_QLA8XXX_TYPE(vha->hw)) + if (!IS_CNA_CAPABLE(vha->hw)) return QLA_FUNCTION_FAILED; mcp->mb[0] = MBC_GET_DCBX_PARAMS; @@ -3775,7 +3849,7 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15| MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0; - if (IS_QLA8XXX_TYPE(vha->hw)) + if (IS_CNA_CAPABLE(vha->hw)) mcp->out_mb |= MBX_2; mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0; @@ -3813,7 +3887,7 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, memset(mcp->mb, 0 , sizeof(mcp->mb)); mcp->mb[0] = MBC_DIAGNOSTIC_ECHO; mcp->mb[1] = mreq->options | BIT_6; /* BIT_6 specifies 64bit address */ - if (IS_QLA8XXX_TYPE(ha)) { + if (IS_CNA_CAPABLE(ha)) { mcp->mb[1] |= BIT_15; mcp->mb[2] = vha->fcoe_fcf_idx; } @@ -3831,13 +3905,14 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15| MBX_14|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0; - if (IS_QLA8XXX_TYPE(ha)) + if (IS_CNA_CAPABLE(ha)) mcp->out_mb |= MBX_2; mcp->in_mb = MBX_0; - if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || IS_QLA8XXX_TYPE(ha)) + if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || + IS_CNA_CAPABLE(ha) || IS_QLA2031(ha)) mcp->in_mb |= MBX_1; - if (IS_QLA8XXX_TYPE(ha)) + if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha)) mcp->in_mb |= MBX_3; mcp->tov = MBX_TOV_SECONDS; @@ -3976,6 +4051,7 @@ qla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb) return rval; } + int qla2x00_get_data_rate(scsi_qla_host_t *vha) { @@ -3993,6 +4069,8 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha) mcp->mb[1] = 0; mcp->out_mb = MBX_1|MBX_0; mcp->in_mb = MBX_2|MBX_1|MBX_0; + if (IS_QLA83XX(ha)) + mcp->in_mb |= MBX_3; mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; rval = qla2x00_mailbox_command(vha, mcp); @@ -4018,7 +4096,7 @@ qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb) ql_dbg(ql_dbg_mbx, vha, 0x1109, "Entered %s.\n", __func__); - if (!IS_QLA81XX(ha)) + if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha)) return QLA_FUNCTION_FAILED; mcp->mb[0] = MBC_GET_PORT_CONFIG; mcp->out_mb = MBX_0; @@ -4299,6 +4377,90 @@ qla82xx_md_get_template(scsi_qla_host_t *vha) } int +qla81xx_set_led_config(scsi_qla_host_t *vha, uint16_t *led_cfg) +{ + int rval; + struct qla_hw_data *ha = vha->hw; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) + return QLA_FUNCTION_FAILED; + + ql_dbg(ql_dbg_mbx, vha, 0x1133, "Entered %s.\n", __func__); + + memset(mcp, 0, sizeof(mbx_cmd_t)); + mcp->mb[0] = MBC_SET_LED_CONFIG; + mcp->mb[1] = led_cfg[0]; + mcp->mb[2] = led_cfg[1]; + if (IS_QLA8031(ha)) { + mcp->mb[3] = led_cfg[2]; + mcp->mb[4] = led_cfg[3]; + mcp->mb[5] = led_cfg[4]; + mcp->mb[6] = led_cfg[5]; + } + + mcp->out_mb = MBX_2|MBX_1|MBX_0; + if (IS_QLA8031(ha)) + mcp->out_mb |= MBX_6|MBX_5|MBX_4|MBX_3; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + + rval = qla2x00_mailbox_command(vha, mcp); + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x1134, + "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); + } else { + ql_dbg(ql_dbg_mbx, vha, 0x1135, "Done %s.\n", __func__); + } + + return rval; +} + +int +qla81xx_get_led_config(scsi_qla_host_t *vha, uint16_t *led_cfg) +{ + int rval; + struct qla_hw_data *ha = vha->hw; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) + return QLA_FUNCTION_FAILED; + + ql_dbg(ql_dbg_mbx, vha, 0x1136, "Entered %s.\n", __func__); + + memset(mcp, 0, sizeof(mbx_cmd_t)); + mcp->mb[0] = MBC_GET_LED_CONFIG; + + mcp->out_mb = MBX_0; + mcp->in_mb = MBX_2|MBX_1|MBX_0; + if (IS_QLA8031(ha)) + mcp->in_mb |= MBX_6|MBX_5|MBX_4|MBX_3; + mcp->tov = 30; + mcp->flags = 0; + + rval = qla2x00_mailbox_command(vha, mcp); + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x1137, + "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); + } else { + led_cfg[0] = mcp->mb[1]; + led_cfg[1] = mcp->mb[2]; + if (IS_QLA8031(ha)) { + led_cfg[2] = mcp->mb[3]; + led_cfg[3] = mcp->mb[4]; + led_cfg[4] = mcp->mb[5]; + led_cfg[5] = mcp->mb[6]; + } + ql_dbg(ql_dbg_mbx, vha, 0x1138, "Done %s.\n", __func__); + } + + return rval; +} + +int qla82xx_mbx_beacon_ctl(scsi_qla_host_t *vha, int enable) { int rval; @@ -4321,7 +4483,7 @@ qla82xx_mbx_beacon_ctl(scsi_qla_host_t *vha, int enable) mcp->out_mb = MBX_7|MBX_0; mcp->in_mb = MBX_0; - mcp->tov = 30; + mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; rval = qla2x00_mailbox_command(vha, mcp); @@ -4335,3 +4497,75 @@ qla82xx_mbx_beacon_ctl(scsi_qla_host_t *vha, int enable) return rval; } + +int +qla83xx_write_remote_reg(scsi_qla_host_t *vha, uint32_t reg, uint32_t data) +{ + int rval; + struct qla_hw_data *ha = vha->hw; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + if (!IS_QLA83XX(ha)) + return QLA_FUNCTION_FAILED; + + ql_dbg(ql_dbg_mbx, vha, 0x1130, "Entered %s.\n", __func__); + + mcp->mb[0] = MBC_WRITE_REMOTE_REG; + mcp->mb[1] = LSW(reg); + mcp->mb[2] = MSW(reg); + mcp->mb[3] = LSW(data); + mcp->mb[4] = MSW(data); + mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + + mcp->in_mb = MBX_1|MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x1131, + "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); + } else { + ql_dbg(ql_dbg_mbx, vha, 0x1132, + "Done %s.\n", __func__); + } + + return rval; +} + +int +qla2x00_port_logout(scsi_qla_host_t *vha, struct fc_port *fcport) +{ + int rval; + struct qla_hw_data *ha = vha->hw; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + if (IS_QLA2100(ha) || IS_QLA2200(ha)) { + ql_dbg(ql_dbg_mbx, vha, 0x113b, + "Implicit LOGO Unsupported.\n"); + return QLA_FUNCTION_FAILED; + } + + + ql_dbg(ql_dbg_mbx, vha, 0x113c, "Done %s.\n", __func__); + + /* Perform Implicit LOGO. */ + mcp->mb[0] = MBC_PORT_LOGOUT; + mcp->mb[1] = fcport->loop_id; + mcp->mb[10] = BIT_15; + mcp->out_mb = MBX_10|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + if (rval != QLA_SUCCESS) + ql_dbg(ql_dbg_mbx, vha, 0x113d, + "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); + else + ql_dbg(ql_dbg_mbx, vha, 0x113e, "Done %s.\n", __func__); + + return rval; +} + |