162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * QLogic Fibre Channel HBA Driver 462306a36Sopenharmony_ci * Copyright (c) 2003-2014 QLogic Corporation 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#include "qla_def.h" 762306a36Sopenharmony_ci#include "qla_target.h" 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/delay.h> 1062306a36Sopenharmony_ci#include <linux/gfp.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#ifdef CONFIG_PPC 1362306a36Sopenharmony_ci#define IS_PPCARCH true 1462306a36Sopenharmony_ci#else 1562306a36Sopenharmony_ci#define IS_PPCARCH false 1662306a36Sopenharmony_ci#endif 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic struct mb_cmd_name { 1962306a36Sopenharmony_ci uint16_t cmd; 2062306a36Sopenharmony_ci const char *str; 2162306a36Sopenharmony_ci} mb_str[] = { 2262306a36Sopenharmony_ci {MBC_GET_PORT_DATABASE, "GPDB"}, 2362306a36Sopenharmony_ci {MBC_GET_ID_LIST, "GIDList"}, 2462306a36Sopenharmony_ci {MBC_GET_LINK_PRIV_STATS, "Stats"}, 2562306a36Sopenharmony_ci {MBC_GET_RESOURCE_COUNTS, "ResCnt"}, 2662306a36Sopenharmony_ci}; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic const char *mb_to_str(uint16_t cmd) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci int i; 3162306a36Sopenharmony_ci struct mb_cmd_name *e; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mb_str); i++) { 3462306a36Sopenharmony_ci e = mb_str + i; 3562306a36Sopenharmony_ci if (cmd == e->cmd) 3662306a36Sopenharmony_ci return e->str; 3762306a36Sopenharmony_ci } 3862306a36Sopenharmony_ci return "unknown"; 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic struct rom_cmd { 4262306a36Sopenharmony_ci uint16_t cmd; 4362306a36Sopenharmony_ci} rom_cmds[] = { 4462306a36Sopenharmony_ci { MBC_LOAD_RAM }, 4562306a36Sopenharmony_ci { MBC_EXECUTE_FIRMWARE }, 4662306a36Sopenharmony_ci { MBC_READ_RAM_WORD }, 4762306a36Sopenharmony_ci { MBC_MAILBOX_REGISTER_TEST }, 4862306a36Sopenharmony_ci { MBC_VERIFY_CHECKSUM }, 4962306a36Sopenharmony_ci { MBC_GET_FIRMWARE_VERSION }, 5062306a36Sopenharmony_ci { MBC_LOAD_RISC_RAM }, 5162306a36Sopenharmony_ci { MBC_DUMP_RISC_RAM }, 5262306a36Sopenharmony_ci { MBC_LOAD_RISC_RAM_EXTENDED }, 5362306a36Sopenharmony_ci { MBC_DUMP_RISC_RAM_EXTENDED }, 5462306a36Sopenharmony_ci { MBC_WRITE_RAM_WORD_EXTENDED }, 5562306a36Sopenharmony_ci { MBC_READ_RAM_EXTENDED }, 5662306a36Sopenharmony_ci { MBC_GET_RESOURCE_COUNTS }, 5762306a36Sopenharmony_ci { MBC_SET_FIRMWARE_OPTION }, 5862306a36Sopenharmony_ci { MBC_MID_INITIALIZE_FIRMWARE }, 5962306a36Sopenharmony_ci { MBC_GET_FIRMWARE_STATE }, 6062306a36Sopenharmony_ci { MBC_GET_MEM_OFFLOAD_CNTRL_STAT }, 6162306a36Sopenharmony_ci { MBC_GET_RETRY_COUNT }, 6262306a36Sopenharmony_ci { MBC_TRACE_CONTROL }, 6362306a36Sopenharmony_ci { MBC_INITIALIZE_MULTIQ }, 6462306a36Sopenharmony_ci { MBC_IOCB_COMMAND_A64 }, 6562306a36Sopenharmony_ci { MBC_GET_ADAPTER_LOOP_ID }, 6662306a36Sopenharmony_ci { MBC_READ_SFP }, 6762306a36Sopenharmony_ci { MBC_SET_RNID_PARAMS }, 6862306a36Sopenharmony_ci { MBC_GET_RNID_PARAMS }, 6962306a36Sopenharmony_ci { MBC_GET_SET_ZIO_THRESHOLD }, 7062306a36Sopenharmony_ci}; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistatic int is_rom_cmd(uint16_t cmd) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci int i; 7562306a36Sopenharmony_ci struct rom_cmd *wc; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(rom_cmds); i++) { 7862306a36Sopenharmony_ci wc = rom_cmds + i; 7962306a36Sopenharmony_ci if (wc->cmd == cmd) 8062306a36Sopenharmony_ci return 1; 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci return 0; 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/* 8762306a36Sopenharmony_ci * qla2x00_mailbox_command 8862306a36Sopenharmony_ci * Issue mailbox command and waits for completion. 8962306a36Sopenharmony_ci * 9062306a36Sopenharmony_ci * Input: 9162306a36Sopenharmony_ci * ha = adapter block pointer. 9262306a36Sopenharmony_ci * mcp = driver internal mbx struct pointer. 9362306a36Sopenharmony_ci * 9462306a36Sopenharmony_ci * Output: 9562306a36Sopenharmony_ci * mb[MAX_MAILBOX_REGISTER_COUNT] = returned mailbox data. 9662306a36Sopenharmony_ci * 9762306a36Sopenharmony_ci * Returns: 9862306a36Sopenharmony_ci * 0 : QLA_SUCCESS = cmd performed success 9962306a36Sopenharmony_ci * 1 : QLA_FUNCTION_FAILED (error encountered) 10062306a36Sopenharmony_ci * 6 : QLA_FUNCTION_TIMEOUT (timeout condition encountered) 10162306a36Sopenharmony_ci * 10262306a36Sopenharmony_ci * Context: 10362306a36Sopenharmony_ci * Kernel context. 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_cistatic int 10662306a36Sopenharmony_ciqla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci int rval, i; 10962306a36Sopenharmony_ci unsigned long flags = 0; 11062306a36Sopenharmony_ci device_reg_t *reg; 11162306a36Sopenharmony_ci uint8_t abort_active, eeh_delay; 11262306a36Sopenharmony_ci uint8_t io_lock_on; 11362306a36Sopenharmony_ci uint16_t command = 0; 11462306a36Sopenharmony_ci uint16_t *iptr; 11562306a36Sopenharmony_ci __le16 __iomem *optr; 11662306a36Sopenharmony_ci uint32_t cnt; 11762306a36Sopenharmony_ci uint32_t mboxes; 11862306a36Sopenharmony_ci unsigned long wait_time; 11962306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 12062306a36Sopenharmony_ci scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); 12162306a36Sopenharmony_ci u32 chip_reset; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1000, "Entered %s.\n", __func__); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci if (ha->pdev->error_state == pci_channel_io_perm_failure) { 12762306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1001, 12862306a36Sopenharmony_ci "PCI channel failed permanently, exiting.\n"); 12962306a36Sopenharmony_ci return QLA_FUNCTION_TIMEOUT; 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci if (vha->device_flags & DFLG_DEV_FAILED) { 13362306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1002, 13462306a36Sopenharmony_ci "Device in failed state, exiting.\n"); 13562306a36Sopenharmony_ci return QLA_FUNCTION_TIMEOUT; 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci /* if PCI error, then avoid mbx processing.*/ 13962306a36Sopenharmony_ci if (test_bit(PFLG_DISCONNECTED, &base_vha->dpc_flags) && 14062306a36Sopenharmony_ci test_bit(UNLOADING, &base_vha->dpc_flags)) { 14162306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0xd04e, 14262306a36Sopenharmony_ci "PCI error, exiting.\n"); 14362306a36Sopenharmony_ci return QLA_FUNCTION_TIMEOUT; 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci eeh_delay = 0; 14662306a36Sopenharmony_ci reg = ha->iobase; 14762306a36Sopenharmony_ci io_lock_on = base_vha->flags.init_done; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci rval = QLA_SUCCESS; 15062306a36Sopenharmony_ci abort_active = test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); 15162306a36Sopenharmony_ci chip_reset = ha->chip_reset; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci if (ha->flags.pci_channel_io_perm_failure) { 15462306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1003, 15562306a36Sopenharmony_ci "Perm failure on EEH timeout MBX, exiting.\n"); 15662306a36Sopenharmony_ci return QLA_FUNCTION_TIMEOUT; 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci if (IS_P3P_TYPE(ha) && ha->flags.isp82xx_fw_hung) { 16062306a36Sopenharmony_ci /* Setting Link-Down error */ 16162306a36Sopenharmony_ci mcp->mb[0] = MBS_LINK_DOWN_ERROR; 16262306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1004, 16362306a36Sopenharmony_ci "FW hung = %d.\n", ha->flags.isp82xx_fw_hung); 16462306a36Sopenharmony_ci return QLA_FUNCTION_TIMEOUT; 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci /* check if ISP abort is active and return cmd with timeout */ 16862306a36Sopenharmony_ci if (((test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) || 16962306a36Sopenharmony_ci test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) || 17062306a36Sopenharmony_ci test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) && 17162306a36Sopenharmony_ci !is_rom_cmd(mcp->mb[0])) || ha->flags.eeh_busy) { 17262306a36Sopenharmony_ci ql_log(ql_log_info, vha, 0x1005, 17362306a36Sopenharmony_ci "Cmd 0x%x aborted with timeout since ISP Abort is pending\n", 17462306a36Sopenharmony_ci mcp->mb[0]); 17562306a36Sopenharmony_ci return QLA_FUNCTION_TIMEOUT; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci atomic_inc(&ha->num_pend_mbx_stage1); 17962306a36Sopenharmony_ci /* 18062306a36Sopenharmony_ci * Wait for active mailbox commands to finish by waiting at most tov 18162306a36Sopenharmony_ci * seconds. This is to serialize actual issuing of mailbox cmds during 18262306a36Sopenharmony_ci * non ISP abort time. 18362306a36Sopenharmony_ci */ 18462306a36Sopenharmony_ci if (!wait_for_completion_timeout(&ha->mbx_cmd_comp, mcp->tov * HZ)) { 18562306a36Sopenharmony_ci /* Timeout occurred. Return error. */ 18662306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0xd035, 18762306a36Sopenharmony_ci "Cmd access timeout, cmd=0x%x, Exiting.\n", 18862306a36Sopenharmony_ci mcp->mb[0]); 18962306a36Sopenharmony_ci vha->hw_err_cnt++; 19062306a36Sopenharmony_ci atomic_dec(&ha->num_pend_mbx_stage1); 19162306a36Sopenharmony_ci return QLA_FUNCTION_TIMEOUT; 19262306a36Sopenharmony_ci } 19362306a36Sopenharmony_ci atomic_dec(&ha->num_pend_mbx_stage1); 19462306a36Sopenharmony_ci if (ha->flags.purge_mbox || chip_reset != ha->chip_reset || 19562306a36Sopenharmony_ci ha->flags.eeh_busy) { 19662306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0xd035, 19762306a36Sopenharmony_ci "Error detected: purge[%d] eeh[%d] cmd=0x%x, Exiting.\n", 19862306a36Sopenharmony_ci ha->flags.purge_mbox, ha->flags.eeh_busy, mcp->mb[0]); 19962306a36Sopenharmony_ci rval = QLA_ABORTED; 20062306a36Sopenharmony_ci goto premature_exit; 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci /* Save mailbox command for debug */ 20562306a36Sopenharmony_ci ha->mcp = mcp; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1006, 20862306a36Sopenharmony_ci "Prepare to issue mbox cmd=0x%x.\n", mcp->mb[0]); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci if (ha->flags.purge_mbox || chip_reset != ha->chip_reset || 21362306a36Sopenharmony_ci ha->flags.mbox_busy) { 21462306a36Sopenharmony_ci rval = QLA_ABORTED; 21562306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 21662306a36Sopenharmony_ci goto premature_exit; 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci ha->flags.mbox_busy = 1; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci /* Load mailbox registers. */ 22162306a36Sopenharmony_ci if (IS_P3P_TYPE(ha)) 22262306a36Sopenharmony_ci optr = ®->isp82.mailbox_in[0]; 22362306a36Sopenharmony_ci else if (IS_FWI2_CAPABLE(ha) && !(IS_P3P_TYPE(ha))) 22462306a36Sopenharmony_ci optr = ®->isp24.mailbox0; 22562306a36Sopenharmony_ci else 22662306a36Sopenharmony_ci optr = MAILBOX_REG(ha, ®->isp, 0); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci iptr = mcp->mb; 22962306a36Sopenharmony_ci command = mcp->mb[0]; 23062306a36Sopenharmony_ci mboxes = mcp->out_mb; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1111, 23362306a36Sopenharmony_ci "Mailbox registers (OUT):\n"); 23462306a36Sopenharmony_ci for (cnt = 0; cnt < ha->mbx_count; cnt++) { 23562306a36Sopenharmony_ci if (IS_QLA2200(ha) && cnt == 8) 23662306a36Sopenharmony_ci optr = MAILBOX_REG(ha, ®->isp, 8); 23762306a36Sopenharmony_ci if (mboxes & BIT_0) { 23862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1112, 23962306a36Sopenharmony_ci "mbox[%d]<-0x%04x\n", cnt, *iptr); 24062306a36Sopenharmony_ci wrt_reg_word(optr, *iptr); 24162306a36Sopenharmony_ci } else { 24262306a36Sopenharmony_ci wrt_reg_word(optr, 0); 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci mboxes >>= 1; 24662306a36Sopenharmony_ci optr++; 24762306a36Sopenharmony_ci iptr++; 24862306a36Sopenharmony_ci } 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1117, 25162306a36Sopenharmony_ci "I/O Address = %p.\n", optr); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci /* Issue set host interrupt command to send cmd out. */ 25462306a36Sopenharmony_ci ha->flags.mbox_int = 0; 25562306a36Sopenharmony_ci clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci /* Unlock mbx registers and wait for interrupt */ 25862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x100f, 25962306a36Sopenharmony_ci "Going to unlock irq & waiting for interrupts. " 26062306a36Sopenharmony_ci "jiffies=%lx.\n", jiffies); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci /* Wait for mbx cmd completion until timeout */ 26362306a36Sopenharmony_ci atomic_inc(&ha->num_pend_mbx_stage2); 26462306a36Sopenharmony_ci if ((!abort_active && io_lock_on) || IS_NOPOLLING_TYPE(ha)) { 26562306a36Sopenharmony_ci set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci if (IS_P3P_TYPE(ha)) 26862306a36Sopenharmony_ci wrt_reg_dword(®->isp82.hint, HINT_MBX_INT_PENDING); 26962306a36Sopenharmony_ci else if (IS_FWI2_CAPABLE(ha)) 27062306a36Sopenharmony_ci wrt_reg_dword(®->isp24.hccr, HCCRX_SET_HOST_INT); 27162306a36Sopenharmony_ci else 27262306a36Sopenharmony_ci wrt_reg_word(®->isp.hccr, HCCR_SET_HOST_INT); 27362306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci wait_time = jiffies; 27662306a36Sopenharmony_ci if (!wait_for_completion_timeout(&ha->mbx_intr_comp, 27762306a36Sopenharmony_ci mcp->tov * HZ)) { 27862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x117a, 27962306a36Sopenharmony_ci "cmd=%x Timeout.\n", command); 28062306a36Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 28162306a36Sopenharmony_ci clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); 28262306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci if (chip_reset != ha->chip_reset) { 28562306a36Sopenharmony_ci eeh_delay = ha->flags.eeh_busy ? 1 : 0; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 28862306a36Sopenharmony_ci ha->flags.mbox_busy = 0; 28962306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, 29062306a36Sopenharmony_ci flags); 29162306a36Sopenharmony_ci atomic_dec(&ha->num_pend_mbx_stage2); 29262306a36Sopenharmony_ci rval = QLA_ABORTED; 29362306a36Sopenharmony_ci goto premature_exit; 29462306a36Sopenharmony_ci } 29562306a36Sopenharmony_ci } else if (ha->flags.purge_mbox || 29662306a36Sopenharmony_ci chip_reset != ha->chip_reset) { 29762306a36Sopenharmony_ci eeh_delay = ha->flags.eeh_busy ? 1 : 0; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 30062306a36Sopenharmony_ci ha->flags.mbox_busy = 0; 30162306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 30262306a36Sopenharmony_ci atomic_dec(&ha->num_pend_mbx_stage2); 30362306a36Sopenharmony_ci rval = QLA_ABORTED; 30462306a36Sopenharmony_ci goto premature_exit; 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci if (time_after(jiffies, wait_time + 5 * HZ)) 30862306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1015, "cmd=0x%x, waited %d msecs\n", 30962306a36Sopenharmony_ci command, jiffies_to_msecs(jiffies - wait_time)); 31062306a36Sopenharmony_ci } else { 31162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1011, 31262306a36Sopenharmony_ci "Cmd=%x Polling Mode.\n", command); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci if (IS_P3P_TYPE(ha)) { 31562306a36Sopenharmony_ci if (rd_reg_dword(®->isp82.hint) & 31662306a36Sopenharmony_ci HINT_MBX_INT_PENDING) { 31762306a36Sopenharmony_ci ha->flags.mbox_busy = 0; 31862306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, 31962306a36Sopenharmony_ci flags); 32062306a36Sopenharmony_ci atomic_dec(&ha->num_pend_mbx_stage2); 32162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1012, 32262306a36Sopenharmony_ci "Pending mailbox timeout, exiting.\n"); 32362306a36Sopenharmony_ci vha->hw_err_cnt++; 32462306a36Sopenharmony_ci rval = QLA_FUNCTION_TIMEOUT; 32562306a36Sopenharmony_ci goto premature_exit; 32662306a36Sopenharmony_ci } 32762306a36Sopenharmony_ci wrt_reg_dword(®->isp82.hint, HINT_MBX_INT_PENDING); 32862306a36Sopenharmony_ci } else if (IS_FWI2_CAPABLE(ha)) 32962306a36Sopenharmony_ci wrt_reg_dword(®->isp24.hccr, HCCRX_SET_HOST_INT); 33062306a36Sopenharmony_ci else 33162306a36Sopenharmony_ci wrt_reg_word(®->isp.hccr, HCCR_SET_HOST_INT); 33262306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci wait_time = jiffies + mcp->tov * HZ; /* wait at most tov secs */ 33562306a36Sopenharmony_ci while (!ha->flags.mbox_int) { 33662306a36Sopenharmony_ci if (ha->flags.purge_mbox || 33762306a36Sopenharmony_ci chip_reset != ha->chip_reset) { 33862306a36Sopenharmony_ci eeh_delay = ha->flags.eeh_busy ? 1 : 0; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 34162306a36Sopenharmony_ci ha->flags.mbox_busy = 0; 34262306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, 34362306a36Sopenharmony_ci flags); 34462306a36Sopenharmony_ci atomic_dec(&ha->num_pend_mbx_stage2); 34562306a36Sopenharmony_ci rval = QLA_ABORTED; 34662306a36Sopenharmony_ci goto premature_exit; 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci if (time_after(jiffies, wait_time)) 35062306a36Sopenharmony_ci break; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci /* Check for pending interrupts. */ 35362306a36Sopenharmony_ci qla2x00_poll(ha->rsp_q_map[0]); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci if (!ha->flags.mbox_int && 35662306a36Sopenharmony_ci !(IS_QLA2200(ha) && 35762306a36Sopenharmony_ci command == MBC_LOAD_RISC_RAM_EXTENDED)) 35862306a36Sopenharmony_ci msleep(10); 35962306a36Sopenharmony_ci } /* while */ 36062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1013, 36162306a36Sopenharmony_ci "Waited %d sec.\n", 36262306a36Sopenharmony_ci (uint)((jiffies - (wait_time - (mcp->tov * HZ)))/HZ)); 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci atomic_dec(&ha->num_pend_mbx_stage2); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci /* Check whether we timed out */ 36762306a36Sopenharmony_ci if (ha->flags.mbox_int) { 36862306a36Sopenharmony_ci uint16_t *iptr2; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1014, 37162306a36Sopenharmony_ci "Cmd=%x completed.\n", command); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci /* Got interrupt. Clear the flag. */ 37462306a36Sopenharmony_ci ha->flags.mbox_int = 0; 37562306a36Sopenharmony_ci clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci if (IS_P3P_TYPE(ha) && ha->flags.isp82xx_fw_hung) { 37862306a36Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 37962306a36Sopenharmony_ci ha->flags.mbox_busy = 0; 38062306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci /* Setting Link-Down error */ 38362306a36Sopenharmony_ci mcp->mb[0] = MBS_LINK_DOWN_ERROR; 38462306a36Sopenharmony_ci ha->mcp = NULL; 38562306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 38662306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0xd048, 38762306a36Sopenharmony_ci "FW hung = %d.\n", ha->flags.isp82xx_fw_hung); 38862306a36Sopenharmony_ci goto premature_exit; 38962306a36Sopenharmony_ci } 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci if (ha->mailbox_out[0] != MBS_COMMAND_COMPLETE) { 39262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x11ff, 39362306a36Sopenharmony_ci "mb_out[0] = %#x <> %#x\n", ha->mailbox_out[0], 39462306a36Sopenharmony_ci MBS_COMMAND_COMPLETE); 39562306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci /* Load return mailbox registers. */ 39962306a36Sopenharmony_ci iptr2 = mcp->mb; 40062306a36Sopenharmony_ci iptr = (uint16_t *)&ha->mailbox_out[0]; 40162306a36Sopenharmony_ci mboxes = mcp->in_mb; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1113, 40462306a36Sopenharmony_ci "Mailbox registers (IN):\n"); 40562306a36Sopenharmony_ci for (cnt = 0; cnt < ha->mbx_count; cnt++) { 40662306a36Sopenharmony_ci if (mboxes & BIT_0) { 40762306a36Sopenharmony_ci *iptr2 = *iptr; 40862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1114, 40962306a36Sopenharmony_ci "mbox[%d]->0x%04x\n", cnt, *iptr2); 41062306a36Sopenharmony_ci } 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci mboxes >>= 1; 41362306a36Sopenharmony_ci iptr2++; 41462306a36Sopenharmony_ci iptr++; 41562306a36Sopenharmony_ci } 41662306a36Sopenharmony_ci } else { 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci uint16_t mb[8]; 41962306a36Sopenharmony_ci uint32_t ictrl, host_status, hccr; 42062306a36Sopenharmony_ci uint16_t w; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci if (IS_FWI2_CAPABLE(ha)) { 42362306a36Sopenharmony_ci mb[0] = rd_reg_word(®->isp24.mailbox0); 42462306a36Sopenharmony_ci mb[1] = rd_reg_word(®->isp24.mailbox1); 42562306a36Sopenharmony_ci mb[2] = rd_reg_word(®->isp24.mailbox2); 42662306a36Sopenharmony_ci mb[3] = rd_reg_word(®->isp24.mailbox3); 42762306a36Sopenharmony_ci mb[7] = rd_reg_word(®->isp24.mailbox7); 42862306a36Sopenharmony_ci ictrl = rd_reg_dword(®->isp24.ictrl); 42962306a36Sopenharmony_ci host_status = rd_reg_dword(®->isp24.host_status); 43062306a36Sopenharmony_ci hccr = rd_reg_dword(®->isp24.hccr); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0xd04c, 43362306a36Sopenharmony_ci "MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx " 43462306a36Sopenharmony_ci "mb[0-3]=[0x%x 0x%x 0x%x 0x%x] mb7 0x%x host_status 0x%x hccr 0x%x\n", 43562306a36Sopenharmony_ci command, ictrl, jiffies, mb[0], mb[1], mb[2], mb[3], 43662306a36Sopenharmony_ci mb[7], host_status, hccr); 43762306a36Sopenharmony_ci vha->hw_err_cnt++; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci } else { 44062306a36Sopenharmony_ci mb[0] = RD_MAILBOX_REG(ha, ®->isp, 0); 44162306a36Sopenharmony_ci ictrl = rd_reg_word(®->isp.ictrl); 44262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1119, 44362306a36Sopenharmony_ci "MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx " 44462306a36Sopenharmony_ci "mb[0]=0x%x\n", command, ictrl, jiffies, mb[0]); 44562306a36Sopenharmony_ci vha->hw_err_cnt++; 44662306a36Sopenharmony_ci } 44762306a36Sopenharmony_ci ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1019); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci /* Capture FW dump only, if PCI device active */ 45062306a36Sopenharmony_ci if (!pci_channel_offline(vha->hw->pdev)) { 45162306a36Sopenharmony_ci pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w); 45262306a36Sopenharmony_ci if (w == 0xffff || ictrl == 0xffffffff || 45362306a36Sopenharmony_ci (chip_reset != ha->chip_reset)) { 45462306a36Sopenharmony_ci /* This is special case if there is unload 45562306a36Sopenharmony_ci * of driver happening and if PCI device go 45662306a36Sopenharmony_ci * into bad state due to PCI error condition 45762306a36Sopenharmony_ci * then only PCI ERR flag would be set. 45862306a36Sopenharmony_ci * we will do premature exit for above case. 45962306a36Sopenharmony_ci */ 46062306a36Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 46162306a36Sopenharmony_ci ha->flags.mbox_busy = 0; 46262306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, 46362306a36Sopenharmony_ci flags); 46462306a36Sopenharmony_ci rval = QLA_FUNCTION_TIMEOUT; 46562306a36Sopenharmony_ci goto premature_exit; 46662306a36Sopenharmony_ci } 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci /* Attempt to capture firmware dump for further 46962306a36Sopenharmony_ci * anallysis of the current formware state. we do not 47062306a36Sopenharmony_ci * need to do this if we are intentionally generating 47162306a36Sopenharmony_ci * a dump 47262306a36Sopenharmony_ci */ 47362306a36Sopenharmony_ci if (mcp->mb[0] != MBC_GEN_SYSTEM_ERROR) 47462306a36Sopenharmony_ci qla2xxx_dump_fw(vha); 47562306a36Sopenharmony_ci rval = QLA_FUNCTION_TIMEOUT; 47662306a36Sopenharmony_ci } 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 47962306a36Sopenharmony_ci ha->flags.mbox_busy = 0; 48062306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci /* Clean up */ 48362306a36Sopenharmony_ci ha->mcp = NULL; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci if ((abort_active || !io_lock_on) && !IS_NOPOLLING_TYPE(ha)) { 48662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x101a, 48762306a36Sopenharmony_ci "Checking for additional resp interrupt.\n"); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci /* polling mode for non isp_abort commands. */ 49062306a36Sopenharmony_ci qla2x00_poll(ha->rsp_q_map[0]); 49162306a36Sopenharmony_ci } 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci if (rval == QLA_FUNCTION_TIMEOUT && 49462306a36Sopenharmony_ci mcp->mb[0] != MBC_GEN_SYSTEM_ERROR) { 49562306a36Sopenharmony_ci if (!io_lock_on || (mcp->flags & IOCTL_CMD) || 49662306a36Sopenharmony_ci ha->flags.eeh_busy) { 49762306a36Sopenharmony_ci /* not in dpc. schedule it for dpc to take over. */ 49862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x101b, 49962306a36Sopenharmony_ci "Timeout, schedule isp_abort_needed.\n"); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) && 50262306a36Sopenharmony_ci !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && 50362306a36Sopenharmony_ci !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { 50462306a36Sopenharmony_ci if (IS_QLA82XX(ha)) { 50562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x112a, 50662306a36Sopenharmony_ci "disabling pause transmit on port " 50762306a36Sopenharmony_ci "0 & 1.\n"); 50862306a36Sopenharmony_ci qla82xx_wr_32(ha, 50962306a36Sopenharmony_ci QLA82XX_CRB_NIU + 0x98, 51062306a36Sopenharmony_ci CRB_NIU_XG_PAUSE_CTL_P0| 51162306a36Sopenharmony_ci CRB_NIU_XG_PAUSE_CTL_P1); 51262306a36Sopenharmony_ci } 51362306a36Sopenharmony_ci ql_log(ql_log_info, base_vha, 0x101c, 51462306a36Sopenharmony_ci "Mailbox cmd timeout occurred, cmd=0x%x, " 51562306a36Sopenharmony_ci "mb[0]=0x%x, eeh_busy=0x%x. Scheduling ISP " 51662306a36Sopenharmony_ci "abort.\n", command, mcp->mb[0], 51762306a36Sopenharmony_ci ha->flags.eeh_busy); 51862306a36Sopenharmony_ci vha->hw_err_cnt++; 51962306a36Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 52062306a36Sopenharmony_ci qla2xxx_wake_dpc(vha); 52162306a36Sopenharmony_ci } 52262306a36Sopenharmony_ci } else if (current == ha->dpc_thread) { 52362306a36Sopenharmony_ci /* call abort directly since we are in the DPC thread */ 52462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x101d, 52562306a36Sopenharmony_ci "Timeout, calling abort_isp.\n"); 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) && 52862306a36Sopenharmony_ci !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && 52962306a36Sopenharmony_ci !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { 53062306a36Sopenharmony_ci if (IS_QLA82XX(ha)) { 53162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x112b, 53262306a36Sopenharmony_ci "disabling pause transmit on port " 53362306a36Sopenharmony_ci "0 & 1.\n"); 53462306a36Sopenharmony_ci qla82xx_wr_32(ha, 53562306a36Sopenharmony_ci QLA82XX_CRB_NIU + 0x98, 53662306a36Sopenharmony_ci CRB_NIU_XG_PAUSE_CTL_P0| 53762306a36Sopenharmony_ci CRB_NIU_XG_PAUSE_CTL_P1); 53862306a36Sopenharmony_ci } 53962306a36Sopenharmony_ci ql_log(ql_log_info, base_vha, 0x101e, 54062306a36Sopenharmony_ci "Mailbox cmd timeout occurred, cmd=0x%x, " 54162306a36Sopenharmony_ci "mb[0]=0x%x. Scheduling ISP abort ", 54262306a36Sopenharmony_ci command, mcp->mb[0]); 54362306a36Sopenharmony_ci vha->hw_err_cnt++; 54462306a36Sopenharmony_ci set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags); 54562306a36Sopenharmony_ci clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 54662306a36Sopenharmony_ci /* Allow next mbx cmd to come in. */ 54762306a36Sopenharmony_ci complete(&ha->mbx_cmd_comp); 54862306a36Sopenharmony_ci if (ha->isp_ops->abort_isp(vha) && 54962306a36Sopenharmony_ci !ha->flags.eeh_busy) { 55062306a36Sopenharmony_ci /* Failed. retry later. */ 55162306a36Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, 55262306a36Sopenharmony_ci &vha->dpc_flags); 55362306a36Sopenharmony_ci } 55462306a36Sopenharmony_ci clear_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags); 55562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x101f, 55662306a36Sopenharmony_ci "Finished abort_isp.\n"); 55762306a36Sopenharmony_ci goto mbx_done; 55862306a36Sopenharmony_ci } 55962306a36Sopenharmony_ci } 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_cipremature_exit: 56362306a36Sopenharmony_ci /* Allow next mbx cmd to come in. */ 56462306a36Sopenharmony_ci complete(&ha->mbx_cmd_comp); 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_cimbx_done: 56762306a36Sopenharmony_ci if (rval == QLA_ABORTED) { 56862306a36Sopenharmony_ci ql_log(ql_log_info, vha, 0xd035, 56962306a36Sopenharmony_ci "Chip Reset in progress. Purging Mbox cmd=0x%x.\n", 57062306a36Sopenharmony_ci mcp->mb[0]); 57162306a36Sopenharmony_ci } else if (rval) { 57262306a36Sopenharmony_ci if (ql2xextended_error_logging & (ql_dbg_disc|ql_dbg_mbx)) { 57362306a36Sopenharmony_ci pr_warn("%s [%s]-%04x:%ld: **** Failed=%x", QL_MSGHDR, 57462306a36Sopenharmony_ci dev_name(&ha->pdev->dev), 0x1020+0x800, 57562306a36Sopenharmony_ci vha->host_no, rval); 57662306a36Sopenharmony_ci mboxes = mcp->in_mb; 57762306a36Sopenharmony_ci cnt = 4; 57862306a36Sopenharmony_ci for (i = 0; i < ha->mbx_count && cnt; i++, mboxes >>= 1) 57962306a36Sopenharmony_ci if (mboxes & BIT_0) { 58062306a36Sopenharmony_ci printk(" mb[%u]=%x", i, mcp->mb[i]); 58162306a36Sopenharmony_ci cnt--; 58262306a36Sopenharmony_ci } 58362306a36Sopenharmony_ci pr_warn(" cmd=%x ****\n", command); 58462306a36Sopenharmony_ci } 58562306a36Sopenharmony_ci if (IS_FWI2_CAPABLE(ha) && !(IS_P3P_TYPE(ha))) { 58662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1198, 58762306a36Sopenharmony_ci "host_status=%#x intr_ctrl=%#x intr_status=%#x\n", 58862306a36Sopenharmony_ci rd_reg_dword(®->isp24.host_status), 58962306a36Sopenharmony_ci rd_reg_dword(®->isp24.ictrl), 59062306a36Sopenharmony_ci rd_reg_dword(®->isp24.istatus)); 59162306a36Sopenharmony_ci } else { 59262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1206, 59362306a36Sopenharmony_ci "ctrl_status=%#x ictrl=%#x istatus=%#x\n", 59462306a36Sopenharmony_ci rd_reg_word(®->isp.ctrl_status), 59562306a36Sopenharmony_ci rd_reg_word(®->isp.ictrl), 59662306a36Sopenharmony_ci rd_reg_word(®->isp.istatus)); 59762306a36Sopenharmony_ci } 59862306a36Sopenharmony_ci } else { 59962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, base_vha, 0x1021, "Done %s.\n", __func__); 60062306a36Sopenharmony_ci } 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci i = 500; 60362306a36Sopenharmony_ci while (i && eeh_delay && (ha->pci_error_state < QLA_PCI_SLOT_RESET)) { 60462306a36Sopenharmony_ci /* 60562306a36Sopenharmony_ci * The caller of this mailbox encounter pci error. 60662306a36Sopenharmony_ci * Hold the thread until PCIE link reset complete to make 60762306a36Sopenharmony_ci * sure caller does not unmap dma while recovery is 60862306a36Sopenharmony_ci * in progress. 60962306a36Sopenharmony_ci */ 61062306a36Sopenharmony_ci msleep(1); 61162306a36Sopenharmony_ci i--; 61262306a36Sopenharmony_ci } 61362306a36Sopenharmony_ci return rval; 61462306a36Sopenharmony_ci} 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ciint 61762306a36Sopenharmony_ciqla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr, 61862306a36Sopenharmony_ci uint32_t risc_code_size) 61962306a36Sopenharmony_ci{ 62062306a36Sopenharmony_ci int rval; 62162306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 62262306a36Sopenharmony_ci mbx_cmd_t mc; 62362306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1022, 62662306a36Sopenharmony_ci "Entered %s.\n", __func__); 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci if (MSW(risc_addr) || IS_FWI2_CAPABLE(ha)) { 62962306a36Sopenharmony_ci mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; 63062306a36Sopenharmony_ci mcp->mb[8] = MSW(risc_addr); 63162306a36Sopenharmony_ci mcp->out_mb = MBX_8|MBX_0; 63262306a36Sopenharmony_ci } else { 63362306a36Sopenharmony_ci mcp->mb[0] = MBC_LOAD_RISC_RAM; 63462306a36Sopenharmony_ci mcp->out_mb = MBX_0; 63562306a36Sopenharmony_ci } 63662306a36Sopenharmony_ci mcp->mb[1] = LSW(risc_addr); 63762306a36Sopenharmony_ci mcp->mb[2] = MSW(req_dma); 63862306a36Sopenharmony_ci mcp->mb[3] = LSW(req_dma); 63962306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(req_dma)); 64062306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(req_dma)); 64162306a36Sopenharmony_ci mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1; 64262306a36Sopenharmony_ci if (IS_FWI2_CAPABLE(ha)) { 64362306a36Sopenharmony_ci mcp->mb[4] = MSW(risc_code_size); 64462306a36Sopenharmony_ci mcp->mb[5] = LSW(risc_code_size); 64562306a36Sopenharmony_ci mcp->out_mb |= MBX_5|MBX_4; 64662306a36Sopenharmony_ci } else { 64762306a36Sopenharmony_ci mcp->mb[4] = LSW(risc_code_size); 64862306a36Sopenharmony_ci mcp->out_mb |= MBX_4; 64962306a36Sopenharmony_ci } 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 65262306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 65362306a36Sopenharmony_ci mcp->flags = 0; 65462306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 65762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1023, 65862306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x.\n", 65962306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1]); 66062306a36Sopenharmony_ci vha->hw_err_cnt++; 66162306a36Sopenharmony_ci } else { 66262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1024, 66362306a36Sopenharmony_ci "Done %s.\n", __func__); 66462306a36Sopenharmony_ci } 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci return rval; 66762306a36Sopenharmony_ci} 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci#define NVME_ENABLE_FLAG BIT_3 67062306a36Sopenharmony_ci#define EDIF_HW_SUPPORT BIT_10 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci/* 67362306a36Sopenharmony_ci * qla2x00_execute_fw 67462306a36Sopenharmony_ci * Start adapter firmware. 67562306a36Sopenharmony_ci * 67662306a36Sopenharmony_ci * Input: 67762306a36Sopenharmony_ci * ha = adapter block pointer. 67862306a36Sopenharmony_ci * TARGET_QUEUE_LOCK must be released. 67962306a36Sopenharmony_ci * ADAPTER_STATE_LOCK must be released. 68062306a36Sopenharmony_ci * 68162306a36Sopenharmony_ci * Returns: 68262306a36Sopenharmony_ci * qla2x00 local function return status code. 68362306a36Sopenharmony_ci * 68462306a36Sopenharmony_ci * Context: 68562306a36Sopenharmony_ci * Kernel context. 68662306a36Sopenharmony_ci */ 68762306a36Sopenharmony_ciint 68862306a36Sopenharmony_ciqla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) 68962306a36Sopenharmony_ci{ 69062306a36Sopenharmony_ci int rval; 69162306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 69262306a36Sopenharmony_ci mbx_cmd_t mc; 69362306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 69462306a36Sopenharmony_ci u8 semaphore = 0; 69562306a36Sopenharmony_ci#define EXE_FW_FORCE_SEMAPHORE BIT_7 69662306a36Sopenharmony_ci u8 retry = 5; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1025, 69962306a36Sopenharmony_ci "Entered %s.\n", __func__); 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ciagain: 70262306a36Sopenharmony_ci mcp->mb[0] = MBC_EXECUTE_FIRMWARE; 70362306a36Sopenharmony_ci mcp->out_mb = MBX_0; 70462306a36Sopenharmony_ci mcp->in_mb = MBX_0; 70562306a36Sopenharmony_ci if (IS_FWI2_CAPABLE(ha)) { 70662306a36Sopenharmony_ci mcp->mb[1] = MSW(risc_addr); 70762306a36Sopenharmony_ci mcp->mb[2] = LSW(risc_addr); 70862306a36Sopenharmony_ci mcp->mb[3] = 0; 70962306a36Sopenharmony_ci mcp->mb[4] = 0; 71062306a36Sopenharmony_ci mcp->mb[11] = 0; 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci /* Enable BPM? */ 71362306a36Sopenharmony_ci if (ha->flags.lr_detected) { 71462306a36Sopenharmony_ci mcp->mb[4] = BIT_0; 71562306a36Sopenharmony_ci if (IS_BPM_RANGE_CAPABLE(ha)) 71662306a36Sopenharmony_ci mcp->mb[4] |= 71762306a36Sopenharmony_ci ha->lr_distance << LR_DIST_FW_POS; 71862306a36Sopenharmony_ci } 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci if (ql2xnvmeenable && (IS_QLA27XX(ha) || IS_QLA28XX(ha))) 72162306a36Sopenharmony_ci mcp->mb[4] |= NVME_ENABLE_FLAG; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { 72462306a36Sopenharmony_ci struct nvram_81xx *nv = ha->nvram; 72562306a36Sopenharmony_ci /* set minimum speed if specified in nvram */ 72662306a36Sopenharmony_ci if (nv->min_supported_speed >= 2 && 72762306a36Sopenharmony_ci nv->min_supported_speed <= 5) { 72862306a36Sopenharmony_ci mcp->mb[4] |= BIT_4; 72962306a36Sopenharmony_ci mcp->mb[11] |= nv->min_supported_speed & 0xF; 73062306a36Sopenharmony_ci mcp->out_mb |= MBX_11; 73162306a36Sopenharmony_ci mcp->in_mb |= BIT_5; 73262306a36Sopenharmony_ci vha->min_supported_speed = 73362306a36Sopenharmony_ci nv->min_supported_speed; 73462306a36Sopenharmony_ci } 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci if (IS_PPCARCH) 73762306a36Sopenharmony_ci mcp->mb[11] |= BIT_4; 73862306a36Sopenharmony_ci } 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci if (ha->flags.exlogins_enabled) 74162306a36Sopenharmony_ci mcp->mb[4] |= ENABLE_EXTENDED_LOGIN; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci if (ha->flags.exchoffld_enabled) 74462306a36Sopenharmony_ci mcp->mb[4] |= ENABLE_EXCHANGE_OFFLD; 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci if (semaphore) 74762306a36Sopenharmony_ci mcp->mb[11] |= EXE_FW_FORCE_SEMAPHORE; 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci mcp->out_mb |= MBX_4 | MBX_3 | MBX_2 | MBX_1 | MBX_11; 75062306a36Sopenharmony_ci mcp->in_mb |= MBX_5 | MBX_3 | MBX_2 | MBX_1; 75162306a36Sopenharmony_ci } else { 75262306a36Sopenharmony_ci mcp->mb[1] = LSW(risc_addr); 75362306a36Sopenharmony_ci mcp->out_mb |= MBX_1; 75462306a36Sopenharmony_ci if (IS_QLA2322(ha) || IS_QLA6322(ha)) { 75562306a36Sopenharmony_ci mcp->mb[2] = 0; 75662306a36Sopenharmony_ci mcp->out_mb |= MBX_2; 75762306a36Sopenharmony_ci } 75862306a36Sopenharmony_ci } 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 76162306a36Sopenharmony_ci mcp->flags = 0; 76262306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 76562306a36Sopenharmony_ci if (IS_QLA28XX(ha) && rval == QLA_COMMAND_ERROR && 76662306a36Sopenharmony_ci mcp->mb[1] == 0x27 && retry) { 76762306a36Sopenharmony_ci semaphore = 1; 76862306a36Sopenharmony_ci retry--; 76962306a36Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x1026, 77062306a36Sopenharmony_ci "Exe FW: force semaphore.\n"); 77162306a36Sopenharmony_ci goto again; 77262306a36Sopenharmony_ci } 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci if (retry) { 77562306a36Sopenharmony_ci retry--; 77662306a36Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x509d, 77762306a36Sopenharmony_ci "Exe FW retry: mb[0]=%x retry[%d]\n", mcp->mb[0], retry); 77862306a36Sopenharmony_ci goto again; 77962306a36Sopenharmony_ci } 78062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1026, 78162306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 78262306a36Sopenharmony_ci vha->hw_err_cnt++; 78362306a36Sopenharmony_ci return rval; 78462306a36Sopenharmony_ci } 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci if (!IS_FWI2_CAPABLE(ha)) 78762306a36Sopenharmony_ci goto done; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci ha->fw_ability_mask = mcp->mb[3] << 16 | mcp->mb[2]; 79062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x119a, 79162306a36Sopenharmony_ci "fw_ability_mask=%x.\n", ha->fw_ability_mask); 79262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1027, "exchanges=%x.\n", mcp->mb[1]); 79362306a36Sopenharmony_ci if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { 79462306a36Sopenharmony_ci ha->max_supported_speed = mcp->mb[2] & (BIT_0|BIT_1); 79562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x119b, "max_supported_speed=%s.\n", 79662306a36Sopenharmony_ci ha->max_supported_speed == 0 ? "16Gps" : 79762306a36Sopenharmony_ci ha->max_supported_speed == 1 ? "32Gps" : 79862306a36Sopenharmony_ci ha->max_supported_speed == 2 ? "64Gps" : "unknown"); 79962306a36Sopenharmony_ci if (vha->min_supported_speed) { 80062306a36Sopenharmony_ci ha->min_supported_speed = mcp->mb[5] & 80162306a36Sopenharmony_ci (BIT_0 | BIT_1 | BIT_2); 80262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x119c, 80362306a36Sopenharmony_ci "min_supported_speed=%s.\n", 80462306a36Sopenharmony_ci ha->min_supported_speed == 6 ? "64Gps" : 80562306a36Sopenharmony_ci ha->min_supported_speed == 5 ? "32Gps" : 80662306a36Sopenharmony_ci ha->min_supported_speed == 4 ? "16Gps" : 80762306a36Sopenharmony_ci ha->min_supported_speed == 3 ? "8Gps" : 80862306a36Sopenharmony_ci ha->min_supported_speed == 2 ? "4Gps" : "unknown"); 80962306a36Sopenharmony_ci } 81062306a36Sopenharmony_ci } 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci if (IS_QLA28XX(ha) && (mcp->mb[5] & EDIF_HW_SUPPORT)) { 81362306a36Sopenharmony_ci ha->flags.edif_hw = 1; 81462306a36Sopenharmony_ci ql_log(ql_log_info, vha, 0xffff, 81562306a36Sopenharmony_ci "%s: edif HW\n", __func__); 81662306a36Sopenharmony_ci } 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_cidone: 81962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1028, 82062306a36Sopenharmony_ci "Done %s.\n", __func__); 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci return rval; 82362306a36Sopenharmony_ci} 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci/* 82662306a36Sopenharmony_ci * qla_get_exlogin_status 82762306a36Sopenharmony_ci * Get extended login status 82862306a36Sopenharmony_ci * uses the memory offload control/status Mailbox 82962306a36Sopenharmony_ci * 83062306a36Sopenharmony_ci * Input: 83162306a36Sopenharmony_ci * ha: adapter state pointer. 83262306a36Sopenharmony_ci * fwopt: firmware options 83362306a36Sopenharmony_ci * 83462306a36Sopenharmony_ci * Returns: 83562306a36Sopenharmony_ci * qla2x00 local function status 83662306a36Sopenharmony_ci * 83762306a36Sopenharmony_ci * Context: 83862306a36Sopenharmony_ci * Kernel context. 83962306a36Sopenharmony_ci */ 84062306a36Sopenharmony_ci#define FETCH_XLOGINS_STAT 0x8 84162306a36Sopenharmony_ciint 84262306a36Sopenharmony_ciqla_get_exlogin_status(scsi_qla_host_t *vha, uint16_t *buf_sz, 84362306a36Sopenharmony_ci uint16_t *ex_logins_cnt) 84462306a36Sopenharmony_ci{ 84562306a36Sopenharmony_ci int rval; 84662306a36Sopenharmony_ci mbx_cmd_t mc; 84762306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118f, 85062306a36Sopenharmony_ci "Entered %s\n", __func__); 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci memset(mcp->mb, 0 , sizeof(mcp->mb)); 85362306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT; 85462306a36Sopenharmony_ci mcp->mb[1] = FETCH_XLOGINS_STAT; 85562306a36Sopenharmony_ci mcp->out_mb = MBX_1|MBX_0; 85662306a36Sopenharmony_ci mcp->in_mb = MBX_10|MBX_4|MBX_0; 85762306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 85862306a36Sopenharmony_ci mcp->flags = 0; 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 86162306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 86262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1115, "Failed=%x.\n", rval); 86362306a36Sopenharmony_ci } else { 86462306a36Sopenharmony_ci *buf_sz = mcp->mb[4]; 86562306a36Sopenharmony_ci *ex_logins_cnt = mcp->mb[10]; 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci ql_log(ql_log_info, vha, 0x1190, 86862306a36Sopenharmony_ci "buffer size 0x%x, exchange login count=%d\n", 86962306a36Sopenharmony_ci mcp->mb[4], mcp->mb[10]); 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1116, 87262306a36Sopenharmony_ci "Done %s.\n", __func__); 87362306a36Sopenharmony_ci } 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci return rval; 87662306a36Sopenharmony_ci} 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci/* 87962306a36Sopenharmony_ci * qla_set_exlogin_mem_cfg 88062306a36Sopenharmony_ci * set extended login memory configuration 88162306a36Sopenharmony_ci * Mbx needs to be issues before init_cb is set 88262306a36Sopenharmony_ci * 88362306a36Sopenharmony_ci * Input: 88462306a36Sopenharmony_ci * ha: adapter state pointer. 88562306a36Sopenharmony_ci * buffer: buffer pointer 88662306a36Sopenharmony_ci * phys_addr: physical address of buffer 88762306a36Sopenharmony_ci * size: size of buffer 88862306a36Sopenharmony_ci * TARGET_QUEUE_LOCK must be released 88962306a36Sopenharmony_ci * ADAPTER_STATE_LOCK must be release 89062306a36Sopenharmony_ci * 89162306a36Sopenharmony_ci * Returns: 89262306a36Sopenharmony_ci * qla2x00 local funxtion status code. 89362306a36Sopenharmony_ci * 89462306a36Sopenharmony_ci * Context: 89562306a36Sopenharmony_ci * Kernel context. 89662306a36Sopenharmony_ci */ 89762306a36Sopenharmony_ci#define CONFIG_XLOGINS_MEM 0x9 89862306a36Sopenharmony_ciint 89962306a36Sopenharmony_ciqla_set_exlogin_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr) 90062306a36Sopenharmony_ci{ 90162306a36Sopenharmony_ci int rval; 90262306a36Sopenharmony_ci mbx_cmd_t mc; 90362306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 90462306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x111a, 90762306a36Sopenharmony_ci "Entered %s.\n", __func__); 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci memset(mcp->mb, 0 , sizeof(mcp->mb)); 91062306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT; 91162306a36Sopenharmony_ci mcp->mb[1] = CONFIG_XLOGINS_MEM; 91262306a36Sopenharmony_ci mcp->mb[2] = MSW(phys_addr); 91362306a36Sopenharmony_ci mcp->mb[3] = LSW(phys_addr); 91462306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(phys_addr)); 91562306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(phys_addr)); 91662306a36Sopenharmony_ci mcp->mb[8] = MSW(ha->exlogin_size); 91762306a36Sopenharmony_ci mcp->mb[9] = LSW(ha->exlogin_size); 91862306a36Sopenharmony_ci mcp->out_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; 91962306a36Sopenharmony_ci mcp->in_mb = MBX_11|MBX_0; 92062306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 92162306a36Sopenharmony_ci mcp->flags = 0; 92262306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 92362306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 92462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x111b, 92562306a36Sopenharmony_ci "EXlogin Failed=%x. MB0=%x MB11=%x\n", 92662306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[11]); 92762306a36Sopenharmony_ci } else { 92862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118c, 92962306a36Sopenharmony_ci "Done %s.\n", __func__); 93062306a36Sopenharmony_ci } 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci return rval; 93362306a36Sopenharmony_ci} 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci/* 93662306a36Sopenharmony_ci * qla_get_exchoffld_status 93762306a36Sopenharmony_ci * Get exchange offload status 93862306a36Sopenharmony_ci * uses the memory offload control/status Mailbox 93962306a36Sopenharmony_ci * 94062306a36Sopenharmony_ci * Input: 94162306a36Sopenharmony_ci * ha: adapter state pointer. 94262306a36Sopenharmony_ci * fwopt: firmware options 94362306a36Sopenharmony_ci * 94462306a36Sopenharmony_ci * Returns: 94562306a36Sopenharmony_ci * qla2x00 local function status 94662306a36Sopenharmony_ci * 94762306a36Sopenharmony_ci * Context: 94862306a36Sopenharmony_ci * Kernel context. 94962306a36Sopenharmony_ci */ 95062306a36Sopenharmony_ci#define FETCH_XCHOFFLD_STAT 0x2 95162306a36Sopenharmony_ciint 95262306a36Sopenharmony_ciqla_get_exchoffld_status(scsi_qla_host_t *vha, uint16_t *buf_sz, 95362306a36Sopenharmony_ci uint16_t *ex_logins_cnt) 95462306a36Sopenharmony_ci{ 95562306a36Sopenharmony_ci int rval; 95662306a36Sopenharmony_ci mbx_cmd_t mc; 95762306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1019, 96062306a36Sopenharmony_ci "Entered %s\n", __func__); 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci memset(mcp->mb, 0 , sizeof(mcp->mb)); 96362306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT; 96462306a36Sopenharmony_ci mcp->mb[1] = FETCH_XCHOFFLD_STAT; 96562306a36Sopenharmony_ci mcp->out_mb = MBX_1|MBX_0; 96662306a36Sopenharmony_ci mcp->in_mb = MBX_10|MBX_4|MBX_0; 96762306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 96862306a36Sopenharmony_ci mcp->flags = 0; 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 97162306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 97262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1155, "Failed=%x.\n", rval); 97362306a36Sopenharmony_ci } else { 97462306a36Sopenharmony_ci *buf_sz = mcp->mb[4]; 97562306a36Sopenharmony_ci *ex_logins_cnt = mcp->mb[10]; 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci ql_log(ql_log_info, vha, 0x118e, 97862306a36Sopenharmony_ci "buffer size 0x%x, exchange offload count=%d\n", 97962306a36Sopenharmony_ci mcp->mb[4], mcp->mb[10]); 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1156, 98262306a36Sopenharmony_ci "Done %s.\n", __func__); 98362306a36Sopenharmony_ci } 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci return rval; 98662306a36Sopenharmony_ci} 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci/* 98962306a36Sopenharmony_ci * qla_set_exchoffld_mem_cfg 99062306a36Sopenharmony_ci * Set exchange offload memory configuration 99162306a36Sopenharmony_ci * Mbx needs to be issues before init_cb is set 99262306a36Sopenharmony_ci * 99362306a36Sopenharmony_ci * Input: 99462306a36Sopenharmony_ci * ha: adapter state pointer. 99562306a36Sopenharmony_ci * buffer: buffer pointer 99662306a36Sopenharmony_ci * phys_addr: physical address of buffer 99762306a36Sopenharmony_ci * size: size of buffer 99862306a36Sopenharmony_ci * TARGET_QUEUE_LOCK must be released 99962306a36Sopenharmony_ci * ADAPTER_STATE_LOCK must be release 100062306a36Sopenharmony_ci * 100162306a36Sopenharmony_ci * Returns: 100262306a36Sopenharmony_ci * qla2x00 local funxtion status code. 100362306a36Sopenharmony_ci * 100462306a36Sopenharmony_ci * Context: 100562306a36Sopenharmony_ci * Kernel context. 100662306a36Sopenharmony_ci */ 100762306a36Sopenharmony_ci#define CONFIG_XCHOFFLD_MEM 0x3 100862306a36Sopenharmony_ciint 100962306a36Sopenharmony_ciqla_set_exchoffld_mem_cfg(scsi_qla_host_t *vha) 101062306a36Sopenharmony_ci{ 101162306a36Sopenharmony_ci int rval; 101262306a36Sopenharmony_ci mbx_cmd_t mc; 101362306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 101462306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1157, 101762306a36Sopenharmony_ci "Entered %s.\n", __func__); 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci memset(mcp->mb, 0 , sizeof(mcp->mb)); 102062306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT; 102162306a36Sopenharmony_ci mcp->mb[1] = CONFIG_XCHOFFLD_MEM; 102262306a36Sopenharmony_ci mcp->mb[2] = MSW(ha->exchoffld_buf_dma); 102362306a36Sopenharmony_ci mcp->mb[3] = LSW(ha->exchoffld_buf_dma); 102462306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(ha->exchoffld_buf_dma)); 102562306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(ha->exchoffld_buf_dma)); 102662306a36Sopenharmony_ci mcp->mb[8] = MSW(ha->exchoffld_size); 102762306a36Sopenharmony_ci mcp->mb[9] = LSW(ha->exchoffld_size); 102862306a36Sopenharmony_ci mcp->out_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; 102962306a36Sopenharmony_ci mcp->in_mb = MBX_11|MBX_0; 103062306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 103162306a36Sopenharmony_ci mcp->flags = 0; 103262306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 103362306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 103462306a36Sopenharmony_ci /*EMPTY*/ 103562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1158, "Failed=%x.\n", rval); 103662306a36Sopenharmony_ci } else { 103762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1192, 103862306a36Sopenharmony_ci "Done %s.\n", __func__); 103962306a36Sopenharmony_ci } 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ci return rval; 104262306a36Sopenharmony_ci} 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci/* 104562306a36Sopenharmony_ci * qla2x00_get_fw_version 104662306a36Sopenharmony_ci * Get firmware version. 104762306a36Sopenharmony_ci * 104862306a36Sopenharmony_ci * Input: 104962306a36Sopenharmony_ci * ha: adapter state pointer. 105062306a36Sopenharmony_ci * major: pointer for major number. 105162306a36Sopenharmony_ci * minor: pointer for minor number. 105262306a36Sopenharmony_ci * subminor: pointer for subminor number. 105362306a36Sopenharmony_ci * 105462306a36Sopenharmony_ci * Returns: 105562306a36Sopenharmony_ci * qla2x00 local function return status code. 105662306a36Sopenharmony_ci * 105762306a36Sopenharmony_ci * Context: 105862306a36Sopenharmony_ci * Kernel context. 105962306a36Sopenharmony_ci */ 106062306a36Sopenharmony_ciint 106162306a36Sopenharmony_ciqla2x00_get_fw_version(scsi_qla_host_t *vha) 106262306a36Sopenharmony_ci{ 106362306a36Sopenharmony_ci int rval; 106462306a36Sopenharmony_ci mbx_cmd_t mc; 106562306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 106662306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1029, 106962306a36Sopenharmony_ci "Entered %s.\n", __func__); 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_FIRMWARE_VERSION; 107262306a36Sopenharmony_ci mcp->out_mb = MBX_0; 107362306a36Sopenharmony_ci mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 107462306a36Sopenharmony_ci if (IS_QLA81XX(vha->hw) || IS_QLA8031(ha) || IS_QLA8044(ha)) 107562306a36Sopenharmony_ci mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8; 107662306a36Sopenharmony_ci if (IS_FWI2_CAPABLE(ha)) 107762306a36Sopenharmony_ci mcp->in_mb |= MBX_17|MBX_16|MBX_15; 107862306a36Sopenharmony_ci if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) 107962306a36Sopenharmony_ci mcp->in_mb |= 108062306a36Sopenharmony_ci MBX_25|MBX_24|MBX_23|MBX_22|MBX_21|MBX_20|MBX_19|MBX_18| 108162306a36Sopenharmony_ci MBX_14|MBX_13|MBX_11|MBX_10|MBX_9|MBX_8|MBX_7; 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci mcp->flags = 0; 108462306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 108562306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 108662306a36Sopenharmony_ci if (rval != QLA_SUCCESS) 108762306a36Sopenharmony_ci goto failed; 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_ci /* Return mailbox data. */ 109062306a36Sopenharmony_ci ha->fw_major_version = mcp->mb[1]; 109162306a36Sopenharmony_ci ha->fw_minor_version = mcp->mb[2]; 109262306a36Sopenharmony_ci ha->fw_subminor_version = mcp->mb[3]; 109362306a36Sopenharmony_ci ha->fw_attributes = mcp->mb[6]; 109462306a36Sopenharmony_ci if (IS_QLA2100(vha->hw) || IS_QLA2200(vha->hw)) 109562306a36Sopenharmony_ci ha->fw_memory_size = 0x1FFFF; /* Defaults to 128KB. */ 109662306a36Sopenharmony_ci else 109762306a36Sopenharmony_ci ha->fw_memory_size = (mcp->mb[5] << 16) | mcp->mb[4]; 109862306a36Sopenharmony_ci 109962306a36Sopenharmony_ci if (IS_QLA81XX(vha->hw) || IS_QLA8031(vha->hw) || IS_QLA8044(ha)) { 110062306a36Sopenharmony_ci ha->mpi_version[0] = mcp->mb[10] & 0xff; 110162306a36Sopenharmony_ci ha->mpi_version[1] = mcp->mb[11] >> 8; 110262306a36Sopenharmony_ci ha->mpi_version[2] = mcp->mb[11] & 0xff; 110362306a36Sopenharmony_ci ha->mpi_capabilities = (mcp->mb[12] << 16) | mcp->mb[13]; 110462306a36Sopenharmony_ci ha->phy_version[0] = mcp->mb[8] & 0xff; 110562306a36Sopenharmony_ci ha->phy_version[1] = mcp->mb[9] >> 8; 110662306a36Sopenharmony_ci ha->phy_version[2] = mcp->mb[9] & 0xff; 110762306a36Sopenharmony_ci } 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci if (IS_FWI2_CAPABLE(ha)) { 111062306a36Sopenharmony_ci ha->fw_attributes_h = mcp->mb[15]; 111162306a36Sopenharmony_ci ha->fw_attributes_ext[0] = mcp->mb[16]; 111262306a36Sopenharmony_ci ha->fw_attributes_ext[1] = mcp->mb[17]; 111362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1139, 111462306a36Sopenharmony_ci "%s: FW_attributes Upper: 0x%x, Lower: 0x%x.\n", 111562306a36Sopenharmony_ci __func__, mcp->mb[15], mcp->mb[6]); 111662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x112f, 111762306a36Sopenharmony_ci "%s: Ext_FwAttributes Upper: 0x%x, Lower: 0x%x.\n", 111862306a36Sopenharmony_ci __func__, mcp->mb[17], mcp->mb[16]); 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci if (ha->fw_attributes_h & 0x4) 112162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118d, 112262306a36Sopenharmony_ci "%s: Firmware supports Extended Login 0x%x\n", 112362306a36Sopenharmony_ci __func__, ha->fw_attributes_h); 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci if (ha->fw_attributes_h & 0x8) 112662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1191, 112762306a36Sopenharmony_ci "%s: Firmware supports Exchange Offload 0x%x\n", 112862306a36Sopenharmony_ci __func__, ha->fw_attributes_h); 112962306a36Sopenharmony_ci 113062306a36Sopenharmony_ci /* 113162306a36Sopenharmony_ci * FW supports nvme and driver load parameter requested nvme. 113262306a36Sopenharmony_ci * BIT 26 of fw_attributes indicates NVMe support. 113362306a36Sopenharmony_ci */ 113462306a36Sopenharmony_ci if ((ha->fw_attributes_h & 113562306a36Sopenharmony_ci (FW_ATTR_H_NVME | FW_ATTR_H_NVME_UPDATED)) && 113662306a36Sopenharmony_ci ql2xnvmeenable) { 113762306a36Sopenharmony_ci if (ha->fw_attributes_h & FW_ATTR_H_NVME_FBURST) 113862306a36Sopenharmony_ci vha->flags.nvme_first_burst = 1; 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_ci vha->flags.nvme_enabled = 1; 114162306a36Sopenharmony_ci ql_log(ql_log_info, vha, 0xd302, 114262306a36Sopenharmony_ci "%s: FC-NVMe is Enabled (0x%x)\n", 114362306a36Sopenharmony_ci __func__, ha->fw_attributes_h); 114462306a36Sopenharmony_ci } 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci /* BIT_13 of Extended FW Attributes informs about NVMe2 support */ 114762306a36Sopenharmony_ci if (ha->fw_attributes_ext[0] & FW_ATTR_EXT0_NVME2) { 114862306a36Sopenharmony_ci ql_log(ql_log_info, vha, 0xd302, 114962306a36Sopenharmony_ci "Firmware supports NVMe2 0x%x\n", 115062306a36Sopenharmony_ci ha->fw_attributes_ext[0]); 115162306a36Sopenharmony_ci vha->flags.nvme2_enabled = 1; 115262306a36Sopenharmony_ci } 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci if (IS_QLA28XX(ha) && ha->flags.edif_hw && ql2xsecenable && 115562306a36Sopenharmony_ci (ha->fw_attributes_ext[0] & FW_ATTR_EXT0_EDIF)) { 115662306a36Sopenharmony_ci ha->flags.edif_enabled = 1; 115762306a36Sopenharmony_ci ql_log(ql_log_info, vha, 0xffff, 115862306a36Sopenharmony_ci "%s: edif is enabled\n", __func__); 115962306a36Sopenharmony_ci } 116062306a36Sopenharmony_ci } 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { 116362306a36Sopenharmony_ci ha->serdes_version[0] = mcp->mb[7] & 0xff; 116462306a36Sopenharmony_ci ha->serdes_version[1] = mcp->mb[8] >> 8; 116562306a36Sopenharmony_ci ha->serdes_version[2] = mcp->mb[8] & 0xff; 116662306a36Sopenharmony_ci ha->mpi_version[0] = mcp->mb[10] & 0xff; 116762306a36Sopenharmony_ci ha->mpi_version[1] = mcp->mb[11] >> 8; 116862306a36Sopenharmony_ci ha->mpi_version[2] = mcp->mb[11] & 0xff; 116962306a36Sopenharmony_ci ha->pep_version[0] = mcp->mb[13] & 0xff; 117062306a36Sopenharmony_ci ha->pep_version[1] = mcp->mb[14] >> 8; 117162306a36Sopenharmony_ci ha->pep_version[2] = mcp->mb[14] & 0xff; 117262306a36Sopenharmony_ci ha->fw_shared_ram_start = (mcp->mb[19] << 16) | mcp->mb[18]; 117362306a36Sopenharmony_ci ha->fw_shared_ram_end = (mcp->mb[21] << 16) | mcp->mb[20]; 117462306a36Sopenharmony_ci ha->fw_ddr_ram_start = (mcp->mb[23] << 16) | mcp->mb[22]; 117562306a36Sopenharmony_ci ha->fw_ddr_ram_end = (mcp->mb[25] << 16) | mcp->mb[24]; 117662306a36Sopenharmony_ci if (IS_QLA28XX(ha)) { 117762306a36Sopenharmony_ci if (mcp->mb[16] & BIT_10) 117862306a36Sopenharmony_ci ha->flags.secure_fw = 1; 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci ql_log(ql_log_info, vha, 0xffff, 118162306a36Sopenharmony_ci "Secure Flash Update in FW: %s\n", 118262306a36Sopenharmony_ci (ha->flags.secure_fw) ? "Supported" : 118362306a36Sopenharmony_ci "Not Supported"); 118462306a36Sopenharmony_ci } 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci if (ha->flags.scm_supported_a && 118762306a36Sopenharmony_ci (ha->fw_attributes_ext[0] & FW_ATTR_EXT0_SCM_SUPPORTED)) { 118862306a36Sopenharmony_ci ha->flags.scm_supported_f = 1; 118962306a36Sopenharmony_ci ha->sf_init_cb->flags |= cpu_to_le16(BIT_13); 119062306a36Sopenharmony_ci } 119162306a36Sopenharmony_ci ql_log(ql_log_info, vha, 0x11a3, "SCM in FW: %s\n", 119262306a36Sopenharmony_ci (ha->flags.scm_supported_f) ? "Supported" : 119362306a36Sopenharmony_ci "Not Supported"); 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci if (vha->flags.nvme2_enabled) { 119662306a36Sopenharmony_ci /* set BIT_15 of special feature control block for SLER */ 119762306a36Sopenharmony_ci ha->sf_init_cb->flags |= cpu_to_le16(BIT_15); 119862306a36Sopenharmony_ci /* set BIT_14 of special feature control block for PI CTRL*/ 119962306a36Sopenharmony_ci ha->sf_init_cb->flags |= cpu_to_le16(BIT_14); 120062306a36Sopenharmony_ci } 120162306a36Sopenharmony_ci } 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_cifailed: 120462306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 120562306a36Sopenharmony_ci /*EMPTY*/ 120662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x102a, "Failed=%x.\n", rval); 120762306a36Sopenharmony_ci } else { 120862306a36Sopenharmony_ci /*EMPTY*/ 120962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102b, 121062306a36Sopenharmony_ci "Done %s.\n", __func__); 121162306a36Sopenharmony_ci } 121262306a36Sopenharmony_ci return rval; 121362306a36Sopenharmony_ci} 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ci/* 121662306a36Sopenharmony_ci * qla2x00_get_fw_options 121762306a36Sopenharmony_ci * Set firmware options. 121862306a36Sopenharmony_ci * 121962306a36Sopenharmony_ci * Input: 122062306a36Sopenharmony_ci * ha = adapter block pointer. 122162306a36Sopenharmony_ci * fwopt = pointer for firmware options. 122262306a36Sopenharmony_ci * 122362306a36Sopenharmony_ci * Returns: 122462306a36Sopenharmony_ci * qla2x00 local function return status code. 122562306a36Sopenharmony_ci * 122662306a36Sopenharmony_ci * Context: 122762306a36Sopenharmony_ci * Kernel context. 122862306a36Sopenharmony_ci */ 122962306a36Sopenharmony_ciint 123062306a36Sopenharmony_ciqla2x00_get_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts) 123162306a36Sopenharmony_ci{ 123262306a36Sopenharmony_ci int rval; 123362306a36Sopenharmony_ci mbx_cmd_t mc; 123462306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102c, 123762306a36Sopenharmony_ci "Entered %s.\n", __func__); 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_FIRMWARE_OPTION; 124062306a36Sopenharmony_ci mcp->out_mb = MBX_0; 124162306a36Sopenharmony_ci mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0; 124262306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 124362306a36Sopenharmony_ci mcp->flags = 0; 124462306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 124762306a36Sopenharmony_ci /*EMPTY*/ 124862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x102d, "Failed=%x.\n", rval); 124962306a36Sopenharmony_ci } else { 125062306a36Sopenharmony_ci fwopts[0] = mcp->mb[0]; 125162306a36Sopenharmony_ci fwopts[1] = mcp->mb[1]; 125262306a36Sopenharmony_ci fwopts[2] = mcp->mb[2]; 125362306a36Sopenharmony_ci fwopts[3] = mcp->mb[3]; 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102e, 125662306a36Sopenharmony_ci "Done %s.\n", __func__); 125762306a36Sopenharmony_ci } 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci return rval; 126062306a36Sopenharmony_ci} 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci/* 126462306a36Sopenharmony_ci * qla2x00_set_fw_options 126562306a36Sopenharmony_ci * Set firmware options. 126662306a36Sopenharmony_ci * 126762306a36Sopenharmony_ci * Input: 126862306a36Sopenharmony_ci * ha = adapter block pointer. 126962306a36Sopenharmony_ci * fwopt = pointer for firmware options. 127062306a36Sopenharmony_ci * 127162306a36Sopenharmony_ci * Returns: 127262306a36Sopenharmony_ci * qla2x00 local function return status code. 127362306a36Sopenharmony_ci * 127462306a36Sopenharmony_ci * Context: 127562306a36Sopenharmony_ci * Kernel context. 127662306a36Sopenharmony_ci */ 127762306a36Sopenharmony_ciint 127862306a36Sopenharmony_ciqla2x00_set_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts) 127962306a36Sopenharmony_ci{ 128062306a36Sopenharmony_ci int rval; 128162306a36Sopenharmony_ci mbx_cmd_t mc; 128262306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102f, 128562306a36Sopenharmony_ci "Entered %s.\n", __func__); 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_ci mcp->mb[0] = MBC_SET_FIRMWARE_OPTION; 128862306a36Sopenharmony_ci mcp->mb[1] = fwopts[1]; 128962306a36Sopenharmony_ci mcp->mb[2] = fwopts[2]; 129062306a36Sopenharmony_ci mcp->mb[3] = fwopts[3]; 129162306a36Sopenharmony_ci mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; 129262306a36Sopenharmony_ci mcp->in_mb = MBX_0; 129362306a36Sopenharmony_ci if (IS_FWI2_CAPABLE(vha->hw)) { 129462306a36Sopenharmony_ci mcp->in_mb |= MBX_1; 129562306a36Sopenharmony_ci mcp->mb[10] = fwopts[10]; 129662306a36Sopenharmony_ci mcp->out_mb |= MBX_10; 129762306a36Sopenharmony_ci } else { 129862306a36Sopenharmony_ci mcp->mb[10] = fwopts[10]; 129962306a36Sopenharmony_ci mcp->mb[11] = fwopts[11]; 130062306a36Sopenharmony_ci mcp->mb[12] = 0; /* Undocumented, but used */ 130162306a36Sopenharmony_ci mcp->out_mb |= MBX_12|MBX_11|MBX_10; 130262306a36Sopenharmony_ci } 130362306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 130462306a36Sopenharmony_ci mcp->flags = 0; 130562306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci fwopts[0] = mcp->mb[0]; 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 131062306a36Sopenharmony_ci /*EMPTY*/ 131162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1030, 131262306a36Sopenharmony_ci "Failed=%x (%x/%x).\n", rval, mcp->mb[0], mcp->mb[1]); 131362306a36Sopenharmony_ci } else { 131462306a36Sopenharmony_ci /*EMPTY*/ 131562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1031, 131662306a36Sopenharmony_ci "Done %s.\n", __func__); 131762306a36Sopenharmony_ci } 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci return rval; 132062306a36Sopenharmony_ci} 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci/* 132362306a36Sopenharmony_ci * qla2x00_mbx_reg_test 132462306a36Sopenharmony_ci * Mailbox register wrap test. 132562306a36Sopenharmony_ci * 132662306a36Sopenharmony_ci * Input: 132762306a36Sopenharmony_ci * ha = adapter block pointer. 132862306a36Sopenharmony_ci * TARGET_QUEUE_LOCK must be released. 132962306a36Sopenharmony_ci * ADAPTER_STATE_LOCK must be released. 133062306a36Sopenharmony_ci * 133162306a36Sopenharmony_ci * Returns: 133262306a36Sopenharmony_ci * qla2x00 local function return status code. 133362306a36Sopenharmony_ci * 133462306a36Sopenharmony_ci * Context: 133562306a36Sopenharmony_ci * Kernel context. 133662306a36Sopenharmony_ci */ 133762306a36Sopenharmony_ciint 133862306a36Sopenharmony_ciqla2x00_mbx_reg_test(scsi_qla_host_t *vha) 133962306a36Sopenharmony_ci{ 134062306a36Sopenharmony_ci int rval; 134162306a36Sopenharmony_ci mbx_cmd_t mc; 134262306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1032, 134562306a36Sopenharmony_ci "Entered %s.\n", __func__); 134662306a36Sopenharmony_ci 134762306a36Sopenharmony_ci mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST; 134862306a36Sopenharmony_ci mcp->mb[1] = 0xAAAA; 134962306a36Sopenharmony_ci mcp->mb[2] = 0x5555; 135062306a36Sopenharmony_ci mcp->mb[3] = 0xAA55; 135162306a36Sopenharmony_ci mcp->mb[4] = 0x55AA; 135262306a36Sopenharmony_ci mcp->mb[5] = 0xA5A5; 135362306a36Sopenharmony_ci mcp->mb[6] = 0x5A5A; 135462306a36Sopenharmony_ci mcp->mb[7] = 0x2525; 135562306a36Sopenharmony_ci mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 135662306a36Sopenharmony_ci mcp->in_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 135762306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 135862306a36Sopenharmony_ci mcp->flags = 0; 135962306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_ci if (rval == QLA_SUCCESS) { 136262306a36Sopenharmony_ci if (mcp->mb[1] != 0xAAAA || mcp->mb[2] != 0x5555 || 136362306a36Sopenharmony_ci mcp->mb[3] != 0xAA55 || mcp->mb[4] != 0x55AA) 136462306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 136562306a36Sopenharmony_ci if (mcp->mb[5] != 0xA5A5 || mcp->mb[6] != 0x5A5A || 136662306a36Sopenharmony_ci mcp->mb[7] != 0x2525) 136762306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 136862306a36Sopenharmony_ci } 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 137162306a36Sopenharmony_ci /*EMPTY*/ 137262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1033, "Failed=%x.\n", rval); 137362306a36Sopenharmony_ci vha->hw_err_cnt++; 137462306a36Sopenharmony_ci } else { 137562306a36Sopenharmony_ci /*EMPTY*/ 137662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1034, 137762306a36Sopenharmony_ci "Done %s.\n", __func__); 137862306a36Sopenharmony_ci } 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci return rval; 138162306a36Sopenharmony_ci} 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_ci/* 138462306a36Sopenharmony_ci * qla2x00_verify_checksum 138562306a36Sopenharmony_ci * Verify firmware checksum. 138662306a36Sopenharmony_ci * 138762306a36Sopenharmony_ci * Input: 138862306a36Sopenharmony_ci * ha = adapter block pointer. 138962306a36Sopenharmony_ci * TARGET_QUEUE_LOCK must be released. 139062306a36Sopenharmony_ci * ADAPTER_STATE_LOCK must be released. 139162306a36Sopenharmony_ci * 139262306a36Sopenharmony_ci * Returns: 139362306a36Sopenharmony_ci * qla2x00 local function return status code. 139462306a36Sopenharmony_ci * 139562306a36Sopenharmony_ci * Context: 139662306a36Sopenharmony_ci * Kernel context. 139762306a36Sopenharmony_ci */ 139862306a36Sopenharmony_ciint 139962306a36Sopenharmony_ciqla2x00_verify_checksum(scsi_qla_host_t *vha, uint32_t risc_addr) 140062306a36Sopenharmony_ci{ 140162306a36Sopenharmony_ci int rval; 140262306a36Sopenharmony_ci mbx_cmd_t mc; 140362306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1035, 140662306a36Sopenharmony_ci "Entered %s.\n", __func__); 140762306a36Sopenharmony_ci 140862306a36Sopenharmony_ci mcp->mb[0] = MBC_VERIFY_CHECKSUM; 140962306a36Sopenharmony_ci mcp->out_mb = MBX_0; 141062306a36Sopenharmony_ci mcp->in_mb = MBX_0; 141162306a36Sopenharmony_ci if (IS_FWI2_CAPABLE(vha->hw)) { 141262306a36Sopenharmony_ci mcp->mb[1] = MSW(risc_addr); 141362306a36Sopenharmony_ci mcp->mb[2] = LSW(risc_addr); 141462306a36Sopenharmony_ci mcp->out_mb |= MBX_2|MBX_1; 141562306a36Sopenharmony_ci mcp->in_mb |= MBX_2|MBX_1; 141662306a36Sopenharmony_ci } else { 141762306a36Sopenharmony_ci mcp->mb[1] = LSW(risc_addr); 141862306a36Sopenharmony_ci mcp->out_mb |= MBX_1; 141962306a36Sopenharmony_ci mcp->in_mb |= MBX_1; 142062306a36Sopenharmony_ci } 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 142362306a36Sopenharmony_ci mcp->flags = 0; 142462306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 142762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1036, 142862306a36Sopenharmony_ci "Failed=%x chm sum=%x.\n", rval, IS_FWI2_CAPABLE(vha->hw) ? 142962306a36Sopenharmony_ci (mcp->mb[2] << 16) | mcp->mb[1] : mcp->mb[1]); 143062306a36Sopenharmony_ci } else { 143162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1037, 143262306a36Sopenharmony_ci "Done %s.\n", __func__); 143362306a36Sopenharmony_ci } 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_ci return rval; 143662306a36Sopenharmony_ci} 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_ci/* 143962306a36Sopenharmony_ci * qla2x00_issue_iocb 144062306a36Sopenharmony_ci * Issue IOCB using mailbox command 144162306a36Sopenharmony_ci * 144262306a36Sopenharmony_ci * Input: 144362306a36Sopenharmony_ci * ha = adapter state pointer. 144462306a36Sopenharmony_ci * buffer = buffer pointer. 144562306a36Sopenharmony_ci * phys_addr = physical address of buffer. 144662306a36Sopenharmony_ci * size = size of buffer. 144762306a36Sopenharmony_ci * TARGET_QUEUE_LOCK must be released. 144862306a36Sopenharmony_ci * ADAPTER_STATE_LOCK must be released. 144962306a36Sopenharmony_ci * 145062306a36Sopenharmony_ci * Returns: 145162306a36Sopenharmony_ci * qla2x00 local function return status code. 145262306a36Sopenharmony_ci * 145362306a36Sopenharmony_ci * Context: 145462306a36Sopenharmony_ci * Kernel context. 145562306a36Sopenharmony_ci */ 145662306a36Sopenharmony_ciint 145762306a36Sopenharmony_ciqla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, 145862306a36Sopenharmony_ci dma_addr_t phys_addr, size_t size, uint32_t tov) 145962306a36Sopenharmony_ci{ 146062306a36Sopenharmony_ci int rval; 146162306a36Sopenharmony_ci mbx_cmd_t mc; 146262306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ci if (!vha->hw->flags.fw_started) 146562306a36Sopenharmony_ci return QLA_INVALID_COMMAND; 146662306a36Sopenharmony_ci 146762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1038, 146862306a36Sopenharmony_ci "Entered %s.\n", __func__); 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_ci mcp->mb[0] = MBC_IOCB_COMMAND_A64; 147162306a36Sopenharmony_ci mcp->mb[1] = 0; 147262306a36Sopenharmony_ci mcp->mb[2] = MSW(LSD(phys_addr)); 147362306a36Sopenharmony_ci mcp->mb[3] = LSW(LSD(phys_addr)); 147462306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(phys_addr)); 147562306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(phys_addr)); 147662306a36Sopenharmony_ci mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; 147762306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 147862306a36Sopenharmony_ci mcp->tov = tov; 147962306a36Sopenharmony_ci mcp->flags = 0; 148062306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 148362306a36Sopenharmony_ci /*EMPTY*/ 148462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1039, "Failed=%x.\n", rval); 148562306a36Sopenharmony_ci } else { 148662306a36Sopenharmony_ci sts_entry_t *sts_entry = buffer; 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci /* Mask reserved bits. */ 148962306a36Sopenharmony_ci sts_entry->entry_status &= 149062306a36Sopenharmony_ci IS_FWI2_CAPABLE(vha->hw) ? RF_MASK_24XX : RF_MASK; 149162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103a, 149262306a36Sopenharmony_ci "Done %s (status=%x).\n", __func__, 149362306a36Sopenharmony_ci sts_entry->entry_status); 149462306a36Sopenharmony_ci } 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_ci return rval; 149762306a36Sopenharmony_ci} 149862306a36Sopenharmony_ci 149962306a36Sopenharmony_ciint 150062306a36Sopenharmony_ciqla2x00_issue_iocb(scsi_qla_host_t *vha, void *buffer, dma_addr_t phys_addr, 150162306a36Sopenharmony_ci size_t size) 150262306a36Sopenharmony_ci{ 150362306a36Sopenharmony_ci return qla2x00_issue_iocb_timeout(vha, buffer, phys_addr, size, 150462306a36Sopenharmony_ci MBX_TOV_SECONDS); 150562306a36Sopenharmony_ci} 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_ci/* 150862306a36Sopenharmony_ci * qla2x00_abort_command 150962306a36Sopenharmony_ci * Abort command aborts a specified IOCB. 151062306a36Sopenharmony_ci * 151162306a36Sopenharmony_ci * Input: 151262306a36Sopenharmony_ci * ha = adapter block pointer. 151362306a36Sopenharmony_ci * sp = SB structure pointer. 151462306a36Sopenharmony_ci * 151562306a36Sopenharmony_ci * Returns: 151662306a36Sopenharmony_ci * qla2x00 local function return status code. 151762306a36Sopenharmony_ci * 151862306a36Sopenharmony_ci * Context: 151962306a36Sopenharmony_ci * Kernel context. 152062306a36Sopenharmony_ci */ 152162306a36Sopenharmony_ciint 152262306a36Sopenharmony_ciqla2x00_abort_command(srb_t *sp) 152362306a36Sopenharmony_ci{ 152462306a36Sopenharmony_ci unsigned long flags = 0; 152562306a36Sopenharmony_ci int rval; 152662306a36Sopenharmony_ci uint32_t handle = 0; 152762306a36Sopenharmony_ci mbx_cmd_t mc; 152862306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 152962306a36Sopenharmony_ci fc_port_t *fcport = sp->fcport; 153062306a36Sopenharmony_ci scsi_qla_host_t *vha = fcport->vha; 153162306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 153262306a36Sopenharmony_ci struct req_que *req; 153362306a36Sopenharmony_ci struct scsi_cmnd *cmd = GET_CMD_SP(sp); 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103b, 153662306a36Sopenharmony_ci "Entered %s.\n", __func__); 153762306a36Sopenharmony_ci 153862306a36Sopenharmony_ci if (sp->qpair) 153962306a36Sopenharmony_ci req = sp->qpair->req; 154062306a36Sopenharmony_ci else 154162306a36Sopenharmony_ci req = vha->req; 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 154462306a36Sopenharmony_ci for (handle = 1; handle < req->num_outstanding_cmds; handle++) { 154562306a36Sopenharmony_ci if (req->outstanding_cmds[handle] == sp) 154662306a36Sopenharmony_ci break; 154762306a36Sopenharmony_ci } 154862306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 154962306a36Sopenharmony_ci 155062306a36Sopenharmony_ci if (handle == req->num_outstanding_cmds) { 155162306a36Sopenharmony_ci /* command not found */ 155262306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 155362306a36Sopenharmony_ci } 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ci mcp->mb[0] = MBC_ABORT_COMMAND; 155662306a36Sopenharmony_ci if (HAS_EXTENDED_IDS(ha)) 155762306a36Sopenharmony_ci mcp->mb[1] = fcport->loop_id; 155862306a36Sopenharmony_ci else 155962306a36Sopenharmony_ci mcp->mb[1] = fcport->loop_id << 8; 156062306a36Sopenharmony_ci mcp->mb[2] = (uint16_t)handle; 156162306a36Sopenharmony_ci mcp->mb[3] = (uint16_t)(handle >> 16); 156262306a36Sopenharmony_ci mcp->mb[6] = (uint16_t)cmd->device->lun; 156362306a36Sopenharmony_ci mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; 156462306a36Sopenharmony_ci mcp->in_mb = MBX_0; 156562306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 156662306a36Sopenharmony_ci mcp->flags = 0; 156762306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 156862306a36Sopenharmony_ci 156962306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 157062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x103c, "Failed=%x.\n", rval); 157162306a36Sopenharmony_ci } else { 157262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103d, 157362306a36Sopenharmony_ci "Done %s.\n", __func__); 157462306a36Sopenharmony_ci } 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci return rval; 157762306a36Sopenharmony_ci} 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_ciint 158062306a36Sopenharmony_ciqla2x00_abort_target(struct fc_port *fcport, uint64_t l, int tag) 158162306a36Sopenharmony_ci{ 158262306a36Sopenharmony_ci int rval, rval2; 158362306a36Sopenharmony_ci mbx_cmd_t mc; 158462306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 158562306a36Sopenharmony_ci scsi_qla_host_t *vha; 158662306a36Sopenharmony_ci 158762306a36Sopenharmony_ci vha = fcport->vha; 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103e, 159062306a36Sopenharmony_ci "Entered %s.\n", __func__); 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_ci mcp->mb[0] = MBC_ABORT_TARGET; 159362306a36Sopenharmony_ci mcp->out_mb = MBX_9|MBX_2|MBX_1|MBX_0; 159462306a36Sopenharmony_ci if (HAS_EXTENDED_IDS(vha->hw)) { 159562306a36Sopenharmony_ci mcp->mb[1] = fcport->loop_id; 159662306a36Sopenharmony_ci mcp->mb[10] = 0; 159762306a36Sopenharmony_ci mcp->out_mb |= MBX_10; 159862306a36Sopenharmony_ci } else { 159962306a36Sopenharmony_ci mcp->mb[1] = fcport->loop_id << 8; 160062306a36Sopenharmony_ci } 160162306a36Sopenharmony_ci mcp->mb[2] = vha->hw->loop_reset_delay; 160262306a36Sopenharmony_ci mcp->mb[9] = vha->vp_idx; 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci mcp->in_mb = MBX_0; 160562306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 160662306a36Sopenharmony_ci mcp->flags = 0; 160762306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 160862306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 160962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103f, 161062306a36Sopenharmony_ci "Failed=%x.\n", rval); 161162306a36Sopenharmony_ci } 161262306a36Sopenharmony_ci 161362306a36Sopenharmony_ci /* Issue marker IOCB. */ 161462306a36Sopenharmony_ci rval2 = qla2x00_marker(vha, vha->hw->base_qpair, fcport->loop_id, 0, 161562306a36Sopenharmony_ci MK_SYNC_ID); 161662306a36Sopenharmony_ci if (rval2 != QLA_SUCCESS) { 161762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1040, 161862306a36Sopenharmony_ci "Failed to issue marker IOCB (%x).\n", rval2); 161962306a36Sopenharmony_ci } else { 162062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1041, 162162306a36Sopenharmony_ci "Done %s.\n", __func__); 162262306a36Sopenharmony_ci } 162362306a36Sopenharmony_ci 162462306a36Sopenharmony_ci return rval; 162562306a36Sopenharmony_ci} 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_ciint 162862306a36Sopenharmony_ciqla2x00_lun_reset(struct fc_port *fcport, uint64_t l, int tag) 162962306a36Sopenharmony_ci{ 163062306a36Sopenharmony_ci int rval, rval2; 163162306a36Sopenharmony_ci mbx_cmd_t mc; 163262306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 163362306a36Sopenharmony_ci scsi_qla_host_t *vha; 163462306a36Sopenharmony_ci 163562306a36Sopenharmony_ci vha = fcport->vha; 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1042, 163862306a36Sopenharmony_ci "Entered %s.\n", __func__); 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_ci mcp->mb[0] = MBC_LUN_RESET; 164162306a36Sopenharmony_ci mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0; 164262306a36Sopenharmony_ci if (HAS_EXTENDED_IDS(vha->hw)) 164362306a36Sopenharmony_ci mcp->mb[1] = fcport->loop_id; 164462306a36Sopenharmony_ci else 164562306a36Sopenharmony_ci mcp->mb[1] = fcport->loop_id << 8; 164662306a36Sopenharmony_ci mcp->mb[2] = (u32)l; 164762306a36Sopenharmony_ci mcp->mb[3] = 0; 164862306a36Sopenharmony_ci mcp->mb[9] = vha->vp_idx; 164962306a36Sopenharmony_ci 165062306a36Sopenharmony_ci mcp->in_mb = MBX_0; 165162306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 165262306a36Sopenharmony_ci mcp->flags = 0; 165362306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 165462306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 165562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1043, "Failed=%x.\n", rval); 165662306a36Sopenharmony_ci } 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci /* Issue marker IOCB. */ 165962306a36Sopenharmony_ci rval2 = qla2x00_marker(vha, vha->hw->base_qpair, fcport->loop_id, l, 166062306a36Sopenharmony_ci MK_SYNC_ID_LUN); 166162306a36Sopenharmony_ci if (rval2 != QLA_SUCCESS) { 166262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1044, 166362306a36Sopenharmony_ci "Failed to issue marker IOCB (%x).\n", rval2); 166462306a36Sopenharmony_ci } else { 166562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1045, 166662306a36Sopenharmony_ci "Done %s.\n", __func__); 166762306a36Sopenharmony_ci } 166862306a36Sopenharmony_ci 166962306a36Sopenharmony_ci return rval; 167062306a36Sopenharmony_ci} 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci/* 167362306a36Sopenharmony_ci * qla2x00_get_adapter_id 167462306a36Sopenharmony_ci * Get adapter ID and topology. 167562306a36Sopenharmony_ci * 167662306a36Sopenharmony_ci * Input: 167762306a36Sopenharmony_ci * ha = adapter block pointer. 167862306a36Sopenharmony_ci * id = pointer for loop ID. 167962306a36Sopenharmony_ci * al_pa = pointer for AL_PA. 168062306a36Sopenharmony_ci * area = pointer for area. 168162306a36Sopenharmony_ci * domain = pointer for domain. 168262306a36Sopenharmony_ci * top = pointer for topology. 168362306a36Sopenharmony_ci * TARGET_QUEUE_LOCK must be released. 168462306a36Sopenharmony_ci * ADAPTER_STATE_LOCK must be released. 168562306a36Sopenharmony_ci * 168662306a36Sopenharmony_ci * Returns: 168762306a36Sopenharmony_ci * qla2x00 local function return status code. 168862306a36Sopenharmony_ci * 168962306a36Sopenharmony_ci * Context: 169062306a36Sopenharmony_ci * Kernel context. 169162306a36Sopenharmony_ci */ 169262306a36Sopenharmony_ciint 169362306a36Sopenharmony_ciqla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, 169462306a36Sopenharmony_ci uint8_t *area, uint8_t *domain, uint16_t *top, uint16_t *sw_cap) 169562306a36Sopenharmony_ci{ 169662306a36Sopenharmony_ci int rval; 169762306a36Sopenharmony_ci mbx_cmd_t mc; 169862306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1046, 170162306a36Sopenharmony_ci "Entered %s.\n", __func__); 170262306a36Sopenharmony_ci 170362306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID; 170462306a36Sopenharmony_ci mcp->mb[9] = vha->vp_idx; 170562306a36Sopenharmony_ci mcp->out_mb = MBX_9|MBX_0; 170662306a36Sopenharmony_ci mcp->in_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; 170762306a36Sopenharmony_ci if (IS_CNA_CAPABLE(vha->hw)) 170862306a36Sopenharmony_ci mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10; 170962306a36Sopenharmony_ci if (IS_FWI2_CAPABLE(vha->hw)) 171062306a36Sopenharmony_ci mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16; 171162306a36Sopenharmony_ci if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) 171262306a36Sopenharmony_ci mcp->in_mb |= MBX_15|MBX_21|MBX_22|MBX_23; 171362306a36Sopenharmony_ci 171462306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 171562306a36Sopenharmony_ci mcp->flags = 0; 171662306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 171762306a36Sopenharmony_ci if (mcp->mb[0] == MBS_COMMAND_ERROR) 171862306a36Sopenharmony_ci rval = QLA_COMMAND_ERROR; 171962306a36Sopenharmony_ci else if (mcp->mb[0] == MBS_INVALID_COMMAND) 172062306a36Sopenharmony_ci rval = QLA_INVALID_COMMAND; 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_ci /* Return data. */ 172362306a36Sopenharmony_ci *id = mcp->mb[1]; 172462306a36Sopenharmony_ci *al_pa = LSB(mcp->mb[2]); 172562306a36Sopenharmony_ci *area = MSB(mcp->mb[2]); 172662306a36Sopenharmony_ci *domain = LSB(mcp->mb[3]); 172762306a36Sopenharmony_ci *top = mcp->mb[6]; 172862306a36Sopenharmony_ci *sw_cap = mcp->mb[7]; 172962306a36Sopenharmony_ci 173062306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 173162306a36Sopenharmony_ci /*EMPTY*/ 173262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1047, "Failed=%x.\n", rval); 173362306a36Sopenharmony_ci } else { 173462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1048, 173562306a36Sopenharmony_ci "Done %s.\n", __func__); 173662306a36Sopenharmony_ci 173762306a36Sopenharmony_ci if (IS_CNA_CAPABLE(vha->hw)) { 173862306a36Sopenharmony_ci vha->fcoe_vlan_id = mcp->mb[9] & 0xfff; 173962306a36Sopenharmony_ci vha->fcoe_fcf_idx = mcp->mb[10]; 174062306a36Sopenharmony_ci vha->fcoe_vn_port_mac[5] = mcp->mb[11] >> 8; 174162306a36Sopenharmony_ci vha->fcoe_vn_port_mac[4] = mcp->mb[11] & 0xff; 174262306a36Sopenharmony_ci vha->fcoe_vn_port_mac[3] = mcp->mb[12] >> 8; 174362306a36Sopenharmony_ci vha->fcoe_vn_port_mac[2] = mcp->mb[12] & 0xff; 174462306a36Sopenharmony_ci vha->fcoe_vn_port_mac[1] = mcp->mb[13] >> 8; 174562306a36Sopenharmony_ci vha->fcoe_vn_port_mac[0] = mcp->mb[13] & 0xff; 174662306a36Sopenharmony_ci } 174762306a36Sopenharmony_ci /* If FA-WWN supported */ 174862306a36Sopenharmony_ci if (IS_FAWWN_CAPABLE(vha->hw)) { 174962306a36Sopenharmony_ci if (mcp->mb[7] & BIT_14) { 175062306a36Sopenharmony_ci vha->port_name[0] = MSB(mcp->mb[16]); 175162306a36Sopenharmony_ci vha->port_name[1] = LSB(mcp->mb[16]); 175262306a36Sopenharmony_ci vha->port_name[2] = MSB(mcp->mb[17]); 175362306a36Sopenharmony_ci vha->port_name[3] = LSB(mcp->mb[17]); 175462306a36Sopenharmony_ci vha->port_name[4] = MSB(mcp->mb[18]); 175562306a36Sopenharmony_ci vha->port_name[5] = LSB(mcp->mb[18]); 175662306a36Sopenharmony_ci vha->port_name[6] = MSB(mcp->mb[19]); 175762306a36Sopenharmony_ci vha->port_name[7] = LSB(mcp->mb[19]); 175862306a36Sopenharmony_ci fc_host_port_name(vha->host) = 175962306a36Sopenharmony_ci wwn_to_u64(vha->port_name); 176062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10ca, 176162306a36Sopenharmony_ci "FA-WWN acquired %016llx\n", 176262306a36Sopenharmony_ci wwn_to_u64(vha->port_name)); 176362306a36Sopenharmony_ci } 176462306a36Sopenharmony_ci } 176562306a36Sopenharmony_ci 176662306a36Sopenharmony_ci if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) { 176762306a36Sopenharmony_ci vha->bbcr = mcp->mb[15]; 176862306a36Sopenharmony_ci if (mcp->mb[7] & SCM_EDC_ACC_RECEIVED) { 176962306a36Sopenharmony_ci ql_log(ql_log_info, vha, 0x11a4, 177062306a36Sopenharmony_ci "SCM: EDC ELS completed, flags 0x%x\n", 177162306a36Sopenharmony_ci mcp->mb[21]); 177262306a36Sopenharmony_ci } 177362306a36Sopenharmony_ci if (mcp->mb[7] & SCM_RDF_ACC_RECEIVED) { 177462306a36Sopenharmony_ci vha->hw->flags.scm_enabled = 1; 177562306a36Sopenharmony_ci vha->scm_fabric_connection_flags |= 177662306a36Sopenharmony_ci SCM_FLAG_RDF_COMPLETED; 177762306a36Sopenharmony_ci ql_log(ql_log_info, vha, 0x11a5, 177862306a36Sopenharmony_ci "SCM: RDF ELS completed, flags 0x%x\n", 177962306a36Sopenharmony_ci mcp->mb[23]); 178062306a36Sopenharmony_ci } 178162306a36Sopenharmony_ci } 178262306a36Sopenharmony_ci } 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci return rval; 178562306a36Sopenharmony_ci} 178662306a36Sopenharmony_ci 178762306a36Sopenharmony_ci/* 178862306a36Sopenharmony_ci * qla2x00_get_retry_cnt 178962306a36Sopenharmony_ci * Get current firmware login retry count and delay. 179062306a36Sopenharmony_ci * 179162306a36Sopenharmony_ci * Input: 179262306a36Sopenharmony_ci * ha = adapter block pointer. 179362306a36Sopenharmony_ci * retry_cnt = pointer to login retry count. 179462306a36Sopenharmony_ci * tov = pointer to login timeout value. 179562306a36Sopenharmony_ci * 179662306a36Sopenharmony_ci * Returns: 179762306a36Sopenharmony_ci * qla2x00 local function return status code. 179862306a36Sopenharmony_ci * 179962306a36Sopenharmony_ci * Context: 180062306a36Sopenharmony_ci * Kernel context. 180162306a36Sopenharmony_ci */ 180262306a36Sopenharmony_ciint 180362306a36Sopenharmony_ciqla2x00_get_retry_cnt(scsi_qla_host_t *vha, uint8_t *retry_cnt, uint8_t *tov, 180462306a36Sopenharmony_ci uint16_t *r_a_tov) 180562306a36Sopenharmony_ci{ 180662306a36Sopenharmony_ci int rval; 180762306a36Sopenharmony_ci uint16_t ratov; 180862306a36Sopenharmony_ci mbx_cmd_t mc; 180962306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 181062306a36Sopenharmony_ci 181162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1049, 181262306a36Sopenharmony_ci "Entered %s.\n", __func__); 181362306a36Sopenharmony_ci 181462306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_RETRY_COUNT; 181562306a36Sopenharmony_ci mcp->out_mb = MBX_0; 181662306a36Sopenharmony_ci mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0; 181762306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 181862306a36Sopenharmony_ci mcp->flags = 0; 181962306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 182062306a36Sopenharmony_ci 182162306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 182262306a36Sopenharmony_ci /*EMPTY*/ 182362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x104a, 182462306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 182562306a36Sopenharmony_ci } else { 182662306a36Sopenharmony_ci /* Convert returned data and check our values. */ 182762306a36Sopenharmony_ci *r_a_tov = mcp->mb[3] / 2; 182862306a36Sopenharmony_ci ratov = (mcp->mb[3]/2) / 10; /* mb[3] value is in 100ms */ 182962306a36Sopenharmony_ci if (mcp->mb[1] * ratov > (*retry_cnt) * (*tov)) { 183062306a36Sopenharmony_ci /* Update to the larger values */ 183162306a36Sopenharmony_ci *retry_cnt = (uint8_t)mcp->mb[1]; 183262306a36Sopenharmony_ci *tov = ratov; 183362306a36Sopenharmony_ci } 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104b, 183662306a36Sopenharmony_ci "Done %s mb3=%d ratov=%d.\n", __func__, mcp->mb[3], ratov); 183762306a36Sopenharmony_ci } 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_ci return rval; 184062306a36Sopenharmony_ci} 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_ci/* 184362306a36Sopenharmony_ci * qla2x00_init_firmware 184462306a36Sopenharmony_ci * Initialize adapter firmware. 184562306a36Sopenharmony_ci * 184662306a36Sopenharmony_ci * Input: 184762306a36Sopenharmony_ci * ha = adapter block pointer. 184862306a36Sopenharmony_ci * dptr = Initialization control block pointer. 184962306a36Sopenharmony_ci * size = size of initialization control block. 185062306a36Sopenharmony_ci * TARGET_QUEUE_LOCK must be released. 185162306a36Sopenharmony_ci * ADAPTER_STATE_LOCK must be released. 185262306a36Sopenharmony_ci * 185362306a36Sopenharmony_ci * Returns: 185462306a36Sopenharmony_ci * qla2x00 local function return status code. 185562306a36Sopenharmony_ci * 185662306a36Sopenharmony_ci * Context: 185762306a36Sopenharmony_ci * Kernel context. 185862306a36Sopenharmony_ci */ 185962306a36Sopenharmony_ciint 186062306a36Sopenharmony_ciqla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size) 186162306a36Sopenharmony_ci{ 186262306a36Sopenharmony_ci int rval; 186362306a36Sopenharmony_ci mbx_cmd_t mc; 186462306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 186562306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 186662306a36Sopenharmony_ci 186762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104c, 186862306a36Sopenharmony_ci "Entered %s.\n", __func__); 186962306a36Sopenharmony_ci 187062306a36Sopenharmony_ci if (IS_P3P_TYPE(ha) && ql2xdbwr) 187162306a36Sopenharmony_ci qla82xx_wr_32(ha, (uintptr_t __force)ha->nxdb_wr_ptr, 187262306a36Sopenharmony_ci (0x04 | (ha->portnum << 5) | (0 << 8) | (0 << 16))); 187362306a36Sopenharmony_ci 187462306a36Sopenharmony_ci if (ha->flags.npiv_supported) 187562306a36Sopenharmony_ci mcp->mb[0] = MBC_MID_INITIALIZE_FIRMWARE; 187662306a36Sopenharmony_ci else 187762306a36Sopenharmony_ci mcp->mb[0] = MBC_INITIALIZE_FIRMWARE; 187862306a36Sopenharmony_ci 187962306a36Sopenharmony_ci mcp->mb[1] = 0; 188062306a36Sopenharmony_ci mcp->mb[2] = MSW(ha->init_cb_dma); 188162306a36Sopenharmony_ci mcp->mb[3] = LSW(ha->init_cb_dma); 188262306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(ha->init_cb_dma)); 188362306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(ha->init_cb_dma)); 188462306a36Sopenharmony_ci mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; 188562306a36Sopenharmony_ci if (ha->ex_init_cb && ha->ex_init_cb->ex_version) { 188662306a36Sopenharmony_ci mcp->mb[1] = BIT_0; 188762306a36Sopenharmony_ci mcp->mb[10] = MSW(ha->ex_init_cb_dma); 188862306a36Sopenharmony_ci mcp->mb[11] = LSW(ha->ex_init_cb_dma); 188962306a36Sopenharmony_ci mcp->mb[12] = MSW(MSD(ha->ex_init_cb_dma)); 189062306a36Sopenharmony_ci mcp->mb[13] = LSW(MSD(ha->ex_init_cb_dma)); 189162306a36Sopenharmony_ci mcp->mb[14] = sizeof(*ha->ex_init_cb); 189262306a36Sopenharmony_ci mcp->out_mb |= MBX_14|MBX_13|MBX_12|MBX_11|MBX_10; 189362306a36Sopenharmony_ci } 189462306a36Sopenharmony_ci 189562306a36Sopenharmony_ci if (ha->flags.scm_supported_f || vha->flags.nvme2_enabled) { 189662306a36Sopenharmony_ci mcp->mb[1] |= BIT_1; 189762306a36Sopenharmony_ci mcp->mb[16] = MSW(ha->sf_init_cb_dma); 189862306a36Sopenharmony_ci mcp->mb[17] = LSW(ha->sf_init_cb_dma); 189962306a36Sopenharmony_ci mcp->mb[18] = MSW(MSD(ha->sf_init_cb_dma)); 190062306a36Sopenharmony_ci mcp->mb[19] = LSW(MSD(ha->sf_init_cb_dma)); 190162306a36Sopenharmony_ci mcp->mb[15] = sizeof(*ha->sf_init_cb); 190262306a36Sopenharmony_ci mcp->out_mb |= MBX_19|MBX_18|MBX_17|MBX_16|MBX_15; 190362306a36Sopenharmony_ci } 190462306a36Sopenharmony_ci 190562306a36Sopenharmony_ci /* 1 and 2 should normally be captured. */ 190662306a36Sopenharmony_ci mcp->in_mb = MBX_2|MBX_1|MBX_0; 190762306a36Sopenharmony_ci if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) 190862306a36Sopenharmony_ci /* mb3 is additional info about the installed SFP. */ 190962306a36Sopenharmony_ci mcp->in_mb |= MBX_3; 191062306a36Sopenharmony_ci mcp->buf_size = size; 191162306a36Sopenharmony_ci mcp->flags = MBX_DMA_OUT; 191262306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 191362306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 191462306a36Sopenharmony_ci 191562306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 191662306a36Sopenharmony_ci /*EMPTY*/ 191762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x104d, 191862306a36Sopenharmony_ci "Failed=%x mb[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x.\n", 191962306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3]); 192062306a36Sopenharmony_ci if (ha->init_cb) { 192162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x104d, "init_cb:\n"); 192262306a36Sopenharmony_ci ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 192362306a36Sopenharmony_ci 0x0104d, ha->init_cb, sizeof(*ha->init_cb)); 192462306a36Sopenharmony_ci } 192562306a36Sopenharmony_ci if (ha->ex_init_cb && ha->ex_init_cb->ex_version) { 192662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x104d, "ex_init_cb:\n"); 192762306a36Sopenharmony_ci ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 192862306a36Sopenharmony_ci 0x0104d, ha->ex_init_cb, sizeof(*ha->ex_init_cb)); 192962306a36Sopenharmony_ci } 193062306a36Sopenharmony_ci } else { 193162306a36Sopenharmony_ci if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { 193262306a36Sopenharmony_ci if (mcp->mb[2] == 6 || mcp->mb[3] == 2) 193362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x119d, 193462306a36Sopenharmony_ci "Invalid SFP/Validation Failed\n"); 193562306a36Sopenharmony_ci } 193662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104e, 193762306a36Sopenharmony_ci "Done %s.\n", __func__); 193862306a36Sopenharmony_ci } 193962306a36Sopenharmony_ci 194062306a36Sopenharmony_ci return rval; 194162306a36Sopenharmony_ci} 194262306a36Sopenharmony_ci 194362306a36Sopenharmony_ci 194462306a36Sopenharmony_ci/* 194562306a36Sopenharmony_ci * qla2x00_get_port_database 194662306a36Sopenharmony_ci * Issue normal/enhanced get port database mailbox command 194762306a36Sopenharmony_ci * and copy device name as necessary. 194862306a36Sopenharmony_ci * 194962306a36Sopenharmony_ci * Input: 195062306a36Sopenharmony_ci * ha = adapter state pointer. 195162306a36Sopenharmony_ci * dev = structure pointer. 195262306a36Sopenharmony_ci * opt = enhanced cmd option byte. 195362306a36Sopenharmony_ci * 195462306a36Sopenharmony_ci * Returns: 195562306a36Sopenharmony_ci * qla2x00 local function return status code. 195662306a36Sopenharmony_ci * 195762306a36Sopenharmony_ci * Context: 195862306a36Sopenharmony_ci * Kernel context. 195962306a36Sopenharmony_ci */ 196062306a36Sopenharmony_ciint 196162306a36Sopenharmony_ciqla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) 196262306a36Sopenharmony_ci{ 196362306a36Sopenharmony_ci int rval; 196462306a36Sopenharmony_ci mbx_cmd_t mc; 196562306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 196662306a36Sopenharmony_ci port_database_t *pd; 196762306a36Sopenharmony_ci struct port_database_24xx *pd24; 196862306a36Sopenharmony_ci dma_addr_t pd_dma; 196962306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 197062306a36Sopenharmony_ci 197162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104f, 197262306a36Sopenharmony_ci "Entered %s.\n", __func__); 197362306a36Sopenharmony_ci 197462306a36Sopenharmony_ci pd24 = NULL; 197562306a36Sopenharmony_ci pd = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma); 197662306a36Sopenharmony_ci if (pd == NULL) { 197762306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1050, 197862306a36Sopenharmony_ci "Failed to allocate port database structure.\n"); 197962306a36Sopenharmony_ci fcport->query = 0; 198062306a36Sopenharmony_ci return QLA_MEMORY_ALLOC_FAILED; 198162306a36Sopenharmony_ci } 198262306a36Sopenharmony_ci 198362306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_PORT_DATABASE; 198462306a36Sopenharmony_ci if (opt != 0 && !IS_FWI2_CAPABLE(ha)) 198562306a36Sopenharmony_ci mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE; 198662306a36Sopenharmony_ci mcp->mb[2] = MSW(pd_dma); 198762306a36Sopenharmony_ci mcp->mb[3] = LSW(pd_dma); 198862306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(pd_dma)); 198962306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(pd_dma)); 199062306a36Sopenharmony_ci mcp->mb[9] = vha->vp_idx; 199162306a36Sopenharmony_ci mcp->out_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; 199262306a36Sopenharmony_ci mcp->in_mb = MBX_0; 199362306a36Sopenharmony_ci if (IS_FWI2_CAPABLE(ha)) { 199462306a36Sopenharmony_ci mcp->mb[1] = fcport->loop_id; 199562306a36Sopenharmony_ci mcp->mb[10] = opt; 199662306a36Sopenharmony_ci mcp->out_mb |= MBX_10|MBX_1; 199762306a36Sopenharmony_ci mcp->in_mb |= MBX_1; 199862306a36Sopenharmony_ci } else if (HAS_EXTENDED_IDS(ha)) { 199962306a36Sopenharmony_ci mcp->mb[1] = fcport->loop_id; 200062306a36Sopenharmony_ci mcp->mb[10] = opt; 200162306a36Sopenharmony_ci mcp->out_mb |= MBX_10|MBX_1; 200262306a36Sopenharmony_ci } else { 200362306a36Sopenharmony_ci mcp->mb[1] = fcport->loop_id << 8 | opt; 200462306a36Sopenharmony_ci mcp->out_mb |= MBX_1; 200562306a36Sopenharmony_ci } 200662306a36Sopenharmony_ci mcp->buf_size = IS_FWI2_CAPABLE(ha) ? 200762306a36Sopenharmony_ci PORT_DATABASE_24XX_SIZE : PORT_DATABASE_SIZE; 200862306a36Sopenharmony_ci mcp->flags = MBX_DMA_IN; 200962306a36Sopenharmony_ci mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); 201062306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 201162306a36Sopenharmony_ci if (rval != QLA_SUCCESS) 201262306a36Sopenharmony_ci goto gpd_error_out; 201362306a36Sopenharmony_ci 201462306a36Sopenharmony_ci if (IS_FWI2_CAPABLE(ha)) { 201562306a36Sopenharmony_ci uint64_t zero = 0; 201662306a36Sopenharmony_ci u8 current_login_state, last_login_state; 201762306a36Sopenharmony_ci 201862306a36Sopenharmony_ci pd24 = (struct port_database_24xx *) pd; 201962306a36Sopenharmony_ci 202062306a36Sopenharmony_ci /* Check for logged in state. */ 202162306a36Sopenharmony_ci if (NVME_TARGET(ha, fcport)) { 202262306a36Sopenharmony_ci current_login_state = pd24->current_login_state >> 4; 202362306a36Sopenharmony_ci last_login_state = pd24->last_login_state >> 4; 202462306a36Sopenharmony_ci } else { 202562306a36Sopenharmony_ci current_login_state = pd24->current_login_state & 0xf; 202662306a36Sopenharmony_ci last_login_state = pd24->last_login_state & 0xf; 202762306a36Sopenharmony_ci } 202862306a36Sopenharmony_ci fcport->current_login_state = pd24->current_login_state; 202962306a36Sopenharmony_ci fcport->last_login_state = pd24->last_login_state; 203062306a36Sopenharmony_ci 203162306a36Sopenharmony_ci /* Check for logged in state. */ 203262306a36Sopenharmony_ci if (current_login_state != PDS_PRLI_COMPLETE && 203362306a36Sopenharmony_ci last_login_state != PDS_PRLI_COMPLETE) { 203462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x119a, 203562306a36Sopenharmony_ci "Unable to verify login-state (%x/%x) for loop_id %x.\n", 203662306a36Sopenharmony_ci current_login_state, last_login_state, 203762306a36Sopenharmony_ci fcport->loop_id); 203862306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 203962306a36Sopenharmony_ci 204062306a36Sopenharmony_ci if (!fcport->query) 204162306a36Sopenharmony_ci goto gpd_error_out; 204262306a36Sopenharmony_ci } 204362306a36Sopenharmony_ci 204462306a36Sopenharmony_ci if (fcport->loop_id == FC_NO_LOOP_ID || 204562306a36Sopenharmony_ci (memcmp(fcport->port_name, (uint8_t *)&zero, 8) && 204662306a36Sopenharmony_ci memcmp(fcport->port_name, pd24->port_name, 8))) { 204762306a36Sopenharmony_ci /* We lost the device mid way. */ 204862306a36Sopenharmony_ci rval = QLA_NOT_LOGGED_IN; 204962306a36Sopenharmony_ci goto gpd_error_out; 205062306a36Sopenharmony_ci } 205162306a36Sopenharmony_ci 205262306a36Sopenharmony_ci /* Names are little-endian. */ 205362306a36Sopenharmony_ci memcpy(fcport->node_name, pd24->node_name, WWN_SIZE); 205462306a36Sopenharmony_ci memcpy(fcport->port_name, pd24->port_name, WWN_SIZE); 205562306a36Sopenharmony_ci 205662306a36Sopenharmony_ci /* Get port_id of device. */ 205762306a36Sopenharmony_ci fcport->d_id.b.domain = pd24->port_id[0]; 205862306a36Sopenharmony_ci fcport->d_id.b.area = pd24->port_id[1]; 205962306a36Sopenharmony_ci fcport->d_id.b.al_pa = pd24->port_id[2]; 206062306a36Sopenharmony_ci fcport->d_id.b.rsvd_1 = 0; 206162306a36Sopenharmony_ci 206262306a36Sopenharmony_ci /* If not target must be initiator or unknown type. */ 206362306a36Sopenharmony_ci if ((pd24->prli_svc_param_word_3[0] & BIT_4) == 0) 206462306a36Sopenharmony_ci fcport->port_type = FCT_INITIATOR; 206562306a36Sopenharmony_ci else 206662306a36Sopenharmony_ci fcport->port_type = FCT_TARGET; 206762306a36Sopenharmony_ci 206862306a36Sopenharmony_ci /* Passback COS information. */ 206962306a36Sopenharmony_ci fcport->supported_classes = (pd24->flags & PDF_CLASS_2) ? 207062306a36Sopenharmony_ci FC_COS_CLASS2 : FC_COS_CLASS3; 207162306a36Sopenharmony_ci 207262306a36Sopenharmony_ci if (pd24->prli_svc_param_word_3[0] & BIT_7) 207362306a36Sopenharmony_ci fcport->flags |= FCF_CONF_COMP_SUPPORTED; 207462306a36Sopenharmony_ci } else { 207562306a36Sopenharmony_ci uint64_t zero = 0; 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_ci /* Check for logged in state. */ 207862306a36Sopenharmony_ci if (pd->master_state != PD_STATE_PORT_LOGGED_IN && 207962306a36Sopenharmony_ci pd->slave_state != PD_STATE_PORT_LOGGED_IN) { 208062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x100a, 208162306a36Sopenharmony_ci "Unable to verify login-state (%x/%x) - " 208262306a36Sopenharmony_ci "portid=%02x%02x%02x.\n", pd->master_state, 208362306a36Sopenharmony_ci pd->slave_state, fcport->d_id.b.domain, 208462306a36Sopenharmony_ci fcport->d_id.b.area, fcport->d_id.b.al_pa); 208562306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 208662306a36Sopenharmony_ci goto gpd_error_out; 208762306a36Sopenharmony_ci } 208862306a36Sopenharmony_ci 208962306a36Sopenharmony_ci if (fcport->loop_id == FC_NO_LOOP_ID || 209062306a36Sopenharmony_ci (memcmp(fcport->port_name, (uint8_t *)&zero, 8) && 209162306a36Sopenharmony_ci memcmp(fcport->port_name, pd->port_name, 8))) { 209262306a36Sopenharmony_ci /* We lost the device mid way. */ 209362306a36Sopenharmony_ci rval = QLA_NOT_LOGGED_IN; 209462306a36Sopenharmony_ci goto gpd_error_out; 209562306a36Sopenharmony_ci } 209662306a36Sopenharmony_ci 209762306a36Sopenharmony_ci /* Names are little-endian. */ 209862306a36Sopenharmony_ci memcpy(fcport->node_name, pd->node_name, WWN_SIZE); 209962306a36Sopenharmony_ci memcpy(fcport->port_name, pd->port_name, WWN_SIZE); 210062306a36Sopenharmony_ci 210162306a36Sopenharmony_ci /* Get port_id of device. */ 210262306a36Sopenharmony_ci fcport->d_id.b.domain = pd->port_id[0]; 210362306a36Sopenharmony_ci fcport->d_id.b.area = pd->port_id[3]; 210462306a36Sopenharmony_ci fcport->d_id.b.al_pa = pd->port_id[2]; 210562306a36Sopenharmony_ci fcport->d_id.b.rsvd_1 = 0; 210662306a36Sopenharmony_ci 210762306a36Sopenharmony_ci /* If not target must be initiator or unknown type. */ 210862306a36Sopenharmony_ci if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0) 210962306a36Sopenharmony_ci fcport->port_type = FCT_INITIATOR; 211062306a36Sopenharmony_ci else 211162306a36Sopenharmony_ci fcport->port_type = FCT_TARGET; 211262306a36Sopenharmony_ci 211362306a36Sopenharmony_ci /* Passback COS information. */ 211462306a36Sopenharmony_ci fcport->supported_classes = (pd->options & BIT_4) ? 211562306a36Sopenharmony_ci FC_COS_CLASS2 : FC_COS_CLASS3; 211662306a36Sopenharmony_ci } 211762306a36Sopenharmony_ci 211862306a36Sopenharmony_cigpd_error_out: 211962306a36Sopenharmony_ci dma_pool_free(ha->s_dma_pool, pd, pd_dma); 212062306a36Sopenharmony_ci fcport->query = 0; 212162306a36Sopenharmony_ci 212262306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 212362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1052, 212462306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x.\n", rval, 212562306a36Sopenharmony_ci mcp->mb[0], mcp->mb[1]); 212662306a36Sopenharmony_ci } else { 212762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1053, 212862306a36Sopenharmony_ci "Done %s.\n", __func__); 212962306a36Sopenharmony_ci } 213062306a36Sopenharmony_ci 213162306a36Sopenharmony_ci return rval; 213262306a36Sopenharmony_ci} 213362306a36Sopenharmony_ci 213462306a36Sopenharmony_ciint 213562306a36Sopenharmony_ciqla24xx_get_port_database(scsi_qla_host_t *vha, u16 nport_handle, 213662306a36Sopenharmony_ci struct port_database_24xx *pdb) 213762306a36Sopenharmony_ci{ 213862306a36Sopenharmony_ci mbx_cmd_t mc; 213962306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 214062306a36Sopenharmony_ci dma_addr_t pdb_dma; 214162306a36Sopenharmony_ci int rval; 214262306a36Sopenharmony_ci 214362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1115, 214462306a36Sopenharmony_ci "Entered %s.\n", __func__); 214562306a36Sopenharmony_ci 214662306a36Sopenharmony_ci memset(pdb, 0, sizeof(*pdb)); 214762306a36Sopenharmony_ci 214862306a36Sopenharmony_ci pdb_dma = dma_map_single(&vha->hw->pdev->dev, pdb, 214962306a36Sopenharmony_ci sizeof(*pdb), DMA_FROM_DEVICE); 215062306a36Sopenharmony_ci if (!pdb_dma) { 215162306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1116, "Failed to map dma buffer.\n"); 215262306a36Sopenharmony_ci return QLA_MEMORY_ALLOC_FAILED; 215362306a36Sopenharmony_ci } 215462306a36Sopenharmony_ci 215562306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_PORT_DATABASE; 215662306a36Sopenharmony_ci mcp->mb[1] = nport_handle; 215762306a36Sopenharmony_ci mcp->mb[2] = MSW(LSD(pdb_dma)); 215862306a36Sopenharmony_ci mcp->mb[3] = LSW(LSD(pdb_dma)); 215962306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(pdb_dma)); 216062306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(pdb_dma)); 216162306a36Sopenharmony_ci mcp->mb[9] = 0; 216262306a36Sopenharmony_ci mcp->mb[10] = 0; 216362306a36Sopenharmony_ci mcp->out_mb = MBX_10|MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; 216462306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 216562306a36Sopenharmony_ci mcp->buf_size = sizeof(*pdb); 216662306a36Sopenharmony_ci mcp->flags = MBX_DMA_IN; 216762306a36Sopenharmony_ci mcp->tov = vha->hw->login_timeout * 2; 216862306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 216962306a36Sopenharmony_ci 217062306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 217162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x111a, 217262306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x.\n", 217362306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1]); 217462306a36Sopenharmony_ci } else { 217562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x111b, 217662306a36Sopenharmony_ci "Done %s.\n", __func__); 217762306a36Sopenharmony_ci } 217862306a36Sopenharmony_ci 217962306a36Sopenharmony_ci dma_unmap_single(&vha->hw->pdev->dev, pdb_dma, 218062306a36Sopenharmony_ci sizeof(*pdb), DMA_FROM_DEVICE); 218162306a36Sopenharmony_ci 218262306a36Sopenharmony_ci return rval; 218362306a36Sopenharmony_ci} 218462306a36Sopenharmony_ci 218562306a36Sopenharmony_ci/* 218662306a36Sopenharmony_ci * qla2x00_get_firmware_state 218762306a36Sopenharmony_ci * Get adapter firmware state. 218862306a36Sopenharmony_ci * 218962306a36Sopenharmony_ci * Input: 219062306a36Sopenharmony_ci * ha = adapter block pointer. 219162306a36Sopenharmony_ci * dptr = pointer for firmware state. 219262306a36Sopenharmony_ci * TARGET_QUEUE_LOCK must be released. 219362306a36Sopenharmony_ci * ADAPTER_STATE_LOCK must be released. 219462306a36Sopenharmony_ci * 219562306a36Sopenharmony_ci * Returns: 219662306a36Sopenharmony_ci * qla2x00 local function return status code. 219762306a36Sopenharmony_ci * 219862306a36Sopenharmony_ci * Context: 219962306a36Sopenharmony_ci * Kernel context. 220062306a36Sopenharmony_ci */ 220162306a36Sopenharmony_ciint 220262306a36Sopenharmony_ciqla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states) 220362306a36Sopenharmony_ci{ 220462306a36Sopenharmony_ci int rval; 220562306a36Sopenharmony_ci mbx_cmd_t mc; 220662306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 220762306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 220862306a36Sopenharmony_ci 220962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1054, 221062306a36Sopenharmony_ci "Entered %s.\n", __func__); 221162306a36Sopenharmony_ci 221262306a36Sopenharmony_ci if (!ha->flags.fw_started) 221362306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 221462306a36Sopenharmony_ci 221562306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_FIRMWARE_STATE; 221662306a36Sopenharmony_ci mcp->out_mb = MBX_0; 221762306a36Sopenharmony_ci if (IS_FWI2_CAPABLE(vha->hw)) 221862306a36Sopenharmony_ci mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 221962306a36Sopenharmony_ci else 222062306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 222162306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 222262306a36Sopenharmony_ci mcp->flags = 0; 222362306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 222462306a36Sopenharmony_ci 222562306a36Sopenharmony_ci /* Return firmware states. */ 222662306a36Sopenharmony_ci states[0] = mcp->mb[1]; 222762306a36Sopenharmony_ci if (IS_FWI2_CAPABLE(vha->hw)) { 222862306a36Sopenharmony_ci states[1] = mcp->mb[2]; 222962306a36Sopenharmony_ci states[2] = mcp->mb[3]; /* SFP info */ 223062306a36Sopenharmony_ci states[3] = mcp->mb[4]; 223162306a36Sopenharmony_ci states[4] = mcp->mb[5]; 223262306a36Sopenharmony_ci states[5] = mcp->mb[6]; /* DPORT status */ 223362306a36Sopenharmony_ci } 223462306a36Sopenharmony_ci 223562306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 223662306a36Sopenharmony_ci /*EMPTY*/ 223762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1055, "Failed=%x.\n", rval); 223862306a36Sopenharmony_ci } else { 223962306a36Sopenharmony_ci if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { 224062306a36Sopenharmony_ci if (mcp->mb[2] == 6 || mcp->mb[3] == 2) 224162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x119e, 224262306a36Sopenharmony_ci "Invalid SFP/Validation Failed\n"); 224362306a36Sopenharmony_ci } 224462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1056, 224562306a36Sopenharmony_ci "Done %s.\n", __func__); 224662306a36Sopenharmony_ci } 224762306a36Sopenharmony_ci 224862306a36Sopenharmony_ci return rval; 224962306a36Sopenharmony_ci} 225062306a36Sopenharmony_ci 225162306a36Sopenharmony_ci/* 225262306a36Sopenharmony_ci * qla2x00_get_port_name 225362306a36Sopenharmony_ci * Issue get port name mailbox command. 225462306a36Sopenharmony_ci * Returned name is in big endian format. 225562306a36Sopenharmony_ci * 225662306a36Sopenharmony_ci * Input: 225762306a36Sopenharmony_ci * ha = adapter block pointer. 225862306a36Sopenharmony_ci * loop_id = loop ID of device. 225962306a36Sopenharmony_ci * name = pointer for name. 226062306a36Sopenharmony_ci * TARGET_QUEUE_LOCK must be released. 226162306a36Sopenharmony_ci * ADAPTER_STATE_LOCK must be released. 226262306a36Sopenharmony_ci * 226362306a36Sopenharmony_ci * Returns: 226462306a36Sopenharmony_ci * qla2x00 local function return status code. 226562306a36Sopenharmony_ci * 226662306a36Sopenharmony_ci * Context: 226762306a36Sopenharmony_ci * Kernel context. 226862306a36Sopenharmony_ci */ 226962306a36Sopenharmony_ciint 227062306a36Sopenharmony_ciqla2x00_get_port_name(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t *name, 227162306a36Sopenharmony_ci uint8_t opt) 227262306a36Sopenharmony_ci{ 227362306a36Sopenharmony_ci int rval; 227462306a36Sopenharmony_ci mbx_cmd_t mc; 227562306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 227662306a36Sopenharmony_ci 227762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1057, 227862306a36Sopenharmony_ci "Entered %s.\n", __func__); 227962306a36Sopenharmony_ci 228062306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_PORT_NAME; 228162306a36Sopenharmony_ci mcp->mb[9] = vha->vp_idx; 228262306a36Sopenharmony_ci mcp->out_mb = MBX_9|MBX_1|MBX_0; 228362306a36Sopenharmony_ci if (HAS_EXTENDED_IDS(vha->hw)) { 228462306a36Sopenharmony_ci mcp->mb[1] = loop_id; 228562306a36Sopenharmony_ci mcp->mb[10] = opt; 228662306a36Sopenharmony_ci mcp->out_mb |= MBX_10; 228762306a36Sopenharmony_ci } else { 228862306a36Sopenharmony_ci mcp->mb[1] = loop_id << 8 | opt; 228962306a36Sopenharmony_ci } 229062306a36Sopenharmony_ci 229162306a36Sopenharmony_ci mcp->in_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; 229262306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 229362306a36Sopenharmony_ci mcp->flags = 0; 229462306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 229562306a36Sopenharmony_ci 229662306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 229762306a36Sopenharmony_ci /*EMPTY*/ 229862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1058, "Failed=%x.\n", rval); 229962306a36Sopenharmony_ci } else { 230062306a36Sopenharmony_ci if (name != NULL) { 230162306a36Sopenharmony_ci /* This function returns name in big endian. */ 230262306a36Sopenharmony_ci name[0] = MSB(mcp->mb[2]); 230362306a36Sopenharmony_ci name[1] = LSB(mcp->mb[2]); 230462306a36Sopenharmony_ci name[2] = MSB(mcp->mb[3]); 230562306a36Sopenharmony_ci name[3] = LSB(mcp->mb[3]); 230662306a36Sopenharmony_ci name[4] = MSB(mcp->mb[6]); 230762306a36Sopenharmony_ci name[5] = LSB(mcp->mb[6]); 230862306a36Sopenharmony_ci name[6] = MSB(mcp->mb[7]); 230962306a36Sopenharmony_ci name[7] = LSB(mcp->mb[7]); 231062306a36Sopenharmony_ci } 231162306a36Sopenharmony_ci 231262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1059, 231362306a36Sopenharmony_ci "Done %s.\n", __func__); 231462306a36Sopenharmony_ci } 231562306a36Sopenharmony_ci 231662306a36Sopenharmony_ci return rval; 231762306a36Sopenharmony_ci} 231862306a36Sopenharmony_ci 231962306a36Sopenharmony_ci/* 232062306a36Sopenharmony_ci * qla24xx_link_initialization 232162306a36Sopenharmony_ci * Issue link initialization mailbox command. 232262306a36Sopenharmony_ci * 232362306a36Sopenharmony_ci * Input: 232462306a36Sopenharmony_ci * ha = adapter block pointer. 232562306a36Sopenharmony_ci * TARGET_QUEUE_LOCK must be released. 232662306a36Sopenharmony_ci * ADAPTER_STATE_LOCK must be released. 232762306a36Sopenharmony_ci * 232862306a36Sopenharmony_ci * Returns: 232962306a36Sopenharmony_ci * qla2x00 local function return status code. 233062306a36Sopenharmony_ci * 233162306a36Sopenharmony_ci * Context: 233262306a36Sopenharmony_ci * Kernel context. 233362306a36Sopenharmony_ci */ 233462306a36Sopenharmony_ciint 233562306a36Sopenharmony_ciqla24xx_link_initialize(scsi_qla_host_t *vha) 233662306a36Sopenharmony_ci{ 233762306a36Sopenharmony_ci int rval; 233862306a36Sopenharmony_ci mbx_cmd_t mc; 233962306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 234062306a36Sopenharmony_ci 234162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1152, 234262306a36Sopenharmony_ci "Entered %s.\n", __func__); 234362306a36Sopenharmony_ci 234462306a36Sopenharmony_ci if (!IS_FWI2_CAPABLE(vha->hw) || IS_CNA_CAPABLE(vha->hw)) 234562306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 234662306a36Sopenharmony_ci 234762306a36Sopenharmony_ci mcp->mb[0] = MBC_LINK_INITIALIZATION; 234862306a36Sopenharmony_ci mcp->mb[1] = BIT_4; 234962306a36Sopenharmony_ci if (vha->hw->operating_mode == LOOP) 235062306a36Sopenharmony_ci mcp->mb[1] |= BIT_6; 235162306a36Sopenharmony_ci else 235262306a36Sopenharmony_ci mcp->mb[1] |= BIT_5; 235362306a36Sopenharmony_ci mcp->mb[2] = 0; 235462306a36Sopenharmony_ci mcp->mb[3] = 0; 235562306a36Sopenharmony_ci mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; 235662306a36Sopenharmony_ci mcp->in_mb = MBX_0; 235762306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 235862306a36Sopenharmony_ci mcp->flags = 0; 235962306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 236062306a36Sopenharmony_ci 236162306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 236262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1153, "Failed=%x.\n", rval); 236362306a36Sopenharmony_ci } else { 236462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1154, 236562306a36Sopenharmony_ci "Done %s.\n", __func__); 236662306a36Sopenharmony_ci } 236762306a36Sopenharmony_ci 236862306a36Sopenharmony_ci return rval; 236962306a36Sopenharmony_ci} 237062306a36Sopenharmony_ci 237162306a36Sopenharmony_ci/* 237262306a36Sopenharmony_ci * qla2x00_lip_reset 237362306a36Sopenharmony_ci * Issue LIP reset mailbox command. 237462306a36Sopenharmony_ci * 237562306a36Sopenharmony_ci * Input: 237662306a36Sopenharmony_ci * ha = adapter block pointer. 237762306a36Sopenharmony_ci * TARGET_QUEUE_LOCK must be released. 237862306a36Sopenharmony_ci * ADAPTER_STATE_LOCK must be released. 237962306a36Sopenharmony_ci * 238062306a36Sopenharmony_ci * Returns: 238162306a36Sopenharmony_ci * qla2x00 local function return status code. 238262306a36Sopenharmony_ci * 238362306a36Sopenharmony_ci * Context: 238462306a36Sopenharmony_ci * Kernel context. 238562306a36Sopenharmony_ci */ 238662306a36Sopenharmony_ciint 238762306a36Sopenharmony_ciqla2x00_lip_reset(scsi_qla_host_t *vha) 238862306a36Sopenharmony_ci{ 238962306a36Sopenharmony_ci int rval; 239062306a36Sopenharmony_ci mbx_cmd_t mc; 239162306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 239262306a36Sopenharmony_ci 239362306a36Sopenharmony_ci ql_dbg(ql_dbg_disc, vha, 0x105a, 239462306a36Sopenharmony_ci "Entered %s.\n", __func__); 239562306a36Sopenharmony_ci 239662306a36Sopenharmony_ci if (IS_CNA_CAPABLE(vha->hw)) { 239762306a36Sopenharmony_ci /* Logout across all FCFs. */ 239862306a36Sopenharmony_ci mcp->mb[0] = MBC_LIP_FULL_LOGIN; 239962306a36Sopenharmony_ci mcp->mb[1] = BIT_1; 240062306a36Sopenharmony_ci mcp->mb[2] = 0; 240162306a36Sopenharmony_ci mcp->out_mb = MBX_2|MBX_1|MBX_0; 240262306a36Sopenharmony_ci } else if (IS_FWI2_CAPABLE(vha->hw)) { 240362306a36Sopenharmony_ci mcp->mb[0] = MBC_LIP_FULL_LOGIN; 240462306a36Sopenharmony_ci mcp->mb[1] = BIT_4; 240562306a36Sopenharmony_ci mcp->mb[2] = 0; 240662306a36Sopenharmony_ci mcp->mb[3] = vha->hw->loop_reset_delay; 240762306a36Sopenharmony_ci mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; 240862306a36Sopenharmony_ci } else { 240962306a36Sopenharmony_ci mcp->mb[0] = MBC_LIP_RESET; 241062306a36Sopenharmony_ci mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; 241162306a36Sopenharmony_ci if (HAS_EXTENDED_IDS(vha->hw)) { 241262306a36Sopenharmony_ci mcp->mb[1] = 0x00ff; 241362306a36Sopenharmony_ci mcp->mb[10] = 0; 241462306a36Sopenharmony_ci mcp->out_mb |= MBX_10; 241562306a36Sopenharmony_ci } else { 241662306a36Sopenharmony_ci mcp->mb[1] = 0xff00; 241762306a36Sopenharmony_ci } 241862306a36Sopenharmony_ci mcp->mb[2] = vha->hw->loop_reset_delay; 241962306a36Sopenharmony_ci mcp->mb[3] = 0; 242062306a36Sopenharmony_ci } 242162306a36Sopenharmony_ci mcp->in_mb = MBX_0; 242262306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 242362306a36Sopenharmony_ci mcp->flags = 0; 242462306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 242562306a36Sopenharmony_ci 242662306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 242762306a36Sopenharmony_ci /*EMPTY*/ 242862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x105b, "Failed=%x.\n", rval); 242962306a36Sopenharmony_ci } else { 243062306a36Sopenharmony_ci /*EMPTY*/ 243162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105c, 243262306a36Sopenharmony_ci "Done %s.\n", __func__); 243362306a36Sopenharmony_ci } 243462306a36Sopenharmony_ci 243562306a36Sopenharmony_ci return rval; 243662306a36Sopenharmony_ci} 243762306a36Sopenharmony_ci 243862306a36Sopenharmony_ci/* 243962306a36Sopenharmony_ci * qla2x00_send_sns 244062306a36Sopenharmony_ci * Send SNS command. 244162306a36Sopenharmony_ci * 244262306a36Sopenharmony_ci * Input: 244362306a36Sopenharmony_ci * ha = adapter block pointer. 244462306a36Sopenharmony_ci * sns = pointer for command. 244562306a36Sopenharmony_ci * cmd_size = command size. 244662306a36Sopenharmony_ci * buf_size = response/command size. 244762306a36Sopenharmony_ci * TARGET_QUEUE_LOCK must be released. 244862306a36Sopenharmony_ci * ADAPTER_STATE_LOCK must be released. 244962306a36Sopenharmony_ci * 245062306a36Sopenharmony_ci * Returns: 245162306a36Sopenharmony_ci * qla2x00 local function return status code. 245262306a36Sopenharmony_ci * 245362306a36Sopenharmony_ci * Context: 245462306a36Sopenharmony_ci * Kernel context. 245562306a36Sopenharmony_ci */ 245662306a36Sopenharmony_ciint 245762306a36Sopenharmony_ciqla2x00_send_sns(scsi_qla_host_t *vha, dma_addr_t sns_phys_address, 245862306a36Sopenharmony_ci uint16_t cmd_size, size_t buf_size) 245962306a36Sopenharmony_ci{ 246062306a36Sopenharmony_ci int rval; 246162306a36Sopenharmony_ci mbx_cmd_t mc; 246262306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 246362306a36Sopenharmony_ci 246462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105d, 246562306a36Sopenharmony_ci "Entered %s.\n", __func__); 246662306a36Sopenharmony_ci 246762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105e, 246862306a36Sopenharmony_ci "Retry cnt=%d ratov=%d total tov=%d.\n", 246962306a36Sopenharmony_ci vha->hw->retry_count, vha->hw->login_timeout, mcp->tov); 247062306a36Sopenharmony_ci 247162306a36Sopenharmony_ci mcp->mb[0] = MBC_SEND_SNS_COMMAND; 247262306a36Sopenharmony_ci mcp->mb[1] = cmd_size; 247362306a36Sopenharmony_ci mcp->mb[2] = MSW(sns_phys_address); 247462306a36Sopenharmony_ci mcp->mb[3] = LSW(sns_phys_address); 247562306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(sns_phys_address)); 247662306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(sns_phys_address)); 247762306a36Sopenharmony_ci mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; 247862306a36Sopenharmony_ci mcp->in_mb = MBX_0|MBX_1; 247962306a36Sopenharmony_ci mcp->buf_size = buf_size; 248062306a36Sopenharmony_ci mcp->flags = MBX_DMA_OUT|MBX_DMA_IN; 248162306a36Sopenharmony_ci mcp->tov = (vha->hw->login_timeout * 2) + (vha->hw->login_timeout / 2); 248262306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 248362306a36Sopenharmony_ci 248462306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 248562306a36Sopenharmony_ci /*EMPTY*/ 248662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x105f, 248762306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x.\n", 248862306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1]); 248962306a36Sopenharmony_ci } else { 249062306a36Sopenharmony_ci /*EMPTY*/ 249162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1060, 249262306a36Sopenharmony_ci "Done %s.\n", __func__); 249362306a36Sopenharmony_ci } 249462306a36Sopenharmony_ci 249562306a36Sopenharmony_ci return rval; 249662306a36Sopenharmony_ci} 249762306a36Sopenharmony_ci 249862306a36Sopenharmony_ciint 249962306a36Sopenharmony_ciqla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, 250062306a36Sopenharmony_ci uint8_t area, uint8_t al_pa, uint16_t *mb, uint8_t opt) 250162306a36Sopenharmony_ci{ 250262306a36Sopenharmony_ci int rval; 250362306a36Sopenharmony_ci 250462306a36Sopenharmony_ci struct logio_entry_24xx *lg; 250562306a36Sopenharmony_ci dma_addr_t lg_dma; 250662306a36Sopenharmony_ci uint32_t iop[2]; 250762306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 250862306a36Sopenharmony_ci struct req_que *req; 250962306a36Sopenharmony_ci 251062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1061, 251162306a36Sopenharmony_ci "Entered %s.\n", __func__); 251262306a36Sopenharmony_ci 251362306a36Sopenharmony_ci if (vha->vp_idx && vha->qpair) 251462306a36Sopenharmony_ci req = vha->qpair->req; 251562306a36Sopenharmony_ci else 251662306a36Sopenharmony_ci req = ha->req_q_map[0]; 251762306a36Sopenharmony_ci 251862306a36Sopenharmony_ci lg = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma); 251962306a36Sopenharmony_ci if (lg == NULL) { 252062306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1062, 252162306a36Sopenharmony_ci "Failed to allocate login IOCB.\n"); 252262306a36Sopenharmony_ci return QLA_MEMORY_ALLOC_FAILED; 252362306a36Sopenharmony_ci } 252462306a36Sopenharmony_ci 252562306a36Sopenharmony_ci lg->entry_type = LOGINOUT_PORT_IOCB_TYPE; 252662306a36Sopenharmony_ci lg->entry_count = 1; 252762306a36Sopenharmony_ci lg->handle = make_handle(req->id, lg->handle); 252862306a36Sopenharmony_ci lg->nport_handle = cpu_to_le16(loop_id); 252962306a36Sopenharmony_ci lg->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); 253062306a36Sopenharmony_ci if (opt & BIT_0) 253162306a36Sopenharmony_ci lg->control_flags |= cpu_to_le16(LCF_COND_PLOGI); 253262306a36Sopenharmony_ci if (opt & BIT_1) 253362306a36Sopenharmony_ci lg->control_flags |= cpu_to_le16(LCF_SKIP_PRLI); 253462306a36Sopenharmony_ci lg->port_id[0] = al_pa; 253562306a36Sopenharmony_ci lg->port_id[1] = area; 253662306a36Sopenharmony_ci lg->port_id[2] = domain; 253762306a36Sopenharmony_ci lg->vp_index = vha->vp_idx; 253862306a36Sopenharmony_ci rval = qla2x00_issue_iocb_timeout(vha, lg, lg_dma, 0, 253962306a36Sopenharmony_ci (ha->r_a_tov / 10 * 2) + 2); 254062306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 254162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1063, 254262306a36Sopenharmony_ci "Failed to issue login IOCB (%x).\n", rval); 254362306a36Sopenharmony_ci } else if (lg->entry_status != 0) { 254462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1064, 254562306a36Sopenharmony_ci "Failed to complete IOCB -- error status (%x).\n", 254662306a36Sopenharmony_ci lg->entry_status); 254762306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 254862306a36Sopenharmony_ci } else if (lg->comp_status != cpu_to_le16(CS_COMPLETE)) { 254962306a36Sopenharmony_ci iop[0] = le32_to_cpu(lg->io_parameter[0]); 255062306a36Sopenharmony_ci iop[1] = le32_to_cpu(lg->io_parameter[1]); 255162306a36Sopenharmony_ci 255262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1065, 255362306a36Sopenharmony_ci "Failed to complete IOCB -- completion status (%x) " 255462306a36Sopenharmony_ci "ioparam=%x/%x.\n", le16_to_cpu(lg->comp_status), 255562306a36Sopenharmony_ci iop[0], iop[1]); 255662306a36Sopenharmony_ci 255762306a36Sopenharmony_ci switch (iop[0]) { 255862306a36Sopenharmony_ci case LSC_SCODE_PORTID_USED: 255962306a36Sopenharmony_ci mb[0] = MBS_PORT_ID_USED; 256062306a36Sopenharmony_ci mb[1] = LSW(iop[1]); 256162306a36Sopenharmony_ci break; 256262306a36Sopenharmony_ci case LSC_SCODE_NPORT_USED: 256362306a36Sopenharmony_ci mb[0] = MBS_LOOP_ID_USED; 256462306a36Sopenharmony_ci break; 256562306a36Sopenharmony_ci case LSC_SCODE_NOLINK: 256662306a36Sopenharmony_ci case LSC_SCODE_NOIOCB: 256762306a36Sopenharmony_ci case LSC_SCODE_NOXCB: 256862306a36Sopenharmony_ci case LSC_SCODE_CMD_FAILED: 256962306a36Sopenharmony_ci case LSC_SCODE_NOFABRIC: 257062306a36Sopenharmony_ci case LSC_SCODE_FW_NOT_READY: 257162306a36Sopenharmony_ci case LSC_SCODE_NOT_LOGGED_IN: 257262306a36Sopenharmony_ci case LSC_SCODE_NOPCB: 257362306a36Sopenharmony_ci case LSC_SCODE_ELS_REJECT: 257462306a36Sopenharmony_ci case LSC_SCODE_CMD_PARAM_ERR: 257562306a36Sopenharmony_ci case LSC_SCODE_NONPORT: 257662306a36Sopenharmony_ci case LSC_SCODE_LOGGED_IN: 257762306a36Sopenharmony_ci case LSC_SCODE_NOFLOGI_ACC: 257862306a36Sopenharmony_ci default: 257962306a36Sopenharmony_ci mb[0] = MBS_COMMAND_ERROR; 258062306a36Sopenharmony_ci break; 258162306a36Sopenharmony_ci } 258262306a36Sopenharmony_ci } else { 258362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1066, 258462306a36Sopenharmony_ci "Done %s.\n", __func__); 258562306a36Sopenharmony_ci 258662306a36Sopenharmony_ci iop[0] = le32_to_cpu(lg->io_parameter[0]); 258762306a36Sopenharmony_ci 258862306a36Sopenharmony_ci mb[0] = MBS_COMMAND_COMPLETE; 258962306a36Sopenharmony_ci mb[1] = 0; 259062306a36Sopenharmony_ci if (iop[0] & BIT_4) { 259162306a36Sopenharmony_ci if (iop[0] & BIT_8) 259262306a36Sopenharmony_ci mb[1] |= BIT_1; 259362306a36Sopenharmony_ci } else 259462306a36Sopenharmony_ci mb[1] = BIT_0; 259562306a36Sopenharmony_ci 259662306a36Sopenharmony_ci /* Passback COS information. */ 259762306a36Sopenharmony_ci mb[10] = 0; 259862306a36Sopenharmony_ci if (lg->io_parameter[7] || lg->io_parameter[8]) 259962306a36Sopenharmony_ci mb[10] |= BIT_0; /* Class 2. */ 260062306a36Sopenharmony_ci if (lg->io_parameter[9] || lg->io_parameter[10]) 260162306a36Sopenharmony_ci mb[10] |= BIT_1; /* Class 3. */ 260262306a36Sopenharmony_ci if (lg->io_parameter[0] & cpu_to_le32(BIT_7)) 260362306a36Sopenharmony_ci mb[10] |= BIT_7; /* Confirmed Completion 260462306a36Sopenharmony_ci * Allowed 260562306a36Sopenharmony_ci */ 260662306a36Sopenharmony_ci } 260762306a36Sopenharmony_ci 260862306a36Sopenharmony_ci dma_pool_free(ha->s_dma_pool, lg, lg_dma); 260962306a36Sopenharmony_ci 261062306a36Sopenharmony_ci return rval; 261162306a36Sopenharmony_ci} 261262306a36Sopenharmony_ci 261362306a36Sopenharmony_ci/* 261462306a36Sopenharmony_ci * qla2x00_login_fabric 261562306a36Sopenharmony_ci * Issue login fabric port mailbox command. 261662306a36Sopenharmony_ci * 261762306a36Sopenharmony_ci * Input: 261862306a36Sopenharmony_ci * ha = adapter block pointer. 261962306a36Sopenharmony_ci * loop_id = device loop ID. 262062306a36Sopenharmony_ci * domain = device domain. 262162306a36Sopenharmony_ci * area = device area. 262262306a36Sopenharmony_ci * al_pa = device AL_PA. 262362306a36Sopenharmony_ci * status = pointer for return status. 262462306a36Sopenharmony_ci * opt = command options. 262562306a36Sopenharmony_ci * TARGET_QUEUE_LOCK must be released. 262662306a36Sopenharmony_ci * ADAPTER_STATE_LOCK must be released. 262762306a36Sopenharmony_ci * 262862306a36Sopenharmony_ci * Returns: 262962306a36Sopenharmony_ci * qla2x00 local function return status code. 263062306a36Sopenharmony_ci * 263162306a36Sopenharmony_ci * Context: 263262306a36Sopenharmony_ci * Kernel context. 263362306a36Sopenharmony_ci */ 263462306a36Sopenharmony_ciint 263562306a36Sopenharmony_ciqla2x00_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, 263662306a36Sopenharmony_ci uint8_t area, uint8_t al_pa, uint16_t *mb, uint8_t opt) 263762306a36Sopenharmony_ci{ 263862306a36Sopenharmony_ci int rval; 263962306a36Sopenharmony_ci mbx_cmd_t mc; 264062306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 264162306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 264262306a36Sopenharmony_ci 264362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1067, 264462306a36Sopenharmony_ci "Entered %s.\n", __func__); 264562306a36Sopenharmony_ci 264662306a36Sopenharmony_ci mcp->mb[0] = MBC_LOGIN_FABRIC_PORT; 264762306a36Sopenharmony_ci mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; 264862306a36Sopenharmony_ci if (HAS_EXTENDED_IDS(ha)) { 264962306a36Sopenharmony_ci mcp->mb[1] = loop_id; 265062306a36Sopenharmony_ci mcp->mb[10] = opt; 265162306a36Sopenharmony_ci mcp->out_mb |= MBX_10; 265262306a36Sopenharmony_ci } else { 265362306a36Sopenharmony_ci mcp->mb[1] = (loop_id << 8) | opt; 265462306a36Sopenharmony_ci } 265562306a36Sopenharmony_ci mcp->mb[2] = domain; 265662306a36Sopenharmony_ci mcp->mb[3] = area << 8 | al_pa; 265762306a36Sopenharmony_ci 265862306a36Sopenharmony_ci mcp->in_mb = MBX_7|MBX_6|MBX_2|MBX_1|MBX_0; 265962306a36Sopenharmony_ci mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); 266062306a36Sopenharmony_ci mcp->flags = 0; 266162306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 266262306a36Sopenharmony_ci 266362306a36Sopenharmony_ci /* Return mailbox statuses. */ 266462306a36Sopenharmony_ci if (mb != NULL) { 266562306a36Sopenharmony_ci mb[0] = mcp->mb[0]; 266662306a36Sopenharmony_ci mb[1] = mcp->mb[1]; 266762306a36Sopenharmony_ci mb[2] = mcp->mb[2]; 266862306a36Sopenharmony_ci mb[6] = mcp->mb[6]; 266962306a36Sopenharmony_ci mb[7] = mcp->mb[7]; 267062306a36Sopenharmony_ci /* COS retrieved from Get-Port-Database mailbox command. */ 267162306a36Sopenharmony_ci mb[10] = 0; 267262306a36Sopenharmony_ci } 267362306a36Sopenharmony_ci 267462306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 267562306a36Sopenharmony_ci /* RLU tmp code: need to change main mailbox_command function to 267662306a36Sopenharmony_ci * return ok even when the mailbox completion value is not 267762306a36Sopenharmony_ci * SUCCESS. The caller needs to be responsible to interpret 267862306a36Sopenharmony_ci * the return values of this mailbox command if we're not 267962306a36Sopenharmony_ci * to change too much of the existing code. 268062306a36Sopenharmony_ci */ 268162306a36Sopenharmony_ci if (mcp->mb[0] == 0x4001 || mcp->mb[0] == 0x4002 || 268262306a36Sopenharmony_ci mcp->mb[0] == 0x4003 || mcp->mb[0] == 0x4005 || 268362306a36Sopenharmony_ci mcp->mb[0] == 0x4006) 268462306a36Sopenharmony_ci rval = QLA_SUCCESS; 268562306a36Sopenharmony_ci 268662306a36Sopenharmony_ci /*EMPTY*/ 268762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1068, 268862306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n", 268962306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); 269062306a36Sopenharmony_ci } else { 269162306a36Sopenharmony_ci /*EMPTY*/ 269262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1069, 269362306a36Sopenharmony_ci "Done %s.\n", __func__); 269462306a36Sopenharmony_ci } 269562306a36Sopenharmony_ci 269662306a36Sopenharmony_ci return rval; 269762306a36Sopenharmony_ci} 269862306a36Sopenharmony_ci 269962306a36Sopenharmony_ci/* 270062306a36Sopenharmony_ci * qla2x00_login_local_device 270162306a36Sopenharmony_ci * Issue login loop port mailbox command. 270262306a36Sopenharmony_ci * 270362306a36Sopenharmony_ci * Input: 270462306a36Sopenharmony_ci * ha = adapter block pointer. 270562306a36Sopenharmony_ci * loop_id = device loop ID. 270662306a36Sopenharmony_ci * opt = command options. 270762306a36Sopenharmony_ci * 270862306a36Sopenharmony_ci * Returns: 270962306a36Sopenharmony_ci * Return status code. 271062306a36Sopenharmony_ci * 271162306a36Sopenharmony_ci * Context: 271262306a36Sopenharmony_ci * Kernel context. 271362306a36Sopenharmony_ci * 271462306a36Sopenharmony_ci */ 271562306a36Sopenharmony_ciint 271662306a36Sopenharmony_ciqla2x00_login_local_device(scsi_qla_host_t *vha, fc_port_t *fcport, 271762306a36Sopenharmony_ci uint16_t *mb_ret, uint8_t opt) 271862306a36Sopenharmony_ci{ 271962306a36Sopenharmony_ci int rval; 272062306a36Sopenharmony_ci mbx_cmd_t mc; 272162306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 272262306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 272362306a36Sopenharmony_ci 272462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106a, 272562306a36Sopenharmony_ci "Entered %s.\n", __func__); 272662306a36Sopenharmony_ci 272762306a36Sopenharmony_ci if (IS_FWI2_CAPABLE(ha)) 272862306a36Sopenharmony_ci return qla24xx_login_fabric(vha, fcport->loop_id, 272962306a36Sopenharmony_ci fcport->d_id.b.domain, fcport->d_id.b.area, 273062306a36Sopenharmony_ci fcport->d_id.b.al_pa, mb_ret, opt); 273162306a36Sopenharmony_ci 273262306a36Sopenharmony_ci mcp->mb[0] = MBC_LOGIN_LOOP_PORT; 273362306a36Sopenharmony_ci if (HAS_EXTENDED_IDS(ha)) 273462306a36Sopenharmony_ci mcp->mb[1] = fcport->loop_id; 273562306a36Sopenharmony_ci else 273662306a36Sopenharmony_ci mcp->mb[1] = fcport->loop_id << 8; 273762306a36Sopenharmony_ci mcp->mb[2] = opt; 273862306a36Sopenharmony_ci mcp->out_mb = MBX_2|MBX_1|MBX_0; 273962306a36Sopenharmony_ci mcp->in_mb = MBX_7|MBX_6|MBX_1|MBX_0; 274062306a36Sopenharmony_ci mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); 274162306a36Sopenharmony_ci mcp->flags = 0; 274262306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 274362306a36Sopenharmony_ci 274462306a36Sopenharmony_ci /* Return mailbox statuses. */ 274562306a36Sopenharmony_ci if (mb_ret != NULL) { 274662306a36Sopenharmony_ci mb_ret[0] = mcp->mb[0]; 274762306a36Sopenharmony_ci mb_ret[1] = mcp->mb[1]; 274862306a36Sopenharmony_ci mb_ret[6] = mcp->mb[6]; 274962306a36Sopenharmony_ci mb_ret[7] = mcp->mb[7]; 275062306a36Sopenharmony_ci } 275162306a36Sopenharmony_ci 275262306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 275362306a36Sopenharmony_ci /* AV tmp code: need to change main mailbox_command function to 275462306a36Sopenharmony_ci * return ok even when the mailbox completion value is not 275562306a36Sopenharmony_ci * SUCCESS. The caller needs to be responsible to interpret 275662306a36Sopenharmony_ci * the return values of this mailbox command if we're not 275762306a36Sopenharmony_ci * to change too much of the existing code. 275862306a36Sopenharmony_ci */ 275962306a36Sopenharmony_ci if (mcp->mb[0] == 0x4005 || mcp->mb[0] == 0x4006) 276062306a36Sopenharmony_ci rval = QLA_SUCCESS; 276162306a36Sopenharmony_ci 276262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x106b, 276362306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x mb[6]=%x mb[7]=%x.\n", 276462306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]); 276562306a36Sopenharmony_ci } else { 276662306a36Sopenharmony_ci /*EMPTY*/ 276762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106c, 276862306a36Sopenharmony_ci "Done %s.\n", __func__); 276962306a36Sopenharmony_ci } 277062306a36Sopenharmony_ci 277162306a36Sopenharmony_ci return (rval); 277262306a36Sopenharmony_ci} 277362306a36Sopenharmony_ci 277462306a36Sopenharmony_ciint 277562306a36Sopenharmony_ciqla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, 277662306a36Sopenharmony_ci uint8_t area, uint8_t al_pa) 277762306a36Sopenharmony_ci{ 277862306a36Sopenharmony_ci int rval; 277962306a36Sopenharmony_ci struct logio_entry_24xx *lg; 278062306a36Sopenharmony_ci dma_addr_t lg_dma; 278162306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 278262306a36Sopenharmony_ci struct req_que *req; 278362306a36Sopenharmony_ci 278462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106d, 278562306a36Sopenharmony_ci "Entered %s.\n", __func__); 278662306a36Sopenharmony_ci 278762306a36Sopenharmony_ci lg = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma); 278862306a36Sopenharmony_ci if (lg == NULL) { 278962306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x106e, 279062306a36Sopenharmony_ci "Failed to allocate logout IOCB.\n"); 279162306a36Sopenharmony_ci return QLA_MEMORY_ALLOC_FAILED; 279262306a36Sopenharmony_ci } 279362306a36Sopenharmony_ci 279462306a36Sopenharmony_ci req = vha->req; 279562306a36Sopenharmony_ci lg->entry_type = LOGINOUT_PORT_IOCB_TYPE; 279662306a36Sopenharmony_ci lg->entry_count = 1; 279762306a36Sopenharmony_ci lg->handle = make_handle(req->id, lg->handle); 279862306a36Sopenharmony_ci lg->nport_handle = cpu_to_le16(loop_id); 279962306a36Sopenharmony_ci lg->control_flags = 280062306a36Sopenharmony_ci cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO| 280162306a36Sopenharmony_ci LCF_FREE_NPORT); 280262306a36Sopenharmony_ci lg->port_id[0] = al_pa; 280362306a36Sopenharmony_ci lg->port_id[1] = area; 280462306a36Sopenharmony_ci lg->port_id[2] = domain; 280562306a36Sopenharmony_ci lg->vp_index = vha->vp_idx; 280662306a36Sopenharmony_ci rval = qla2x00_issue_iocb_timeout(vha, lg, lg_dma, 0, 280762306a36Sopenharmony_ci (ha->r_a_tov / 10 * 2) + 2); 280862306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 280962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x106f, 281062306a36Sopenharmony_ci "Failed to issue logout IOCB (%x).\n", rval); 281162306a36Sopenharmony_ci } else if (lg->entry_status != 0) { 281262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1070, 281362306a36Sopenharmony_ci "Failed to complete IOCB -- error status (%x).\n", 281462306a36Sopenharmony_ci lg->entry_status); 281562306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 281662306a36Sopenharmony_ci } else if (lg->comp_status != cpu_to_le16(CS_COMPLETE)) { 281762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1071, 281862306a36Sopenharmony_ci "Failed to complete IOCB -- completion status (%x) " 281962306a36Sopenharmony_ci "ioparam=%x/%x.\n", le16_to_cpu(lg->comp_status), 282062306a36Sopenharmony_ci le32_to_cpu(lg->io_parameter[0]), 282162306a36Sopenharmony_ci le32_to_cpu(lg->io_parameter[1])); 282262306a36Sopenharmony_ci } else { 282362306a36Sopenharmony_ci /*EMPTY*/ 282462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1072, 282562306a36Sopenharmony_ci "Done %s.\n", __func__); 282662306a36Sopenharmony_ci } 282762306a36Sopenharmony_ci 282862306a36Sopenharmony_ci dma_pool_free(ha->s_dma_pool, lg, lg_dma); 282962306a36Sopenharmony_ci 283062306a36Sopenharmony_ci return rval; 283162306a36Sopenharmony_ci} 283262306a36Sopenharmony_ci 283362306a36Sopenharmony_ci/* 283462306a36Sopenharmony_ci * qla2x00_fabric_logout 283562306a36Sopenharmony_ci * Issue logout fabric port mailbox command. 283662306a36Sopenharmony_ci * 283762306a36Sopenharmony_ci * Input: 283862306a36Sopenharmony_ci * ha = adapter block pointer. 283962306a36Sopenharmony_ci * loop_id = device loop ID. 284062306a36Sopenharmony_ci * TARGET_QUEUE_LOCK must be released. 284162306a36Sopenharmony_ci * ADAPTER_STATE_LOCK must be released. 284262306a36Sopenharmony_ci * 284362306a36Sopenharmony_ci * Returns: 284462306a36Sopenharmony_ci * qla2x00 local function return status code. 284562306a36Sopenharmony_ci * 284662306a36Sopenharmony_ci * Context: 284762306a36Sopenharmony_ci * Kernel context. 284862306a36Sopenharmony_ci */ 284962306a36Sopenharmony_ciint 285062306a36Sopenharmony_ciqla2x00_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, 285162306a36Sopenharmony_ci uint8_t area, uint8_t al_pa) 285262306a36Sopenharmony_ci{ 285362306a36Sopenharmony_ci int rval; 285462306a36Sopenharmony_ci mbx_cmd_t mc; 285562306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 285662306a36Sopenharmony_ci 285762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1073, 285862306a36Sopenharmony_ci "Entered %s.\n", __func__); 285962306a36Sopenharmony_ci 286062306a36Sopenharmony_ci mcp->mb[0] = MBC_LOGOUT_FABRIC_PORT; 286162306a36Sopenharmony_ci mcp->out_mb = MBX_1|MBX_0; 286262306a36Sopenharmony_ci if (HAS_EXTENDED_IDS(vha->hw)) { 286362306a36Sopenharmony_ci mcp->mb[1] = loop_id; 286462306a36Sopenharmony_ci mcp->mb[10] = 0; 286562306a36Sopenharmony_ci mcp->out_mb |= MBX_10; 286662306a36Sopenharmony_ci } else { 286762306a36Sopenharmony_ci mcp->mb[1] = loop_id << 8; 286862306a36Sopenharmony_ci } 286962306a36Sopenharmony_ci 287062306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 287162306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 287262306a36Sopenharmony_ci mcp->flags = 0; 287362306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 287462306a36Sopenharmony_ci 287562306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 287662306a36Sopenharmony_ci /*EMPTY*/ 287762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1074, 287862306a36Sopenharmony_ci "Failed=%x mb[1]=%x.\n", rval, mcp->mb[1]); 287962306a36Sopenharmony_ci } else { 288062306a36Sopenharmony_ci /*EMPTY*/ 288162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1075, 288262306a36Sopenharmony_ci "Done %s.\n", __func__); 288362306a36Sopenharmony_ci } 288462306a36Sopenharmony_ci 288562306a36Sopenharmony_ci return rval; 288662306a36Sopenharmony_ci} 288762306a36Sopenharmony_ci 288862306a36Sopenharmony_ci/* 288962306a36Sopenharmony_ci * qla2x00_full_login_lip 289062306a36Sopenharmony_ci * Issue full login LIP mailbox command. 289162306a36Sopenharmony_ci * 289262306a36Sopenharmony_ci * Input: 289362306a36Sopenharmony_ci * ha = adapter block pointer. 289462306a36Sopenharmony_ci * TARGET_QUEUE_LOCK must be released. 289562306a36Sopenharmony_ci * ADAPTER_STATE_LOCK must be released. 289662306a36Sopenharmony_ci * 289762306a36Sopenharmony_ci * Returns: 289862306a36Sopenharmony_ci * qla2x00 local function return status code. 289962306a36Sopenharmony_ci * 290062306a36Sopenharmony_ci * Context: 290162306a36Sopenharmony_ci * Kernel context. 290262306a36Sopenharmony_ci */ 290362306a36Sopenharmony_ciint 290462306a36Sopenharmony_ciqla2x00_full_login_lip(scsi_qla_host_t *vha) 290562306a36Sopenharmony_ci{ 290662306a36Sopenharmony_ci int rval; 290762306a36Sopenharmony_ci mbx_cmd_t mc; 290862306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 290962306a36Sopenharmony_ci 291062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1076, 291162306a36Sopenharmony_ci "Entered %s.\n", __func__); 291262306a36Sopenharmony_ci 291362306a36Sopenharmony_ci mcp->mb[0] = MBC_LIP_FULL_LOGIN; 291462306a36Sopenharmony_ci mcp->mb[1] = IS_FWI2_CAPABLE(vha->hw) ? BIT_4 : 0; 291562306a36Sopenharmony_ci mcp->mb[2] = 0; 291662306a36Sopenharmony_ci mcp->mb[3] = 0; 291762306a36Sopenharmony_ci mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; 291862306a36Sopenharmony_ci mcp->in_mb = MBX_0; 291962306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 292062306a36Sopenharmony_ci mcp->flags = 0; 292162306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 292262306a36Sopenharmony_ci 292362306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 292462306a36Sopenharmony_ci /*EMPTY*/ 292562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1077, "Failed=%x.\n", rval); 292662306a36Sopenharmony_ci } else { 292762306a36Sopenharmony_ci /*EMPTY*/ 292862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1078, 292962306a36Sopenharmony_ci "Done %s.\n", __func__); 293062306a36Sopenharmony_ci } 293162306a36Sopenharmony_ci 293262306a36Sopenharmony_ci return rval; 293362306a36Sopenharmony_ci} 293462306a36Sopenharmony_ci 293562306a36Sopenharmony_ci/* 293662306a36Sopenharmony_ci * qla2x00_get_id_list 293762306a36Sopenharmony_ci * 293862306a36Sopenharmony_ci * Input: 293962306a36Sopenharmony_ci * ha = adapter block pointer. 294062306a36Sopenharmony_ci * 294162306a36Sopenharmony_ci * Returns: 294262306a36Sopenharmony_ci * qla2x00 local function return status code. 294362306a36Sopenharmony_ci * 294462306a36Sopenharmony_ci * Context: 294562306a36Sopenharmony_ci * Kernel context. 294662306a36Sopenharmony_ci */ 294762306a36Sopenharmony_ciint 294862306a36Sopenharmony_ciqla2x00_get_id_list(scsi_qla_host_t *vha, void *id_list, dma_addr_t id_list_dma, 294962306a36Sopenharmony_ci uint16_t *entries) 295062306a36Sopenharmony_ci{ 295162306a36Sopenharmony_ci int rval; 295262306a36Sopenharmony_ci mbx_cmd_t mc; 295362306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 295462306a36Sopenharmony_ci 295562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1079, 295662306a36Sopenharmony_ci "Entered %s.\n", __func__); 295762306a36Sopenharmony_ci 295862306a36Sopenharmony_ci if (id_list == NULL) 295962306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 296062306a36Sopenharmony_ci 296162306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_ID_LIST; 296262306a36Sopenharmony_ci mcp->out_mb = MBX_0; 296362306a36Sopenharmony_ci if (IS_FWI2_CAPABLE(vha->hw)) { 296462306a36Sopenharmony_ci mcp->mb[2] = MSW(id_list_dma); 296562306a36Sopenharmony_ci mcp->mb[3] = LSW(id_list_dma); 296662306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(id_list_dma)); 296762306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(id_list_dma)); 296862306a36Sopenharmony_ci mcp->mb[8] = 0; 296962306a36Sopenharmony_ci mcp->mb[9] = vha->vp_idx; 297062306a36Sopenharmony_ci mcp->out_mb |= MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2; 297162306a36Sopenharmony_ci } else { 297262306a36Sopenharmony_ci mcp->mb[1] = MSW(id_list_dma); 297362306a36Sopenharmony_ci mcp->mb[2] = LSW(id_list_dma); 297462306a36Sopenharmony_ci mcp->mb[3] = MSW(MSD(id_list_dma)); 297562306a36Sopenharmony_ci mcp->mb[6] = LSW(MSD(id_list_dma)); 297662306a36Sopenharmony_ci mcp->out_mb |= MBX_6|MBX_3|MBX_2|MBX_1; 297762306a36Sopenharmony_ci } 297862306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 297962306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 298062306a36Sopenharmony_ci mcp->flags = 0; 298162306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 298262306a36Sopenharmony_ci 298362306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 298462306a36Sopenharmony_ci /*EMPTY*/ 298562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x107a, "Failed=%x.\n", rval); 298662306a36Sopenharmony_ci } else { 298762306a36Sopenharmony_ci *entries = mcp->mb[1]; 298862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107b, 298962306a36Sopenharmony_ci "Done %s.\n", __func__); 299062306a36Sopenharmony_ci } 299162306a36Sopenharmony_ci 299262306a36Sopenharmony_ci return rval; 299362306a36Sopenharmony_ci} 299462306a36Sopenharmony_ci 299562306a36Sopenharmony_ci/* 299662306a36Sopenharmony_ci * qla2x00_get_resource_cnts 299762306a36Sopenharmony_ci * Get current firmware resource counts. 299862306a36Sopenharmony_ci * 299962306a36Sopenharmony_ci * Input: 300062306a36Sopenharmony_ci * ha = adapter block pointer. 300162306a36Sopenharmony_ci * 300262306a36Sopenharmony_ci * Returns: 300362306a36Sopenharmony_ci * qla2x00 local function return status code. 300462306a36Sopenharmony_ci * 300562306a36Sopenharmony_ci * Context: 300662306a36Sopenharmony_ci * Kernel context. 300762306a36Sopenharmony_ci */ 300862306a36Sopenharmony_ciint 300962306a36Sopenharmony_ciqla2x00_get_resource_cnts(scsi_qla_host_t *vha) 301062306a36Sopenharmony_ci{ 301162306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 301262306a36Sopenharmony_ci int rval; 301362306a36Sopenharmony_ci mbx_cmd_t mc; 301462306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 301562306a36Sopenharmony_ci 301662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107c, 301762306a36Sopenharmony_ci "Entered %s.\n", __func__); 301862306a36Sopenharmony_ci 301962306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_RESOURCE_COUNTS; 302062306a36Sopenharmony_ci mcp->out_mb = MBX_0; 302162306a36Sopenharmony_ci mcp->in_mb = MBX_11|MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; 302262306a36Sopenharmony_ci if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || 302362306a36Sopenharmony_ci IS_QLA27XX(ha) || IS_QLA28XX(ha)) 302462306a36Sopenharmony_ci mcp->in_mb |= MBX_12; 302562306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 302662306a36Sopenharmony_ci mcp->flags = 0; 302762306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 302862306a36Sopenharmony_ci 302962306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 303062306a36Sopenharmony_ci /*EMPTY*/ 303162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x107d, 303262306a36Sopenharmony_ci "Failed mb[0]=%x.\n", mcp->mb[0]); 303362306a36Sopenharmony_ci } else { 303462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107e, 303562306a36Sopenharmony_ci "Done %s mb1=%x mb2=%x mb3=%x mb6=%x mb7=%x mb10=%x " 303662306a36Sopenharmony_ci "mb11=%x mb12=%x.\n", __func__, mcp->mb[1], mcp->mb[2], 303762306a36Sopenharmony_ci mcp->mb[3], mcp->mb[6], mcp->mb[7], mcp->mb[10], 303862306a36Sopenharmony_ci mcp->mb[11], mcp->mb[12]); 303962306a36Sopenharmony_ci 304062306a36Sopenharmony_ci ha->orig_fw_tgt_xcb_count = mcp->mb[1]; 304162306a36Sopenharmony_ci ha->cur_fw_tgt_xcb_count = mcp->mb[2]; 304262306a36Sopenharmony_ci ha->cur_fw_xcb_count = mcp->mb[3]; 304362306a36Sopenharmony_ci ha->orig_fw_xcb_count = mcp->mb[6]; 304462306a36Sopenharmony_ci ha->cur_fw_iocb_count = mcp->mb[7]; 304562306a36Sopenharmony_ci ha->orig_fw_iocb_count = mcp->mb[10]; 304662306a36Sopenharmony_ci if (ha->flags.npiv_supported) 304762306a36Sopenharmony_ci ha->max_npiv_vports = mcp->mb[11]; 304862306a36Sopenharmony_ci if (IS_QLA81XX(ha) || IS_QLA83XX(ha)) 304962306a36Sopenharmony_ci ha->fw_max_fcf_count = mcp->mb[12]; 305062306a36Sopenharmony_ci } 305162306a36Sopenharmony_ci 305262306a36Sopenharmony_ci return (rval); 305362306a36Sopenharmony_ci} 305462306a36Sopenharmony_ci 305562306a36Sopenharmony_ci/* 305662306a36Sopenharmony_ci * qla2x00_get_fcal_position_map 305762306a36Sopenharmony_ci * Get FCAL (LILP) position map using mailbox command 305862306a36Sopenharmony_ci * 305962306a36Sopenharmony_ci * Input: 306062306a36Sopenharmony_ci * ha = adapter state pointer. 306162306a36Sopenharmony_ci * pos_map = buffer pointer (can be NULL). 306262306a36Sopenharmony_ci * 306362306a36Sopenharmony_ci * Returns: 306462306a36Sopenharmony_ci * qla2x00 local function return status code. 306562306a36Sopenharmony_ci * 306662306a36Sopenharmony_ci * Context: 306762306a36Sopenharmony_ci * Kernel context. 306862306a36Sopenharmony_ci */ 306962306a36Sopenharmony_ciint 307062306a36Sopenharmony_ciqla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map, 307162306a36Sopenharmony_ci u8 *num_entries) 307262306a36Sopenharmony_ci{ 307362306a36Sopenharmony_ci int rval; 307462306a36Sopenharmony_ci mbx_cmd_t mc; 307562306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 307662306a36Sopenharmony_ci char *pmap; 307762306a36Sopenharmony_ci dma_addr_t pmap_dma; 307862306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 307962306a36Sopenharmony_ci 308062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107f, 308162306a36Sopenharmony_ci "Entered %s.\n", __func__); 308262306a36Sopenharmony_ci 308362306a36Sopenharmony_ci pmap = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pmap_dma); 308462306a36Sopenharmony_ci if (pmap == NULL) { 308562306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1080, 308662306a36Sopenharmony_ci "Memory alloc failed.\n"); 308762306a36Sopenharmony_ci return QLA_MEMORY_ALLOC_FAILED; 308862306a36Sopenharmony_ci } 308962306a36Sopenharmony_ci 309062306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_FC_AL_POSITION_MAP; 309162306a36Sopenharmony_ci mcp->mb[2] = MSW(pmap_dma); 309262306a36Sopenharmony_ci mcp->mb[3] = LSW(pmap_dma); 309362306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(pmap_dma)); 309462306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(pmap_dma)); 309562306a36Sopenharmony_ci mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; 309662306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 309762306a36Sopenharmony_ci mcp->buf_size = FCAL_MAP_SIZE; 309862306a36Sopenharmony_ci mcp->flags = MBX_DMA_IN; 309962306a36Sopenharmony_ci mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); 310062306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 310162306a36Sopenharmony_ci 310262306a36Sopenharmony_ci if (rval == QLA_SUCCESS) { 310362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1081, 310462306a36Sopenharmony_ci "mb0/mb1=%x/%X FC/AL position map size (%x).\n", 310562306a36Sopenharmony_ci mcp->mb[0], mcp->mb[1], (unsigned)pmap[0]); 310662306a36Sopenharmony_ci ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111d, 310762306a36Sopenharmony_ci pmap, pmap[0] + 1); 310862306a36Sopenharmony_ci 310962306a36Sopenharmony_ci if (pos_map) 311062306a36Sopenharmony_ci memcpy(pos_map, pmap, FCAL_MAP_SIZE); 311162306a36Sopenharmony_ci if (num_entries) 311262306a36Sopenharmony_ci *num_entries = pmap[0]; 311362306a36Sopenharmony_ci } 311462306a36Sopenharmony_ci dma_pool_free(ha->s_dma_pool, pmap, pmap_dma); 311562306a36Sopenharmony_ci 311662306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 311762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1082, "Failed=%x.\n", rval); 311862306a36Sopenharmony_ci } else { 311962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1083, 312062306a36Sopenharmony_ci "Done %s.\n", __func__); 312162306a36Sopenharmony_ci } 312262306a36Sopenharmony_ci 312362306a36Sopenharmony_ci return rval; 312462306a36Sopenharmony_ci} 312562306a36Sopenharmony_ci 312662306a36Sopenharmony_ci/* 312762306a36Sopenharmony_ci * qla2x00_get_link_status 312862306a36Sopenharmony_ci * 312962306a36Sopenharmony_ci * Input: 313062306a36Sopenharmony_ci * ha = adapter block pointer. 313162306a36Sopenharmony_ci * loop_id = device loop ID. 313262306a36Sopenharmony_ci * ret_buf = pointer to link status return buffer. 313362306a36Sopenharmony_ci * 313462306a36Sopenharmony_ci * Returns: 313562306a36Sopenharmony_ci * 0 = success. 313662306a36Sopenharmony_ci * BIT_0 = mem alloc error. 313762306a36Sopenharmony_ci * BIT_1 = mailbox error. 313862306a36Sopenharmony_ci */ 313962306a36Sopenharmony_ciint 314062306a36Sopenharmony_ciqla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id, 314162306a36Sopenharmony_ci struct link_statistics *stats, dma_addr_t stats_dma) 314262306a36Sopenharmony_ci{ 314362306a36Sopenharmony_ci int rval; 314462306a36Sopenharmony_ci mbx_cmd_t mc; 314562306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 314662306a36Sopenharmony_ci uint32_t *iter = (uint32_t *)stats; 314762306a36Sopenharmony_ci ushort dwords = offsetof(typeof(*stats), link_up_cnt)/sizeof(*iter); 314862306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 314962306a36Sopenharmony_ci 315062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1084, 315162306a36Sopenharmony_ci "Entered %s.\n", __func__); 315262306a36Sopenharmony_ci 315362306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_LINK_STATUS; 315462306a36Sopenharmony_ci mcp->mb[2] = MSW(LSD(stats_dma)); 315562306a36Sopenharmony_ci mcp->mb[3] = LSW(LSD(stats_dma)); 315662306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(stats_dma)); 315762306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(stats_dma)); 315862306a36Sopenharmony_ci mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; 315962306a36Sopenharmony_ci mcp->in_mb = MBX_0; 316062306a36Sopenharmony_ci if (IS_FWI2_CAPABLE(ha)) { 316162306a36Sopenharmony_ci mcp->mb[1] = loop_id; 316262306a36Sopenharmony_ci mcp->mb[4] = 0; 316362306a36Sopenharmony_ci mcp->mb[10] = 0; 316462306a36Sopenharmony_ci mcp->out_mb |= MBX_10|MBX_4|MBX_1; 316562306a36Sopenharmony_ci mcp->in_mb |= MBX_1; 316662306a36Sopenharmony_ci } else if (HAS_EXTENDED_IDS(ha)) { 316762306a36Sopenharmony_ci mcp->mb[1] = loop_id; 316862306a36Sopenharmony_ci mcp->mb[10] = 0; 316962306a36Sopenharmony_ci mcp->out_mb |= MBX_10|MBX_1; 317062306a36Sopenharmony_ci } else { 317162306a36Sopenharmony_ci mcp->mb[1] = loop_id << 8; 317262306a36Sopenharmony_ci mcp->out_mb |= MBX_1; 317362306a36Sopenharmony_ci } 317462306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 317562306a36Sopenharmony_ci mcp->flags = IOCTL_CMD; 317662306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 317762306a36Sopenharmony_ci 317862306a36Sopenharmony_ci if (rval == QLA_SUCCESS) { 317962306a36Sopenharmony_ci if (mcp->mb[0] != MBS_COMMAND_COMPLETE) { 318062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1085, 318162306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 318262306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 318362306a36Sopenharmony_ci } else { 318462306a36Sopenharmony_ci /* Re-endianize - firmware data is le32. */ 318562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1086, 318662306a36Sopenharmony_ci "Done %s.\n", __func__); 318762306a36Sopenharmony_ci for ( ; dwords--; iter++) 318862306a36Sopenharmony_ci le32_to_cpus(iter); 318962306a36Sopenharmony_ci } 319062306a36Sopenharmony_ci } else { 319162306a36Sopenharmony_ci /* Failed. */ 319262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1087, "Failed=%x.\n", rval); 319362306a36Sopenharmony_ci } 319462306a36Sopenharmony_ci 319562306a36Sopenharmony_ci return rval; 319662306a36Sopenharmony_ci} 319762306a36Sopenharmony_ci 319862306a36Sopenharmony_ciint 319962306a36Sopenharmony_ciqla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats, 320062306a36Sopenharmony_ci dma_addr_t stats_dma, uint16_t options) 320162306a36Sopenharmony_ci{ 320262306a36Sopenharmony_ci int rval; 320362306a36Sopenharmony_ci mbx_cmd_t mc; 320462306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 320562306a36Sopenharmony_ci uint32_t *iter = (uint32_t *)stats; 320662306a36Sopenharmony_ci ushort dwords = sizeof(*stats)/sizeof(*iter); 320762306a36Sopenharmony_ci 320862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1088, 320962306a36Sopenharmony_ci "Entered %s.\n", __func__); 321062306a36Sopenharmony_ci 321162306a36Sopenharmony_ci memset(&mc, 0, sizeof(mc)); 321262306a36Sopenharmony_ci mc.mb[0] = MBC_GET_LINK_PRIV_STATS; 321362306a36Sopenharmony_ci mc.mb[2] = MSW(LSD(stats_dma)); 321462306a36Sopenharmony_ci mc.mb[3] = LSW(LSD(stats_dma)); 321562306a36Sopenharmony_ci mc.mb[6] = MSW(MSD(stats_dma)); 321662306a36Sopenharmony_ci mc.mb[7] = LSW(MSD(stats_dma)); 321762306a36Sopenharmony_ci mc.mb[8] = dwords; 321862306a36Sopenharmony_ci mc.mb[9] = vha->vp_idx; 321962306a36Sopenharmony_ci mc.mb[10] = options; 322062306a36Sopenharmony_ci 322162306a36Sopenharmony_ci rval = qla24xx_send_mb_cmd(vha, &mc); 322262306a36Sopenharmony_ci 322362306a36Sopenharmony_ci if (rval == QLA_SUCCESS) { 322462306a36Sopenharmony_ci if (mcp->mb[0] != MBS_COMMAND_COMPLETE) { 322562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1089, 322662306a36Sopenharmony_ci "Failed mb[0]=%x.\n", mcp->mb[0]); 322762306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 322862306a36Sopenharmony_ci } else { 322962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108a, 323062306a36Sopenharmony_ci "Done %s.\n", __func__); 323162306a36Sopenharmony_ci /* Re-endianize - firmware data is le32. */ 323262306a36Sopenharmony_ci for ( ; dwords--; iter++) 323362306a36Sopenharmony_ci le32_to_cpus(iter); 323462306a36Sopenharmony_ci } 323562306a36Sopenharmony_ci } else { 323662306a36Sopenharmony_ci /* Failed. */ 323762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x108b, "Failed=%x.\n", rval); 323862306a36Sopenharmony_ci } 323962306a36Sopenharmony_ci 324062306a36Sopenharmony_ci return rval; 324162306a36Sopenharmony_ci} 324262306a36Sopenharmony_ci 324362306a36Sopenharmony_ciint 324462306a36Sopenharmony_ciqla24xx_abort_command(srb_t *sp) 324562306a36Sopenharmony_ci{ 324662306a36Sopenharmony_ci int rval; 324762306a36Sopenharmony_ci unsigned long flags = 0; 324862306a36Sopenharmony_ci 324962306a36Sopenharmony_ci struct abort_entry_24xx *abt; 325062306a36Sopenharmony_ci dma_addr_t abt_dma; 325162306a36Sopenharmony_ci uint32_t handle; 325262306a36Sopenharmony_ci fc_port_t *fcport = sp->fcport; 325362306a36Sopenharmony_ci struct scsi_qla_host *vha = fcport->vha; 325462306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 325562306a36Sopenharmony_ci struct req_que *req; 325662306a36Sopenharmony_ci struct qla_qpair *qpair = sp->qpair; 325762306a36Sopenharmony_ci 325862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108c, 325962306a36Sopenharmony_ci "Entered %s.\n", __func__); 326062306a36Sopenharmony_ci 326162306a36Sopenharmony_ci if (sp->qpair) 326262306a36Sopenharmony_ci req = sp->qpair->req; 326362306a36Sopenharmony_ci else 326462306a36Sopenharmony_ci return QLA_ERR_NO_QPAIR; 326562306a36Sopenharmony_ci 326662306a36Sopenharmony_ci if (ql2xasynctmfenable) 326762306a36Sopenharmony_ci return qla24xx_async_abort_command(sp); 326862306a36Sopenharmony_ci 326962306a36Sopenharmony_ci spin_lock_irqsave(qpair->qp_lock_ptr, flags); 327062306a36Sopenharmony_ci for (handle = 1; handle < req->num_outstanding_cmds; handle++) { 327162306a36Sopenharmony_ci if (req->outstanding_cmds[handle] == sp) 327262306a36Sopenharmony_ci break; 327362306a36Sopenharmony_ci } 327462306a36Sopenharmony_ci spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); 327562306a36Sopenharmony_ci if (handle == req->num_outstanding_cmds) { 327662306a36Sopenharmony_ci /* Command not found. */ 327762306a36Sopenharmony_ci return QLA_ERR_NOT_FOUND; 327862306a36Sopenharmony_ci } 327962306a36Sopenharmony_ci 328062306a36Sopenharmony_ci abt = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &abt_dma); 328162306a36Sopenharmony_ci if (abt == NULL) { 328262306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x108d, 328362306a36Sopenharmony_ci "Failed to allocate abort IOCB.\n"); 328462306a36Sopenharmony_ci return QLA_MEMORY_ALLOC_FAILED; 328562306a36Sopenharmony_ci } 328662306a36Sopenharmony_ci 328762306a36Sopenharmony_ci abt->entry_type = ABORT_IOCB_TYPE; 328862306a36Sopenharmony_ci abt->entry_count = 1; 328962306a36Sopenharmony_ci abt->handle = make_handle(req->id, abt->handle); 329062306a36Sopenharmony_ci abt->nport_handle = cpu_to_le16(fcport->loop_id); 329162306a36Sopenharmony_ci abt->handle_to_abort = make_handle(req->id, handle); 329262306a36Sopenharmony_ci abt->port_id[0] = fcport->d_id.b.al_pa; 329362306a36Sopenharmony_ci abt->port_id[1] = fcport->d_id.b.area; 329462306a36Sopenharmony_ci abt->port_id[2] = fcport->d_id.b.domain; 329562306a36Sopenharmony_ci abt->vp_index = fcport->vha->vp_idx; 329662306a36Sopenharmony_ci 329762306a36Sopenharmony_ci abt->req_que_no = cpu_to_le16(req->id); 329862306a36Sopenharmony_ci /* Need to pass original sp */ 329962306a36Sopenharmony_ci qla_nvme_abort_set_option(abt, sp); 330062306a36Sopenharmony_ci 330162306a36Sopenharmony_ci rval = qla2x00_issue_iocb(vha, abt, abt_dma, 0); 330262306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 330362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x108e, 330462306a36Sopenharmony_ci "Failed to issue IOCB (%x).\n", rval); 330562306a36Sopenharmony_ci } else if (abt->entry_status != 0) { 330662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x108f, 330762306a36Sopenharmony_ci "Failed to complete IOCB -- error status (%x).\n", 330862306a36Sopenharmony_ci abt->entry_status); 330962306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 331062306a36Sopenharmony_ci } else if (abt->nport_handle != cpu_to_le16(0)) { 331162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1090, 331262306a36Sopenharmony_ci "Failed to complete IOCB -- completion status (%x).\n", 331362306a36Sopenharmony_ci le16_to_cpu(abt->nport_handle)); 331462306a36Sopenharmony_ci if (abt->nport_handle == cpu_to_le16(CS_IOCB_ERROR)) 331562306a36Sopenharmony_ci rval = QLA_FUNCTION_PARAMETER_ERROR; 331662306a36Sopenharmony_ci else 331762306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 331862306a36Sopenharmony_ci } else { 331962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1091, 332062306a36Sopenharmony_ci "Done %s.\n", __func__); 332162306a36Sopenharmony_ci } 332262306a36Sopenharmony_ci if (rval == QLA_SUCCESS) 332362306a36Sopenharmony_ci qla_nvme_abort_process_comp_status(abt, sp); 332462306a36Sopenharmony_ci 332562306a36Sopenharmony_ci qla_wait_nvme_release_cmd_kref(sp); 332662306a36Sopenharmony_ci 332762306a36Sopenharmony_ci dma_pool_free(ha->s_dma_pool, abt, abt_dma); 332862306a36Sopenharmony_ci 332962306a36Sopenharmony_ci return rval; 333062306a36Sopenharmony_ci} 333162306a36Sopenharmony_ci 333262306a36Sopenharmony_cistruct tsk_mgmt_cmd { 333362306a36Sopenharmony_ci union { 333462306a36Sopenharmony_ci struct tsk_mgmt_entry tsk; 333562306a36Sopenharmony_ci struct sts_entry_24xx sts; 333662306a36Sopenharmony_ci } p; 333762306a36Sopenharmony_ci}; 333862306a36Sopenharmony_ci 333962306a36Sopenharmony_cistatic int 334062306a36Sopenharmony_ci__qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, 334162306a36Sopenharmony_ci uint64_t l, int tag) 334262306a36Sopenharmony_ci{ 334362306a36Sopenharmony_ci int rval, rval2; 334462306a36Sopenharmony_ci struct tsk_mgmt_cmd *tsk; 334562306a36Sopenharmony_ci struct sts_entry_24xx *sts; 334662306a36Sopenharmony_ci dma_addr_t tsk_dma; 334762306a36Sopenharmony_ci scsi_qla_host_t *vha; 334862306a36Sopenharmony_ci struct qla_hw_data *ha; 334962306a36Sopenharmony_ci struct req_que *req; 335062306a36Sopenharmony_ci struct qla_qpair *qpair; 335162306a36Sopenharmony_ci 335262306a36Sopenharmony_ci vha = fcport->vha; 335362306a36Sopenharmony_ci ha = vha->hw; 335462306a36Sopenharmony_ci req = vha->req; 335562306a36Sopenharmony_ci 335662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1092, 335762306a36Sopenharmony_ci "Entered %s.\n", __func__); 335862306a36Sopenharmony_ci 335962306a36Sopenharmony_ci if (vha->vp_idx && vha->qpair) { 336062306a36Sopenharmony_ci /* NPIV port */ 336162306a36Sopenharmony_ci qpair = vha->qpair; 336262306a36Sopenharmony_ci req = qpair->req; 336362306a36Sopenharmony_ci } 336462306a36Sopenharmony_ci 336562306a36Sopenharmony_ci tsk = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma); 336662306a36Sopenharmony_ci if (tsk == NULL) { 336762306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1093, 336862306a36Sopenharmony_ci "Failed to allocate task management IOCB.\n"); 336962306a36Sopenharmony_ci return QLA_MEMORY_ALLOC_FAILED; 337062306a36Sopenharmony_ci } 337162306a36Sopenharmony_ci 337262306a36Sopenharmony_ci tsk->p.tsk.entry_type = TSK_MGMT_IOCB_TYPE; 337362306a36Sopenharmony_ci tsk->p.tsk.entry_count = 1; 337462306a36Sopenharmony_ci tsk->p.tsk.handle = make_handle(req->id, tsk->p.tsk.handle); 337562306a36Sopenharmony_ci tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id); 337662306a36Sopenharmony_ci tsk->p.tsk.timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); 337762306a36Sopenharmony_ci tsk->p.tsk.control_flags = cpu_to_le32(type); 337862306a36Sopenharmony_ci tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa; 337962306a36Sopenharmony_ci tsk->p.tsk.port_id[1] = fcport->d_id.b.area; 338062306a36Sopenharmony_ci tsk->p.tsk.port_id[2] = fcport->d_id.b.domain; 338162306a36Sopenharmony_ci tsk->p.tsk.vp_index = fcport->vha->vp_idx; 338262306a36Sopenharmony_ci if (type == TCF_LUN_RESET) { 338362306a36Sopenharmony_ci int_to_scsilun(l, &tsk->p.tsk.lun); 338462306a36Sopenharmony_ci host_to_fcp_swap((uint8_t *)&tsk->p.tsk.lun, 338562306a36Sopenharmony_ci sizeof(tsk->p.tsk.lun)); 338662306a36Sopenharmony_ci } 338762306a36Sopenharmony_ci 338862306a36Sopenharmony_ci sts = &tsk->p.sts; 338962306a36Sopenharmony_ci rval = qla2x00_issue_iocb(vha, tsk, tsk_dma, 0); 339062306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 339162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1094, 339262306a36Sopenharmony_ci "Failed to issue %s reset IOCB (%x).\n", name, rval); 339362306a36Sopenharmony_ci } else if (sts->entry_status != 0) { 339462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1095, 339562306a36Sopenharmony_ci "Failed to complete IOCB -- error status (%x).\n", 339662306a36Sopenharmony_ci sts->entry_status); 339762306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 339862306a36Sopenharmony_ci } else if (sts->comp_status != cpu_to_le16(CS_COMPLETE)) { 339962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1096, 340062306a36Sopenharmony_ci "Failed to complete IOCB -- completion status (%x).\n", 340162306a36Sopenharmony_ci le16_to_cpu(sts->comp_status)); 340262306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 340362306a36Sopenharmony_ci } else if (le16_to_cpu(sts->scsi_status) & 340462306a36Sopenharmony_ci SS_RESPONSE_INFO_LEN_VALID) { 340562306a36Sopenharmony_ci if (le32_to_cpu(sts->rsp_data_len) < 4) { 340662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1097, 340762306a36Sopenharmony_ci "Ignoring inconsistent data length -- not enough " 340862306a36Sopenharmony_ci "response info (%d).\n", 340962306a36Sopenharmony_ci le32_to_cpu(sts->rsp_data_len)); 341062306a36Sopenharmony_ci } else if (sts->data[3]) { 341162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1098, 341262306a36Sopenharmony_ci "Failed to complete IOCB -- response (%x).\n", 341362306a36Sopenharmony_ci sts->data[3]); 341462306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 341562306a36Sopenharmony_ci } 341662306a36Sopenharmony_ci } 341762306a36Sopenharmony_ci 341862306a36Sopenharmony_ci /* Issue marker IOCB. */ 341962306a36Sopenharmony_ci rval2 = qla2x00_marker(vha, ha->base_qpair, fcport->loop_id, l, 342062306a36Sopenharmony_ci type == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID); 342162306a36Sopenharmony_ci if (rval2 != QLA_SUCCESS) { 342262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1099, 342362306a36Sopenharmony_ci "Failed to issue marker IOCB (%x).\n", rval2); 342462306a36Sopenharmony_ci } else { 342562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109a, 342662306a36Sopenharmony_ci "Done %s.\n", __func__); 342762306a36Sopenharmony_ci } 342862306a36Sopenharmony_ci 342962306a36Sopenharmony_ci dma_pool_free(ha->s_dma_pool, tsk, tsk_dma); 343062306a36Sopenharmony_ci 343162306a36Sopenharmony_ci return rval; 343262306a36Sopenharmony_ci} 343362306a36Sopenharmony_ci 343462306a36Sopenharmony_ciint 343562306a36Sopenharmony_ciqla24xx_abort_target(struct fc_port *fcport, uint64_t l, int tag) 343662306a36Sopenharmony_ci{ 343762306a36Sopenharmony_ci struct qla_hw_data *ha = fcport->vha->hw; 343862306a36Sopenharmony_ci 343962306a36Sopenharmony_ci if ((ql2xasynctmfenable) && IS_FWI2_CAPABLE(ha)) 344062306a36Sopenharmony_ci return qla2x00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag); 344162306a36Sopenharmony_ci 344262306a36Sopenharmony_ci return __qla24xx_issue_tmf("Target", TCF_TARGET_RESET, fcport, l, tag); 344362306a36Sopenharmony_ci} 344462306a36Sopenharmony_ci 344562306a36Sopenharmony_ciint 344662306a36Sopenharmony_ciqla24xx_lun_reset(struct fc_port *fcport, uint64_t l, int tag) 344762306a36Sopenharmony_ci{ 344862306a36Sopenharmony_ci struct qla_hw_data *ha = fcport->vha->hw; 344962306a36Sopenharmony_ci 345062306a36Sopenharmony_ci if ((ql2xasynctmfenable) && IS_FWI2_CAPABLE(ha)) 345162306a36Sopenharmony_ci return qla2x00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag); 345262306a36Sopenharmony_ci 345362306a36Sopenharmony_ci return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l, tag); 345462306a36Sopenharmony_ci} 345562306a36Sopenharmony_ci 345662306a36Sopenharmony_ciint 345762306a36Sopenharmony_ciqla2x00_system_error(scsi_qla_host_t *vha) 345862306a36Sopenharmony_ci{ 345962306a36Sopenharmony_ci int rval; 346062306a36Sopenharmony_ci mbx_cmd_t mc; 346162306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 346262306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 346362306a36Sopenharmony_ci 346462306a36Sopenharmony_ci if (!IS_QLA23XX(ha) && !IS_FWI2_CAPABLE(ha)) 346562306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 346662306a36Sopenharmony_ci 346762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109b, 346862306a36Sopenharmony_ci "Entered %s.\n", __func__); 346962306a36Sopenharmony_ci 347062306a36Sopenharmony_ci mcp->mb[0] = MBC_GEN_SYSTEM_ERROR; 347162306a36Sopenharmony_ci mcp->out_mb = MBX_0; 347262306a36Sopenharmony_ci mcp->in_mb = MBX_0; 347362306a36Sopenharmony_ci mcp->tov = 5; 347462306a36Sopenharmony_ci mcp->flags = 0; 347562306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 347662306a36Sopenharmony_ci 347762306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 347862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x109c, "Failed=%x.\n", rval); 347962306a36Sopenharmony_ci } else { 348062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109d, 348162306a36Sopenharmony_ci "Done %s.\n", __func__); 348262306a36Sopenharmony_ci } 348362306a36Sopenharmony_ci 348462306a36Sopenharmony_ci return rval; 348562306a36Sopenharmony_ci} 348662306a36Sopenharmony_ci 348762306a36Sopenharmony_ciint 348862306a36Sopenharmony_ciqla2x00_write_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t data) 348962306a36Sopenharmony_ci{ 349062306a36Sopenharmony_ci int rval; 349162306a36Sopenharmony_ci mbx_cmd_t mc; 349262306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 349362306a36Sopenharmony_ci 349462306a36Sopenharmony_ci if (!IS_QLA25XX(vha->hw) && !IS_QLA2031(vha->hw) && 349562306a36Sopenharmony_ci !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw)) 349662306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 349762306a36Sopenharmony_ci 349862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1182, 349962306a36Sopenharmony_ci "Entered %s.\n", __func__); 350062306a36Sopenharmony_ci 350162306a36Sopenharmony_ci mcp->mb[0] = MBC_WRITE_SERDES; 350262306a36Sopenharmony_ci mcp->mb[1] = addr; 350362306a36Sopenharmony_ci if (IS_QLA2031(vha->hw)) 350462306a36Sopenharmony_ci mcp->mb[2] = data & 0xff; 350562306a36Sopenharmony_ci else 350662306a36Sopenharmony_ci mcp->mb[2] = data; 350762306a36Sopenharmony_ci 350862306a36Sopenharmony_ci mcp->mb[3] = 0; 350962306a36Sopenharmony_ci mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; 351062306a36Sopenharmony_ci mcp->in_mb = MBX_0; 351162306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 351262306a36Sopenharmony_ci mcp->flags = 0; 351362306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 351462306a36Sopenharmony_ci 351562306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 351662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1183, 351762306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 351862306a36Sopenharmony_ci } else { 351962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1184, 352062306a36Sopenharmony_ci "Done %s.\n", __func__); 352162306a36Sopenharmony_ci } 352262306a36Sopenharmony_ci 352362306a36Sopenharmony_ci return rval; 352462306a36Sopenharmony_ci} 352562306a36Sopenharmony_ci 352662306a36Sopenharmony_ciint 352762306a36Sopenharmony_ciqla2x00_read_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t *data) 352862306a36Sopenharmony_ci{ 352962306a36Sopenharmony_ci int rval; 353062306a36Sopenharmony_ci mbx_cmd_t mc; 353162306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 353262306a36Sopenharmony_ci 353362306a36Sopenharmony_ci if (!IS_QLA25XX(vha->hw) && !IS_QLA2031(vha->hw) && 353462306a36Sopenharmony_ci !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw)) 353562306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 353662306a36Sopenharmony_ci 353762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1185, 353862306a36Sopenharmony_ci "Entered %s.\n", __func__); 353962306a36Sopenharmony_ci 354062306a36Sopenharmony_ci mcp->mb[0] = MBC_READ_SERDES; 354162306a36Sopenharmony_ci mcp->mb[1] = addr; 354262306a36Sopenharmony_ci mcp->mb[3] = 0; 354362306a36Sopenharmony_ci mcp->out_mb = MBX_3|MBX_1|MBX_0; 354462306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 354562306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 354662306a36Sopenharmony_ci mcp->flags = 0; 354762306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 354862306a36Sopenharmony_ci 354962306a36Sopenharmony_ci if (IS_QLA2031(vha->hw)) 355062306a36Sopenharmony_ci *data = mcp->mb[1] & 0xff; 355162306a36Sopenharmony_ci else 355262306a36Sopenharmony_ci *data = mcp->mb[1]; 355362306a36Sopenharmony_ci 355462306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 355562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1186, 355662306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 355762306a36Sopenharmony_ci } else { 355862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1187, 355962306a36Sopenharmony_ci "Done %s.\n", __func__); 356062306a36Sopenharmony_ci } 356162306a36Sopenharmony_ci 356262306a36Sopenharmony_ci return rval; 356362306a36Sopenharmony_ci} 356462306a36Sopenharmony_ci 356562306a36Sopenharmony_ciint 356662306a36Sopenharmony_ciqla8044_write_serdes_word(scsi_qla_host_t *vha, uint32_t addr, uint32_t data) 356762306a36Sopenharmony_ci{ 356862306a36Sopenharmony_ci int rval; 356962306a36Sopenharmony_ci mbx_cmd_t mc; 357062306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 357162306a36Sopenharmony_ci 357262306a36Sopenharmony_ci if (!IS_QLA8044(vha->hw)) 357362306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 357462306a36Sopenharmony_ci 357562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x11a0, 357662306a36Sopenharmony_ci "Entered %s.\n", __func__); 357762306a36Sopenharmony_ci 357862306a36Sopenharmony_ci mcp->mb[0] = MBC_SET_GET_ETH_SERDES_REG; 357962306a36Sopenharmony_ci mcp->mb[1] = HCS_WRITE_SERDES; 358062306a36Sopenharmony_ci mcp->mb[3] = LSW(addr); 358162306a36Sopenharmony_ci mcp->mb[4] = MSW(addr); 358262306a36Sopenharmony_ci mcp->mb[5] = LSW(data); 358362306a36Sopenharmony_ci mcp->mb[6] = MSW(data); 358462306a36Sopenharmony_ci mcp->out_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_1|MBX_0; 358562306a36Sopenharmony_ci mcp->in_mb = MBX_0; 358662306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 358762306a36Sopenharmony_ci mcp->flags = 0; 358862306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 358962306a36Sopenharmony_ci 359062306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 359162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x11a1, 359262306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 359362306a36Sopenharmony_ci } else { 359462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1188, 359562306a36Sopenharmony_ci "Done %s.\n", __func__); 359662306a36Sopenharmony_ci } 359762306a36Sopenharmony_ci 359862306a36Sopenharmony_ci return rval; 359962306a36Sopenharmony_ci} 360062306a36Sopenharmony_ci 360162306a36Sopenharmony_ciint 360262306a36Sopenharmony_ciqla8044_read_serdes_word(scsi_qla_host_t *vha, uint32_t addr, uint32_t *data) 360362306a36Sopenharmony_ci{ 360462306a36Sopenharmony_ci int rval; 360562306a36Sopenharmony_ci mbx_cmd_t mc; 360662306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 360762306a36Sopenharmony_ci 360862306a36Sopenharmony_ci if (!IS_QLA8044(vha->hw)) 360962306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 361062306a36Sopenharmony_ci 361162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1189, 361262306a36Sopenharmony_ci "Entered %s.\n", __func__); 361362306a36Sopenharmony_ci 361462306a36Sopenharmony_ci mcp->mb[0] = MBC_SET_GET_ETH_SERDES_REG; 361562306a36Sopenharmony_ci mcp->mb[1] = HCS_READ_SERDES; 361662306a36Sopenharmony_ci mcp->mb[3] = LSW(addr); 361762306a36Sopenharmony_ci mcp->mb[4] = MSW(addr); 361862306a36Sopenharmony_ci mcp->out_mb = MBX_4|MBX_3|MBX_1|MBX_0; 361962306a36Sopenharmony_ci mcp->in_mb = MBX_2|MBX_1|MBX_0; 362062306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 362162306a36Sopenharmony_ci mcp->flags = 0; 362262306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 362362306a36Sopenharmony_ci 362462306a36Sopenharmony_ci *data = mcp->mb[2] << 16 | mcp->mb[1]; 362562306a36Sopenharmony_ci 362662306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 362762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x118a, 362862306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 362962306a36Sopenharmony_ci } else { 363062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118b, 363162306a36Sopenharmony_ci "Done %s.\n", __func__); 363262306a36Sopenharmony_ci } 363362306a36Sopenharmony_ci 363462306a36Sopenharmony_ci return rval; 363562306a36Sopenharmony_ci} 363662306a36Sopenharmony_ci 363762306a36Sopenharmony_ci/** 363862306a36Sopenharmony_ci * qla2x00_set_serdes_params() - 363962306a36Sopenharmony_ci * @vha: HA context 364062306a36Sopenharmony_ci * @sw_em_1g: serial link options 364162306a36Sopenharmony_ci * @sw_em_2g: serial link options 364262306a36Sopenharmony_ci * @sw_em_4g: serial link options 364362306a36Sopenharmony_ci * 364462306a36Sopenharmony_ci * Returns 364562306a36Sopenharmony_ci */ 364662306a36Sopenharmony_ciint 364762306a36Sopenharmony_ciqla2x00_set_serdes_params(scsi_qla_host_t *vha, uint16_t sw_em_1g, 364862306a36Sopenharmony_ci uint16_t sw_em_2g, uint16_t sw_em_4g) 364962306a36Sopenharmony_ci{ 365062306a36Sopenharmony_ci int rval; 365162306a36Sopenharmony_ci mbx_cmd_t mc; 365262306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 365362306a36Sopenharmony_ci 365462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109e, 365562306a36Sopenharmony_ci "Entered %s.\n", __func__); 365662306a36Sopenharmony_ci 365762306a36Sopenharmony_ci mcp->mb[0] = MBC_SERDES_PARAMS; 365862306a36Sopenharmony_ci mcp->mb[1] = BIT_0; 365962306a36Sopenharmony_ci mcp->mb[2] = sw_em_1g | BIT_15; 366062306a36Sopenharmony_ci mcp->mb[3] = sw_em_2g | BIT_15; 366162306a36Sopenharmony_ci mcp->mb[4] = sw_em_4g | BIT_15; 366262306a36Sopenharmony_ci mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 366362306a36Sopenharmony_ci mcp->in_mb = MBX_0; 366462306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 366562306a36Sopenharmony_ci mcp->flags = 0; 366662306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 366762306a36Sopenharmony_ci 366862306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 366962306a36Sopenharmony_ci /*EMPTY*/ 367062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x109f, 367162306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 367262306a36Sopenharmony_ci } else { 367362306a36Sopenharmony_ci /*EMPTY*/ 367462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a0, 367562306a36Sopenharmony_ci "Done %s.\n", __func__); 367662306a36Sopenharmony_ci } 367762306a36Sopenharmony_ci 367862306a36Sopenharmony_ci return rval; 367962306a36Sopenharmony_ci} 368062306a36Sopenharmony_ci 368162306a36Sopenharmony_ciint 368262306a36Sopenharmony_ciqla2x00_stop_firmware(scsi_qla_host_t *vha) 368362306a36Sopenharmony_ci{ 368462306a36Sopenharmony_ci int rval; 368562306a36Sopenharmony_ci mbx_cmd_t mc; 368662306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 368762306a36Sopenharmony_ci 368862306a36Sopenharmony_ci if (!IS_FWI2_CAPABLE(vha->hw)) 368962306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 369062306a36Sopenharmony_ci 369162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a1, 369262306a36Sopenharmony_ci "Entered %s.\n", __func__); 369362306a36Sopenharmony_ci 369462306a36Sopenharmony_ci mcp->mb[0] = MBC_STOP_FIRMWARE; 369562306a36Sopenharmony_ci mcp->mb[1] = 0; 369662306a36Sopenharmony_ci mcp->out_mb = MBX_1|MBX_0; 369762306a36Sopenharmony_ci mcp->in_mb = MBX_0; 369862306a36Sopenharmony_ci mcp->tov = 5; 369962306a36Sopenharmony_ci mcp->flags = 0; 370062306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 370162306a36Sopenharmony_ci 370262306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 370362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10a2, "Failed=%x.\n", rval); 370462306a36Sopenharmony_ci if (mcp->mb[0] == MBS_INVALID_COMMAND) 370562306a36Sopenharmony_ci rval = QLA_INVALID_COMMAND; 370662306a36Sopenharmony_ci } else { 370762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a3, 370862306a36Sopenharmony_ci "Done %s.\n", __func__); 370962306a36Sopenharmony_ci } 371062306a36Sopenharmony_ci 371162306a36Sopenharmony_ci return rval; 371262306a36Sopenharmony_ci} 371362306a36Sopenharmony_ci 371462306a36Sopenharmony_ciint 371562306a36Sopenharmony_ciqla2x00_enable_eft_trace(scsi_qla_host_t *vha, dma_addr_t eft_dma, 371662306a36Sopenharmony_ci uint16_t buffers) 371762306a36Sopenharmony_ci{ 371862306a36Sopenharmony_ci int rval; 371962306a36Sopenharmony_ci mbx_cmd_t mc; 372062306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 372162306a36Sopenharmony_ci 372262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a4, 372362306a36Sopenharmony_ci "Entered %s.\n", __func__); 372462306a36Sopenharmony_ci 372562306a36Sopenharmony_ci if (!IS_FWI2_CAPABLE(vha->hw)) 372662306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 372762306a36Sopenharmony_ci 372862306a36Sopenharmony_ci if (unlikely(pci_channel_offline(vha->hw->pdev))) 372962306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 373062306a36Sopenharmony_ci 373162306a36Sopenharmony_ci mcp->mb[0] = MBC_TRACE_CONTROL; 373262306a36Sopenharmony_ci mcp->mb[1] = TC_EFT_ENABLE; 373362306a36Sopenharmony_ci mcp->mb[2] = LSW(eft_dma); 373462306a36Sopenharmony_ci mcp->mb[3] = MSW(eft_dma); 373562306a36Sopenharmony_ci mcp->mb[4] = LSW(MSD(eft_dma)); 373662306a36Sopenharmony_ci mcp->mb[5] = MSW(MSD(eft_dma)); 373762306a36Sopenharmony_ci mcp->mb[6] = buffers; 373862306a36Sopenharmony_ci mcp->mb[7] = TC_AEN_DISABLE; 373962306a36Sopenharmony_ci mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 374062306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 374162306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 374262306a36Sopenharmony_ci mcp->flags = 0; 374362306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 374462306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 374562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10a5, 374662306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x.\n", 374762306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1]); 374862306a36Sopenharmony_ci } else { 374962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a6, 375062306a36Sopenharmony_ci "Done %s.\n", __func__); 375162306a36Sopenharmony_ci } 375262306a36Sopenharmony_ci 375362306a36Sopenharmony_ci return rval; 375462306a36Sopenharmony_ci} 375562306a36Sopenharmony_ci 375662306a36Sopenharmony_ciint 375762306a36Sopenharmony_ciqla2x00_disable_eft_trace(scsi_qla_host_t *vha) 375862306a36Sopenharmony_ci{ 375962306a36Sopenharmony_ci int rval; 376062306a36Sopenharmony_ci mbx_cmd_t mc; 376162306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 376262306a36Sopenharmony_ci 376362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a7, 376462306a36Sopenharmony_ci "Entered %s.\n", __func__); 376562306a36Sopenharmony_ci 376662306a36Sopenharmony_ci if (!IS_FWI2_CAPABLE(vha->hw)) 376762306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 376862306a36Sopenharmony_ci 376962306a36Sopenharmony_ci if (unlikely(pci_channel_offline(vha->hw->pdev))) 377062306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 377162306a36Sopenharmony_ci 377262306a36Sopenharmony_ci mcp->mb[0] = MBC_TRACE_CONTROL; 377362306a36Sopenharmony_ci mcp->mb[1] = TC_EFT_DISABLE; 377462306a36Sopenharmony_ci mcp->out_mb = MBX_1|MBX_0; 377562306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 377662306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 377762306a36Sopenharmony_ci mcp->flags = 0; 377862306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 377962306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 378062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10a8, 378162306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x.\n", 378262306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1]); 378362306a36Sopenharmony_ci } else { 378462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a9, 378562306a36Sopenharmony_ci "Done %s.\n", __func__); 378662306a36Sopenharmony_ci } 378762306a36Sopenharmony_ci 378862306a36Sopenharmony_ci return rval; 378962306a36Sopenharmony_ci} 379062306a36Sopenharmony_ci 379162306a36Sopenharmony_ciint 379262306a36Sopenharmony_ciqla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma, 379362306a36Sopenharmony_ci uint16_t buffers, uint16_t *mb, uint32_t *dwords) 379462306a36Sopenharmony_ci{ 379562306a36Sopenharmony_ci int rval; 379662306a36Sopenharmony_ci mbx_cmd_t mc; 379762306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 379862306a36Sopenharmony_ci 379962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10aa, 380062306a36Sopenharmony_ci "Entered %s.\n", __func__); 380162306a36Sopenharmony_ci 380262306a36Sopenharmony_ci if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw) && 380362306a36Sopenharmony_ci !IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) && 380462306a36Sopenharmony_ci !IS_QLA28XX(vha->hw)) 380562306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 380662306a36Sopenharmony_ci 380762306a36Sopenharmony_ci if (unlikely(pci_channel_offline(vha->hw->pdev))) 380862306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 380962306a36Sopenharmony_ci 381062306a36Sopenharmony_ci mcp->mb[0] = MBC_TRACE_CONTROL; 381162306a36Sopenharmony_ci mcp->mb[1] = TC_FCE_ENABLE; 381262306a36Sopenharmony_ci mcp->mb[2] = LSW(fce_dma); 381362306a36Sopenharmony_ci mcp->mb[3] = MSW(fce_dma); 381462306a36Sopenharmony_ci mcp->mb[4] = LSW(MSD(fce_dma)); 381562306a36Sopenharmony_ci mcp->mb[5] = MSW(MSD(fce_dma)); 381662306a36Sopenharmony_ci mcp->mb[6] = buffers; 381762306a36Sopenharmony_ci mcp->mb[7] = TC_AEN_DISABLE; 381862306a36Sopenharmony_ci mcp->mb[8] = 0; 381962306a36Sopenharmony_ci mcp->mb[9] = TC_FCE_DEFAULT_RX_SIZE; 382062306a36Sopenharmony_ci mcp->mb[10] = TC_FCE_DEFAULT_TX_SIZE; 382162306a36Sopenharmony_ci mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2| 382262306a36Sopenharmony_ci MBX_1|MBX_0; 382362306a36Sopenharmony_ci mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 382462306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 382562306a36Sopenharmony_ci mcp->flags = 0; 382662306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 382762306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 382862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10ab, 382962306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x.\n", 383062306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1]); 383162306a36Sopenharmony_ci } else { 383262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ac, 383362306a36Sopenharmony_ci "Done %s.\n", __func__); 383462306a36Sopenharmony_ci 383562306a36Sopenharmony_ci if (mb) 383662306a36Sopenharmony_ci memcpy(mb, mcp->mb, 8 * sizeof(*mb)); 383762306a36Sopenharmony_ci if (dwords) 383862306a36Sopenharmony_ci *dwords = buffers; 383962306a36Sopenharmony_ci } 384062306a36Sopenharmony_ci 384162306a36Sopenharmony_ci return rval; 384262306a36Sopenharmony_ci} 384362306a36Sopenharmony_ci 384462306a36Sopenharmony_ciint 384562306a36Sopenharmony_ciqla2x00_disable_fce_trace(scsi_qla_host_t *vha, uint64_t *wr, uint64_t *rd) 384662306a36Sopenharmony_ci{ 384762306a36Sopenharmony_ci int rval; 384862306a36Sopenharmony_ci mbx_cmd_t mc; 384962306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 385062306a36Sopenharmony_ci 385162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ad, 385262306a36Sopenharmony_ci "Entered %s.\n", __func__); 385362306a36Sopenharmony_ci 385462306a36Sopenharmony_ci if (!IS_FWI2_CAPABLE(vha->hw)) 385562306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 385662306a36Sopenharmony_ci 385762306a36Sopenharmony_ci if (unlikely(pci_channel_offline(vha->hw->pdev))) 385862306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 385962306a36Sopenharmony_ci 386062306a36Sopenharmony_ci mcp->mb[0] = MBC_TRACE_CONTROL; 386162306a36Sopenharmony_ci mcp->mb[1] = TC_FCE_DISABLE; 386262306a36Sopenharmony_ci mcp->mb[2] = TC_FCE_DISABLE_TRACE; 386362306a36Sopenharmony_ci mcp->out_mb = MBX_2|MBX_1|MBX_0; 386462306a36Sopenharmony_ci mcp->in_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2| 386562306a36Sopenharmony_ci MBX_1|MBX_0; 386662306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 386762306a36Sopenharmony_ci mcp->flags = 0; 386862306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 386962306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 387062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10ae, 387162306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x.\n", 387262306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1]); 387362306a36Sopenharmony_ci } else { 387462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10af, 387562306a36Sopenharmony_ci "Done %s.\n", __func__); 387662306a36Sopenharmony_ci 387762306a36Sopenharmony_ci if (wr) 387862306a36Sopenharmony_ci *wr = (uint64_t) mcp->mb[5] << 48 | 387962306a36Sopenharmony_ci (uint64_t) mcp->mb[4] << 32 | 388062306a36Sopenharmony_ci (uint64_t) mcp->mb[3] << 16 | 388162306a36Sopenharmony_ci (uint64_t) mcp->mb[2]; 388262306a36Sopenharmony_ci if (rd) 388362306a36Sopenharmony_ci *rd = (uint64_t) mcp->mb[9] << 48 | 388462306a36Sopenharmony_ci (uint64_t) mcp->mb[8] << 32 | 388562306a36Sopenharmony_ci (uint64_t) mcp->mb[7] << 16 | 388662306a36Sopenharmony_ci (uint64_t) mcp->mb[6]; 388762306a36Sopenharmony_ci } 388862306a36Sopenharmony_ci 388962306a36Sopenharmony_ci return rval; 389062306a36Sopenharmony_ci} 389162306a36Sopenharmony_ci 389262306a36Sopenharmony_ciint 389362306a36Sopenharmony_ciqla2x00_get_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, 389462306a36Sopenharmony_ci uint16_t *port_speed, uint16_t *mb) 389562306a36Sopenharmony_ci{ 389662306a36Sopenharmony_ci int rval; 389762306a36Sopenharmony_ci mbx_cmd_t mc; 389862306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 389962306a36Sopenharmony_ci 390062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b0, 390162306a36Sopenharmony_ci "Entered %s.\n", __func__); 390262306a36Sopenharmony_ci 390362306a36Sopenharmony_ci if (!IS_IIDMA_CAPABLE(vha->hw)) 390462306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 390562306a36Sopenharmony_ci 390662306a36Sopenharmony_ci mcp->mb[0] = MBC_PORT_PARAMS; 390762306a36Sopenharmony_ci mcp->mb[1] = loop_id; 390862306a36Sopenharmony_ci mcp->mb[2] = mcp->mb[3] = 0; 390962306a36Sopenharmony_ci mcp->mb[9] = vha->vp_idx; 391062306a36Sopenharmony_ci mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0; 391162306a36Sopenharmony_ci mcp->in_mb = MBX_3|MBX_1|MBX_0; 391262306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 391362306a36Sopenharmony_ci mcp->flags = 0; 391462306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 391562306a36Sopenharmony_ci 391662306a36Sopenharmony_ci /* Return mailbox statuses. */ 391762306a36Sopenharmony_ci if (mb) { 391862306a36Sopenharmony_ci mb[0] = mcp->mb[0]; 391962306a36Sopenharmony_ci mb[1] = mcp->mb[1]; 392062306a36Sopenharmony_ci mb[3] = mcp->mb[3]; 392162306a36Sopenharmony_ci } 392262306a36Sopenharmony_ci 392362306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 392462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10b1, "Failed=%x.\n", rval); 392562306a36Sopenharmony_ci } else { 392662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b2, 392762306a36Sopenharmony_ci "Done %s.\n", __func__); 392862306a36Sopenharmony_ci if (port_speed) 392962306a36Sopenharmony_ci *port_speed = mcp->mb[3]; 393062306a36Sopenharmony_ci } 393162306a36Sopenharmony_ci 393262306a36Sopenharmony_ci return rval; 393362306a36Sopenharmony_ci} 393462306a36Sopenharmony_ci 393562306a36Sopenharmony_ciint 393662306a36Sopenharmony_ciqla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, 393762306a36Sopenharmony_ci uint16_t port_speed, uint16_t *mb) 393862306a36Sopenharmony_ci{ 393962306a36Sopenharmony_ci int rval; 394062306a36Sopenharmony_ci mbx_cmd_t mc; 394162306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 394262306a36Sopenharmony_ci 394362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b3, 394462306a36Sopenharmony_ci "Entered %s.\n", __func__); 394562306a36Sopenharmony_ci 394662306a36Sopenharmony_ci if (!IS_IIDMA_CAPABLE(vha->hw)) 394762306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 394862306a36Sopenharmony_ci 394962306a36Sopenharmony_ci mcp->mb[0] = MBC_PORT_PARAMS; 395062306a36Sopenharmony_ci mcp->mb[1] = loop_id; 395162306a36Sopenharmony_ci mcp->mb[2] = BIT_0; 395262306a36Sopenharmony_ci mcp->mb[3] = port_speed & 0x3F; 395362306a36Sopenharmony_ci mcp->mb[9] = vha->vp_idx; 395462306a36Sopenharmony_ci mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0; 395562306a36Sopenharmony_ci mcp->in_mb = MBX_3|MBX_1|MBX_0; 395662306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 395762306a36Sopenharmony_ci mcp->flags = 0; 395862306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 395962306a36Sopenharmony_ci 396062306a36Sopenharmony_ci /* Return mailbox statuses. */ 396162306a36Sopenharmony_ci if (mb) { 396262306a36Sopenharmony_ci mb[0] = mcp->mb[0]; 396362306a36Sopenharmony_ci mb[1] = mcp->mb[1]; 396462306a36Sopenharmony_ci mb[3] = mcp->mb[3]; 396562306a36Sopenharmony_ci } 396662306a36Sopenharmony_ci 396762306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 396862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10b4, 396962306a36Sopenharmony_ci "Failed=%x.\n", rval); 397062306a36Sopenharmony_ci } else { 397162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b5, 397262306a36Sopenharmony_ci "Done %s.\n", __func__); 397362306a36Sopenharmony_ci } 397462306a36Sopenharmony_ci 397562306a36Sopenharmony_ci return rval; 397662306a36Sopenharmony_ci} 397762306a36Sopenharmony_ci 397862306a36Sopenharmony_civoid 397962306a36Sopenharmony_ciqla24xx_report_id_acquisition(scsi_qla_host_t *vha, 398062306a36Sopenharmony_ci struct vp_rpt_id_entry_24xx *rptid_entry) 398162306a36Sopenharmony_ci{ 398262306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 398362306a36Sopenharmony_ci scsi_qla_host_t *vp = NULL; 398462306a36Sopenharmony_ci unsigned long flags; 398562306a36Sopenharmony_ci int found; 398662306a36Sopenharmony_ci port_id_t id; 398762306a36Sopenharmony_ci struct fc_port *fcport; 398862306a36Sopenharmony_ci 398962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b6, 399062306a36Sopenharmony_ci "Entered %s.\n", __func__); 399162306a36Sopenharmony_ci 399262306a36Sopenharmony_ci if (rptid_entry->entry_status != 0) 399362306a36Sopenharmony_ci return; 399462306a36Sopenharmony_ci 399562306a36Sopenharmony_ci id.b.domain = rptid_entry->port_id[2]; 399662306a36Sopenharmony_ci id.b.area = rptid_entry->port_id[1]; 399762306a36Sopenharmony_ci id.b.al_pa = rptid_entry->port_id[0]; 399862306a36Sopenharmony_ci id.b.rsvd_1 = 0; 399962306a36Sopenharmony_ci ha->flags.n2n_ae = 0; 400062306a36Sopenharmony_ci 400162306a36Sopenharmony_ci if (rptid_entry->format == 0) { 400262306a36Sopenharmony_ci /* loop */ 400362306a36Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x10b7, 400462306a36Sopenharmony_ci "Format 0 : Number of VPs setup %d, number of " 400562306a36Sopenharmony_ci "VPs acquired %d.\n", rptid_entry->vp_setup, 400662306a36Sopenharmony_ci rptid_entry->vp_acquired); 400762306a36Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x10b8, 400862306a36Sopenharmony_ci "Primary port id %02x%02x%02x.\n", 400962306a36Sopenharmony_ci rptid_entry->port_id[2], rptid_entry->port_id[1], 401062306a36Sopenharmony_ci rptid_entry->port_id[0]); 401162306a36Sopenharmony_ci ha->current_topology = ISP_CFG_NL; 401262306a36Sopenharmony_ci qla_update_host_map(vha, id); 401362306a36Sopenharmony_ci 401462306a36Sopenharmony_ci } else if (rptid_entry->format == 1) { 401562306a36Sopenharmony_ci /* fabric */ 401662306a36Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x10b9, 401762306a36Sopenharmony_ci "Format 1: VP[%d] enabled - status %d - with " 401862306a36Sopenharmony_ci "port id %02x%02x%02x.\n", rptid_entry->vp_idx, 401962306a36Sopenharmony_ci rptid_entry->vp_status, 402062306a36Sopenharmony_ci rptid_entry->port_id[2], rptid_entry->port_id[1], 402162306a36Sopenharmony_ci rptid_entry->port_id[0]); 402262306a36Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x5075, 402362306a36Sopenharmony_ci "Format 1: Remote WWPN %8phC.\n", 402462306a36Sopenharmony_ci rptid_entry->u.f1.port_name); 402562306a36Sopenharmony_ci 402662306a36Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x5075, 402762306a36Sopenharmony_ci "Format 1: WWPN %8phC.\n", 402862306a36Sopenharmony_ci vha->port_name); 402962306a36Sopenharmony_ci 403062306a36Sopenharmony_ci switch (rptid_entry->u.f1.flags & TOPO_MASK) { 403162306a36Sopenharmony_ci case TOPO_N2N: 403262306a36Sopenharmony_ci ha->current_topology = ISP_CFG_N; 403362306a36Sopenharmony_ci spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); 403462306a36Sopenharmony_ci list_for_each_entry(fcport, &vha->vp_fcports, list) { 403562306a36Sopenharmony_ci fcport->scan_state = QLA_FCPORT_SCAN; 403662306a36Sopenharmony_ci fcport->n2n_flag = 0; 403762306a36Sopenharmony_ci } 403862306a36Sopenharmony_ci id.b24 = 0; 403962306a36Sopenharmony_ci if (wwn_to_u64(vha->port_name) > 404062306a36Sopenharmony_ci wwn_to_u64(rptid_entry->u.f1.port_name)) { 404162306a36Sopenharmony_ci vha->d_id.b24 = 0; 404262306a36Sopenharmony_ci vha->d_id.b.al_pa = 1; 404362306a36Sopenharmony_ci ha->flags.n2n_bigger = 1; 404462306a36Sopenharmony_ci 404562306a36Sopenharmony_ci id.b.al_pa = 2; 404662306a36Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x5075, 404762306a36Sopenharmony_ci "Format 1: assign local id %x remote id %x\n", 404862306a36Sopenharmony_ci vha->d_id.b24, id.b24); 404962306a36Sopenharmony_ci } else { 405062306a36Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x5075, 405162306a36Sopenharmony_ci "Format 1: Remote login - Waiting for WWPN %8phC.\n", 405262306a36Sopenharmony_ci rptid_entry->u.f1.port_name); 405362306a36Sopenharmony_ci ha->flags.n2n_bigger = 0; 405462306a36Sopenharmony_ci } 405562306a36Sopenharmony_ci 405662306a36Sopenharmony_ci fcport = qla2x00_find_fcport_by_wwpn(vha, 405762306a36Sopenharmony_ci rptid_entry->u.f1.port_name, 1); 405862306a36Sopenharmony_ci spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); 405962306a36Sopenharmony_ci 406062306a36Sopenharmony_ci 406162306a36Sopenharmony_ci if (fcport) { 406262306a36Sopenharmony_ci fcport->plogi_nack_done_deadline = jiffies + HZ; 406362306a36Sopenharmony_ci fcport->dm_login_expire = jiffies + 406462306a36Sopenharmony_ci QLA_N2N_WAIT_TIME * HZ; 406562306a36Sopenharmony_ci fcport->scan_state = QLA_FCPORT_FOUND; 406662306a36Sopenharmony_ci fcport->n2n_flag = 1; 406762306a36Sopenharmony_ci fcport->keep_nport_handle = 1; 406862306a36Sopenharmony_ci fcport->login_retry = vha->hw->login_retry_count; 406962306a36Sopenharmony_ci fcport->fc4_type = FS_FC4TYPE_FCP; 407062306a36Sopenharmony_ci if (vha->flags.nvme_enabled) 407162306a36Sopenharmony_ci fcport->fc4_type |= FS_FC4TYPE_NVME; 407262306a36Sopenharmony_ci 407362306a36Sopenharmony_ci if (wwn_to_u64(vha->port_name) > 407462306a36Sopenharmony_ci wwn_to_u64(fcport->port_name)) { 407562306a36Sopenharmony_ci fcport->d_id = id; 407662306a36Sopenharmony_ci } 407762306a36Sopenharmony_ci 407862306a36Sopenharmony_ci switch (fcport->disc_state) { 407962306a36Sopenharmony_ci case DSC_DELETED: 408062306a36Sopenharmony_ci set_bit(RELOGIN_NEEDED, 408162306a36Sopenharmony_ci &vha->dpc_flags); 408262306a36Sopenharmony_ci break; 408362306a36Sopenharmony_ci case DSC_DELETE_PEND: 408462306a36Sopenharmony_ci break; 408562306a36Sopenharmony_ci default: 408662306a36Sopenharmony_ci qlt_schedule_sess_for_deletion(fcport); 408762306a36Sopenharmony_ci break; 408862306a36Sopenharmony_ci } 408962306a36Sopenharmony_ci } else { 409062306a36Sopenharmony_ci qla24xx_post_newsess_work(vha, &id, 409162306a36Sopenharmony_ci rptid_entry->u.f1.port_name, 409262306a36Sopenharmony_ci rptid_entry->u.f1.node_name, 409362306a36Sopenharmony_ci NULL, 409462306a36Sopenharmony_ci FS_FCP_IS_N2N); 409562306a36Sopenharmony_ci } 409662306a36Sopenharmony_ci 409762306a36Sopenharmony_ci /* if our portname is higher then initiate N2N login */ 409862306a36Sopenharmony_ci 409962306a36Sopenharmony_ci set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags); 410062306a36Sopenharmony_ci return; 410162306a36Sopenharmony_ci case TOPO_FL: 410262306a36Sopenharmony_ci ha->current_topology = ISP_CFG_FL; 410362306a36Sopenharmony_ci break; 410462306a36Sopenharmony_ci case TOPO_F: 410562306a36Sopenharmony_ci ha->current_topology = ISP_CFG_F; 410662306a36Sopenharmony_ci break; 410762306a36Sopenharmony_ci default: 410862306a36Sopenharmony_ci break; 410962306a36Sopenharmony_ci } 411062306a36Sopenharmony_ci 411162306a36Sopenharmony_ci ha->flags.gpsc_supported = 1; 411262306a36Sopenharmony_ci ha->current_topology = ISP_CFG_F; 411362306a36Sopenharmony_ci /* buffer to buffer credit flag */ 411462306a36Sopenharmony_ci vha->flags.bbcr_enable = (rptid_entry->u.f1.bbcr & 0xf) != 0; 411562306a36Sopenharmony_ci 411662306a36Sopenharmony_ci if (rptid_entry->vp_idx == 0) { 411762306a36Sopenharmony_ci if (rptid_entry->vp_status == VP_STAT_COMPL) { 411862306a36Sopenharmony_ci /* FA-WWN is only for physical port */ 411962306a36Sopenharmony_ci if (qla_ini_mode_enabled(vha) && 412062306a36Sopenharmony_ci ha->flags.fawwpn_enabled && 412162306a36Sopenharmony_ci (rptid_entry->u.f1.flags & 412262306a36Sopenharmony_ci BIT_6)) { 412362306a36Sopenharmony_ci memcpy(vha->port_name, 412462306a36Sopenharmony_ci rptid_entry->u.f1.port_name, 412562306a36Sopenharmony_ci WWN_SIZE); 412662306a36Sopenharmony_ci } 412762306a36Sopenharmony_ci 412862306a36Sopenharmony_ci qla_update_host_map(vha, id); 412962306a36Sopenharmony_ci } 413062306a36Sopenharmony_ci 413162306a36Sopenharmony_ci set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags); 413262306a36Sopenharmony_ci set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags); 413362306a36Sopenharmony_ci } else { 413462306a36Sopenharmony_ci if (rptid_entry->vp_status != VP_STAT_COMPL && 413562306a36Sopenharmony_ci rptid_entry->vp_status != VP_STAT_ID_CHG) { 413662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10ba, 413762306a36Sopenharmony_ci "Could not acquire ID for VP[%d].\n", 413862306a36Sopenharmony_ci rptid_entry->vp_idx); 413962306a36Sopenharmony_ci return; 414062306a36Sopenharmony_ci } 414162306a36Sopenharmony_ci 414262306a36Sopenharmony_ci found = 0; 414362306a36Sopenharmony_ci spin_lock_irqsave(&ha->vport_slock, flags); 414462306a36Sopenharmony_ci list_for_each_entry(vp, &ha->vp_list, list) { 414562306a36Sopenharmony_ci if (rptid_entry->vp_idx == vp->vp_idx) { 414662306a36Sopenharmony_ci found = 1; 414762306a36Sopenharmony_ci break; 414862306a36Sopenharmony_ci } 414962306a36Sopenharmony_ci } 415062306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->vport_slock, flags); 415162306a36Sopenharmony_ci 415262306a36Sopenharmony_ci if (!found) 415362306a36Sopenharmony_ci return; 415462306a36Sopenharmony_ci 415562306a36Sopenharmony_ci qla_update_host_map(vp, id); 415662306a36Sopenharmony_ci 415762306a36Sopenharmony_ci /* 415862306a36Sopenharmony_ci * Cannot configure here as we are still sitting on the 415962306a36Sopenharmony_ci * response queue. Handle it in dpc context. 416062306a36Sopenharmony_ci */ 416162306a36Sopenharmony_ci set_bit(VP_IDX_ACQUIRED, &vp->vp_flags); 416262306a36Sopenharmony_ci set_bit(REGISTER_FC4_NEEDED, &vp->dpc_flags); 416362306a36Sopenharmony_ci set_bit(REGISTER_FDMI_NEEDED, &vp->dpc_flags); 416462306a36Sopenharmony_ci } 416562306a36Sopenharmony_ci set_bit(VP_DPC_NEEDED, &vha->dpc_flags); 416662306a36Sopenharmony_ci qla2xxx_wake_dpc(vha); 416762306a36Sopenharmony_ci } else if (rptid_entry->format == 2) { 416862306a36Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x505f, 416962306a36Sopenharmony_ci "RIDA: format 2/N2N Primary port id %02x%02x%02x.\n", 417062306a36Sopenharmony_ci rptid_entry->port_id[2], rptid_entry->port_id[1], 417162306a36Sopenharmony_ci rptid_entry->port_id[0]); 417262306a36Sopenharmony_ci 417362306a36Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x5075, 417462306a36Sopenharmony_ci "N2N: Remote WWPN %8phC.\n", 417562306a36Sopenharmony_ci rptid_entry->u.f2.port_name); 417662306a36Sopenharmony_ci 417762306a36Sopenharmony_ci /* N2N. direct connect */ 417862306a36Sopenharmony_ci ha->current_topology = ISP_CFG_N; 417962306a36Sopenharmony_ci ha->flags.rida_fmt2 = 1; 418062306a36Sopenharmony_ci vha->d_id.b.domain = rptid_entry->port_id[2]; 418162306a36Sopenharmony_ci vha->d_id.b.area = rptid_entry->port_id[1]; 418262306a36Sopenharmony_ci vha->d_id.b.al_pa = rptid_entry->port_id[0]; 418362306a36Sopenharmony_ci 418462306a36Sopenharmony_ci ha->flags.n2n_ae = 1; 418562306a36Sopenharmony_ci spin_lock_irqsave(&ha->vport_slock, flags); 418662306a36Sopenharmony_ci qla_update_vp_map(vha, SET_AL_PA); 418762306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->vport_slock, flags); 418862306a36Sopenharmony_ci 418962306a36Sopenharmony_ci list_for_each_entry(fcport, &vha->vp_fcports, list) { 419062306a36Sopenharmony_ci fcport->scan_state = QLA_FCPORT_SCAN; 419162306a36Sopenharmony_ci fcport->n2n_flag = 0; 419262306a36Sopenharmony_ci } 419362306a36Sopenharmony_ci 419462306a36Sopenharmony_ci fcport = qla2x00_find_fcport_by_wwpn(vha, 419562306a36Sopenharmony_ci rptid_entry->u.f2.port_name, 1); 419662306a36Sopenharmony_ci 419762306a36Sopenharmony_ci if (fcport) { 419862306a36Sopenharmony_ci fcport->login_retry = vha->hw->login_retry_count; 419962306a36Sopenharmony_ci fcport->plogi_nack_done_deadline = jiffies + HZ; 420062306a36Sopenharmony_ci fcport->scan_state = QLA_FCPORT_FOUND; 420162306a36Sopenharmony_ci fcport->keep_nport_handle = 1; 420262306a36Sopenharmony_ci fcport->n2n_flag = 1; 420362306a36Sopenharmony_ci fcport->d_id.b.domain = 420462306a36Sopenharmony_ci rptid_entry->u.f2.remote_nport_id[2]; 420562306a36Sopenharmony_ci fcport->d_id.b.area = 420662306a36Sopenharmony_ci rptid_entry->u.f2.remote_nport_id[1]; 420762306a36Sopenharmony_ci fcport->d_id.b.al_pa = 420862306a36Sopenharmony_ci rptid_entry->u.f2.remote_nport_id[0]; 420962306a36Sopenharmony_ci 421062306a36Sopenharmony_ci /* 421162306a36Sopenharmony_ci * For the case where remote port sending PRLO, FW 421262306a36Sopenharmony_ci * sends up RIDA Format 2 as an indication of session 421362306a36Sopenharmony_ci * loss. In other word, FW state change from PRLI 421462306a36Sopenharmony_ci * complete back to PLOGI complete. Delete the 421562306a36Sopenharmony_ci * session and let relogin drive the reconnect. 421662306a36Sopenharmony_ci */ 421762306a36Sopenharmony_ci if (atomic_read(&fcport->state) == FCS_ONLINE) 421862306a36Sopenharmony_ci qlt_schedule_sess_for_deletion(fcport); 421962306a36Sopenharmony_ci } 422062306a36Sopenharmony_ci } 422162306a36Sopenharmony_ci} 422262306a36Sopenharmony_ci 422362306a36Sopenharmony_ci/* 422462306a36Sopenharmony_ci * qla24xx_modify_vp_config 422562306a36Sopenharmony_ci * Change VP configuration for vha 422662306a36Sopenharmony_ci * 422762306a36Sopenharmony_ci * Input: 422862306a36Sopenharmony_ci * vha = adapter block pointer. 422962306a36Sopenharmony_ci * 423062306a36Sopenharmony_ci * Returns: 423162306a36Sopenharmony_ci * qla2xxx local function return status code. 423262306a36Sopenharmony_ci * 423362306a36Sopenharmony_ci * Context: 423462306a36Sopenharmony_ci * Kernel context. 423562306a36Sopenharmony_ci */ 423662306a36Sopenharmony_ciint 423762306a36Sopenharmony_ciqla24xx_modify_vp_config(scsi_qla_host_t *vha) 423862306a36Sopenharmony_ci{ 423962306a36Sopenharmony_ci int rval; 424062306a36Sopenharmony_ci struct vp_config_entry_24xx *vpmod; 424162306a36Sopenharmony_ci dma_addr_t vpmod_dma; 424262306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 424362306a36Sopenharmony_ci struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); 424462306a36Sopenharmony_ci 424562306a36Sopenharmony_ci /* This can be called by the parent */ 424662306a36Sopenharmony_ci 424762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10bb, 424862306a36Sopenharmony_ci "Entered %s.\n", __func__); 424962306a36Sopenharmony_ci 425062306a36Sopenharmony_ci vpmod = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &vpmod_dma); 425162306a36Sopenharmony_ci if (!vpmod) { 425262306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x10bc, 425362306a36Sopenharmony_ci "Failed to allocate modify VP IOCB.\n"); 425462306a36Sopenharmony_ci return QLA_MEMORY_ALLOC_FAILED; 425562306a36Sopenharmony_ci } 425662306a36Sopenharmony_ci 425762306a36Sopenharmony_ci vpmod->entry_type = VP_CONFIG_IOCB_TYPE; 425862306a36Sopenharmony_ci vpmod->entry_count = 1; 425962306a36Sopenharmony_ci vpmod->command = VCT_COMMAND_MOD_ENABLE_VPS; 426062306a36Sopenharmony_ci vpmod->vp_count = 1; 426162306a36Sopenharmony_ci vpmod->vp_index1 = vha->vp_idx; 426262306a36Sopenharmony_ci vpmod->options_idx1 = BIT_3|BIT_4|BIT_5; 426362306a36Sopenharmony_ci 426462306a36Sopenharmony_ci qlt_modify_vp_config(vha, vpmod); 426562306a36Sopenharmony_ci 426662306a36Sopenharmony_ci memcpy(vpmod->node_name_idx1, vha->node_name, WWN_SIZE); 426762306a36Sopenharmony_ci memcpy(vpmod->port_name_idx1, vha->port_name, WWN_SIZE); 426862306a36Sopenharmony_ci vpmod->entry_count = 1; 426962306a36Sopenharmony_ci 427062306a36Sopenharmony_ci rval = qla2x00_issue_iocb(base_vha, vpmod, vpmod_dma, 0); 427162306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 427262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10bd, 427362306a36Sopenharmony_ci "Failed to issue VP config IOCB (%x).\n", rval); 427462306a36Sopenharmony_ci } else if (vpmod->comp_status != 0) { 427562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10be, 427662306a36Sopenharmony_ci "Failed to complete IOCB -- error status (%x).\n", 427762306a36Sopenharmony_ci vpmod->comp_status); 427862306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 427962306a36Sopenharmony_ci } else if (vpmod->comp_status != cpu_to_le16(CS_COMPLETE)) { 428062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10bf, 428162306a36Sopenharmony_ci "Failed to complete IOCB -- completion status (%x).\n", 428262306a36Sopenharmony_ci le16_to_cpu(vpmod->comp_status)); 428362306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 428462306a36Sopenharmony_ci } else { 428562306a36Sopenharmony_ci /* EMPTY */ 428662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c0, 428762306a36Sopenharmony_ci "Done %s.\n", __func__); 428862306a36Sopenharmony_ci fc_vport_set_state(vha->fc_vport, FC_VPORT_INITIALIZING); 428962306a36Sopenharmony_ci } 429062306a36Sopenharmony_ci dma_pool_free(ha->s_dma_pool, vpmod, vpmod_dma); 429162306a36Sopenharmony_ci 429262306a36Sopenharmony_ci return rval; 429362306a36Sopenharmony_ci} 429462306a36Sopenharmony_ci 429562306a36Sopenharmony_ci/* 429662306a36Sopenharmony_ci * qla2x00_send_change_request 429762306a36Sopenharmony_ci * Receive or disable RSCN request from fabric controller 429862306a36Sopenharmony_ci * 429962306a36Sopenharmony_ci * Input: 430062306a36Sopenharmony_ci * ha = adapter block pointer 430162306a36Sopenharmony_ci * format = registration format: 430262306a36Sopenharmony_ci * 0 - Reserved 430362306a36Sopenharmony_ci * 1 - Fabric detected registration 430462306a36Sopenharmony_ci * 2 - N_port detected registration 430562306a36Sopenharmony_ci * 3 - Full registration 430662306a36Sopenharmony_ci * FF - clear registration 430762306a36Sopenharmony_ci * vp_idx = Virtual port index 430862306a36Sopenharmony_ci * 430962306a36Sopenharmony_ci * Returns: 431062306a36Sopenharmony_ci * qla2x00 local function return status code. 431162306a36Sopenharmony_ci * 431262306a36Sopenharmony_ci * Context: 431362306a36Sopenharmony_ci * Kernel Context 431462306a36Sopenharmony_ci */ 431562306a36Sopenharmony_ci 431662306a36Sopenharmony_ciint 431762306a36Sopenharmony_ciqla2x00_send_change_request(scsi_qla_host_t *vha, uint16_t format, 431862306a36Sopenharmony_ci uint16_t vp_idx) 431962306a36Sopenharmony_ci{ 432062306a36Sopenharmony_ci int rval; 432162306a36Sopenharmony_ci mbx_cmd_t mc; 432262306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 432362306a36Sopenharmony_ci 432462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c7, 432562306a36Sopenharmony_ci "Entered %s.\n", __func__); 432662306a36Sopenharmony_ci 432762306a36Sopenharmony_ci mcp->mb[0] = MBC_SEND_CHANGE_REQUEST; 432862306a36Sopenharmony_ci mcp->mb[1] = format; 432962306a36Sopenharmony_ci mcp->mb[9] = vp_idx; 433062306a36Sopenharmony_ci mcp->out_mb = MBX_9|MBX_1|MBX_0; 433162306a36Sopenharmony_ci mcp->in_mb = MBX_0|MBX_1; 433262306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 433362306a36Sopenharmony_ci mcp->flags = 0; 433462306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 433562306a36Sopenharmony_ci 433662306a36Sopenharmony_ci if (rval == QLA_SUCCESS) { 433762306a36Sopenharmony_ci if (mcp->mb[0] != MBS_COMMAND_COMPLETE) { 433862306a36Sopenharmony_ci rval = BIT_1; 433962306a36Sopenharmony_ci } 434062306a36Sopenharmony_ci } else 434162306a36Sopenharmony_ci rval = BIT_1; 434262306a36Sopenharmony_ci 434362306a36Sopenharmony_ci return rval; 434462306a36Sopenharmony_ci} 434562306a36Sopenharmony_ci 434662306a36Sopenharmony_ciint 434762306a36Sopenharmony_ciqla2x00_dump_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr, 434862306a36Sopenharmony_ci uint32_t size) 434962306a36Sopenharmony_ci{ 435062306a36Sopenharmony_ci int rval; 435162306a36Sopenharmony_ci mbx_cmd_t mc; 435262306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 435362306a36Sopenharmony_ci 435462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1009, 435562306a36Sopenharmony_ci "Entered %s.\n", __func__); 435662306a36Sopenharmony_ci 435762306a36Sopenharmony_ci if (MSW(addr) || IS_FWI2_CAPABLE(vha->hw)) { 435862306a36Sopenharmony_ci mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED; 435962306a36Sopenharmony_ci mcp->mb[8] = MSW(addr); 436062306a36Sopenharmony_ci mcp->mb[10] = 0; 436162306a36Sopenharmony_ci mcp->out_mb = MBX_10|MBX_8|MBX_0; 436262306a36Sopenharmony_ci } else { 436362306a36Sopenharmony_ci mcp->mb[0] = MBC_DUMP_RISC_RAM; 436462306a36Sopenharmony_ci mcp->out_mb = MBX_0; 436562306a36Sopenharmony_ci } 436662306a36Sopenharmony_ci mcp->mb[1] = LSW(addr); 436762306a36Sopenharmony_ci mcp->mb[2] = MSW(req_dma); 436862306a36Sopenharmony_ci mcp->mb[3] = LSW(req_dma); 436962306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(req_dma)); 437062306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(req_dma)); 437162306a36Sopenharmony_ci mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1; 437262306a36Sopenharmony_ci if (IS_FWI2_CAPABLE(vha->hw)) { 437362306a36Sopenharmony_ci mcp->mb[4] = MSW(size); 437462306a36Sopenharmony_ci mcp->mb[5] = LSW(size); 437562306a36Sopenharmony_ci mcp->out_mb |= MBX_5|MBX_4; 437662306a36Sopenharmony_ci } else { 437762306a36Sopenharmony_ci mcp->mb[4] = LSW(size); 437862306a36Sopenharmony_ci mcp->out_mb |= MBX_4; 437962306a36Sopenharmony_ci } 438062306a36Sopenharmony_ci 438162306a36Sopenharmony_ci mcp->in_mb = MBX_0; 438262306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 438362306a36Sopenharmony_ci mcp->flags = 0; 438462306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 438562306a36Sopenharmony_ci 438662306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 438762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1008, 438862306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 438962306a36Sopenharmony_ci } else { 439062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1007, 439162306a36Sopenharmony_ci "Done %s.\n", __func__); 439262306a36Sopenharmony_ci } 439362306a36Sopenharmony_ci 439462306a36Sopenharmony_ci return rval; 439562306a36Sopenharmony_ci} 439662306a36Sopenharmony_ci/* 84XX Support **************************************************************/ 439762306a36Sopenharmony_ci 439862306a36Sopenharmony_cistruct cs84xx_mgmt_cmd { 439962306a36Sopenharmony_ci union { 440062306a36Sopenharmony_ci struct verify_chip_entry_84xx req; 440162306a36Sopenharmony_ci struct verify_chip_rsp_84xx rsp; 440262306a36Sopenharmony_ci } p; 440362306a36Sopenharmony_ci}; 440462306a36Sopenharmony_ci 440562306a36Sopenharmony_ciint 440662306a36Sopenharmony_ciqla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status) 440762306a36Sopenharmony_ci{ 440862306a36Sopenharmony_ci int rval, retry; 440962306a36Sopenharmony_ci struct cs84xx_mgmt_cmd *mn; 441062306a36Sopenharmony_ci dma_addr_t mn_dma; 441162306a36Sopenharmony_ci uint16_t options; 441262306a36Sopenharmony_ci unsigned long flags; 441362306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 441462306a36Sopenharmony_ci 441562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c8, 441662306a36Sopenharmony_ci "Entered %s.\n", __func__); 441762306a36Sopenharmony_ci 441862306a36Sopenharmony_ci mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma); 441962306a36Sopenharmony_ci if (mn == NULL) { 442062306a36Sopenharmony_ci return QLA_MEMORY_ALLOC_FAILED; 442162306a36Sopenharmony_ci } 442262306a36Sopenharmony_ci 442362306a36Sopenharmony_ci /* Force Update? */ 442462306a36Sopenharmony_ci options = ha->cs84xx->fw_update ? VCO_FORCE_UPDATE : 0; 442562306a36Sopenharmony_ci /* Diagnostic firmware? */ 442662306a36Sopenharmony_ci /* options |= MENLO_DIAG_FW; */ 442762306a36Sopenharmony_ci /* We update the firmware with only one data sequence. */ 442862306a36Sopenharmony_ci options |= VCO_END_OF_DATA; 442962306a36Sopenharmony_ci 443062306a36Sopenharmony_ci do { 443162306a36Sopenharmony_ci retry = 0; 443262306a36Sopenharmony_ci memset(mn, 0, sizeof(*mn)); 443362306a36Sopenharmony_ci mn->p.req.entry_type = VERIFY_CHIP_IOCB_TYPE; 443462306a36Sopenharmony_ci mn->p.req.entry_count = 1; 443562306a36Sopenharmony_ci mn->p.req.options = cpu_to_le16(options); 443662306a36Sopenharmony_ci 443762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111c, 443862306a36Sopenharmony_ci "Dump of Verify Request.\n"); 443962306a36Sopenharmony_ci ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111e, 444062306a36Sopenharmony_ci mn, sizeof(*mn)); 444162306a36Sopenharmony_ci 444262306a36Sopenharmony_ci rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120); 444362306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 444462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10cb, 444562306a36Sopenharmony_ci "Failed to issue verify IOCB (%x).\n", rval); 444662306a36Sopenharmony_ci goto verify_done; 444762306a36Sopenharmony_ci } 444862306a36Sopenharmony_ci 444962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1110, 445062306a36Sopenharmony_ci "Dump of Verify Response.\n"); 445162306a36Sopenharmony_ci ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1118, 445262306a36Sopenharmony_ci mn, sizeof(*mn)); 445362306a36Sopenharmony_ci 445462306a36Sopenharmony_ci status[0] = le16_to_cpu(mn->p.rsp.comp_status); 445562306a36Sopenharmony_ci status[1] = status[0] == CS_VCS_CHIP_FAILURE ? 445662306a36Sopenharmony_ci le16_to_cpu(mn->p.rsp.failure_code) : 0; 445762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ce, 445862306a36Sopenharmony_ci "cs=%x fc=%x.\n", status[0], status[1]); 445962306a36Sopenharmony_ci 446062306a36Sopenharmony_ci if (status[0] != CS_COMPLETE) { 446162306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 446262306a36Sopenharmony_ci if (!(options & VCO_DONT_UPDATE_FW)) { 446362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10cf, 446462306a36Sopenharmony_ci "Firmware update failed. Retrying " 446562306a36Sopenharmony_ci "without update firmware.\n"); 446662306a36Sopenharmony_ci options |= VCO_DONT_UPDATE_FW; 446762306a36Sopenharmony_ci options &= ~VCO_FORCE_UPDATE; 446862306a36Sopenharmony_ci retry = 1; 446962306a36Sopenharmony_ci } 447062306a36Sopenharmony_ci } else { 447162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d0, 447262306a36Sopenharmony_ci "Firmware updated to %x.\n", 447362306a36Sopenharmony_ci le32_to_cpu(mn->p.rsp.fw_ver)); 447462306a36Sopenharmony_ci 447562306a36Sopenharmony_ci /* NOTE: we only update OP firmware. */ 447662306a36Sopenharmony_ci spin_lock_irqsave(&ha->cs84xx->access_lock, flags); 447762306a36Sopenharmony_ci ha->cs84xx->op_fw_version = 447862306a36Sopenharmony_ci le32_to_cpu(mn->p.rsp.fw_ver); 447962306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->cs84xx->access_lock, 448062306a36Sopenharmony_ci flags); 448162306a36Sopenharmony_ci } 448262306a36Sopenharmony_ci } while (retry); 448362306a36Sopenharmony_ci 448462306a36Sopenharmony_civerify_done: 448562306a36Sopenharmony_ci dma_pool_free(ha->s_dma_pool, mn, mn_dma); 448662306a36Sopenharmony_ci 448762306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 448862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10d1, 448962306a36Sopenharmony_ci "Failed=%x.\n", rval); 449062306a36Sopenharmony_ci } else { 449162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d2, 449262306a36Sopenharmony_ci "Done %s.\n", __func__); 449362306a36Sopenharmony_ci } 449462306a36Sopenharmony_ci 449562306a36Sopenharmony_ci return rval; 449662306a36Sopenharmony_ci} 449762306a36Sopenharmony_ci 449862306a36Sopenharmony_ciint 449962306a36Sopenharmony_ciqla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req) 450062306a36Sopenharmony_ci{ 450162306a36Sopenharmony_ci int rval; 450262306a36Sopenharmony_ci unsigned long flags; 450362306a36Sopenharmony_ci mbx_cmd_t mc; 450462306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 450562306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 450662306a36Sopenharmony_ci 450762306a36Sopenharmony_ci if (!ha->flags.fw_started) 450862306a36Sopenharmony_ci return QLA_SUCCESS; 450962306a36Sopenharmony_ci 451062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d3, 451162306a36Sopenharmony_ci "Entered %s.\n", __func__); 451262306a36Sopenharmony_ci 451362306a36Sopenharmony_ci if (IS_SHADOW_REG_CAPABLE(ha)) 451462306a36Sopenharmony_ci req->options |= BIT_13; 451562306a36Sopenharmony_ci 451662306a36Sopenharmony_ci mcp->mb[0] = MBC_INITIALIZE_MULTIQ; 451762306a36Sopenharmony_ci mcp->mb[1] = req->options; 451862306a36Sopenharmony_ci mcp->mb[2] = MSW(LSD(req->dma)); 451962306a36Sopenharmony_ci mcp->mb[3] = LSW(LSD(req->dma)); 452062306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(req->dma)); 452162306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(req->dma)); 452262306a36Sopenharmony_ci mcp->mb[5] = req->length; 452362306a36Sopenharmony_ci if (req->rsp) 452462306a36Sopenharmony_ci mcp->mb[10] = req->rsp->id; 452562306a36Sopenharmony_ci mcp->mb[12] = req->qos; 452662306a36Sopenharmony_ci mcp->mb[11] = req->vp_idx; 452762306a36Sopenharmony_ci mcp->mb[13] = req->rid; 452862306a36Sopenharmony_ci if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) 452962306a36Sopenharmony_ci mcp->mb[15] = 0; 453062306a36Sopenharmony_ci 453162306a36Sopenharmony_ci mcp->mb[4] = req->id; 453262306a36Sopenharmony_ci /* que in ptr index */ 453362306a36Sopenharmony_ci mcp->mb[8] = 0; 453462306a36Sopenharmony_ci /* que out ptr index */ 453562306a36Sopenharmony_ci mcp->mb[9] = *req->out_ptr = 0; 453662306a36Sopenharmony_ci mcp->out_mb = MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|MBX_7| 453762306a36Sopenharmony_ci MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 453862306a36Sopenharmony_ci mcp->in_mb = MBX_0; 453962306a36Sopenharmony_ci mcp->flags = MBX_DMA_OUT; 454062306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS * 2; 454162306a36Sopenharmony_ci 454262306a36Sopenharmony_ci if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || 454362306a36Sopenharmony_ci IS_QLA28XX(ha)) 454462306a36Sopenharmony_ci mcp->in_mb |= MBX_1; 454562306a36Sopenharmony_ci if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { 454662306a36Sopenharmony_ci mcp->out_mb |= MBX_15; 454762306a36Sopenharmony_ci /* debug q create issue in SR-IOV */ 454862306a36Sopenharmony_ci mcp->in_mb |= MBX_9 | MBX_8 | MBX_7; 454962306a36Sopenharmony_ci } 455062306a36Sopenharmony_ci 455162306a36Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 455262306a36Sopenharmony_ci if (!(req->options & BIT_0)) { 455362306a36Sopenharmony_ci wrt_reg_dword(req->req_q_in, 0); 455462306a36Sopenharmony_ci if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 455562306a36Sopenharmony_ci wrt_reg_dword(req->req_q_out, 0); 455662306a36Sopenharmony_ci } 455762306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 455862306a36Sopenharmony_ci 455962306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 456062306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 456162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10d4, 456262306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 456362306a36Sopenharmony_ci } else { 456462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d5, 456562306a36Sopenharmony_ci "Done %s.\n", __func__); 456662306a36Sopenharmony_ci } 456762306a36Sopenharmony_ci 456862306a36Sopenharmony_ci return rval; 456962306a36Sopenharmony_ci} 457062306a36Sopenharmony_ci 457162306a36Sopenharmony_ciint 457262306a36Sopenharmony_ciqla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) 457362306a36Sopenharmony_ci{ 457462306a36Sopenharmony_ci int rval; 457562306a36Sopenharmony_ci unsigned long flags; 457662306a36Sopenharmony_ci mbx_cmd_t mc; 457762306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 457862306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 457962306a36Sopenharmony_ci 458062306a36Sopenharmony_ci if (!ha->flags.fw_started) 458162306a36Sopenharmony_ci return QLA_SUCCESS; 458262306a36Sopenharmony_ci 458362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d6, 458462306a36Sopenharmony_ci "Entered %s.\n", __func__); 458562306a36Sopenharmony_ci 458662306a36Sopenharmony_ci if (IS_SHADOW_REG_CAPABLE(ha)) 458762306a36Sopenharmony_ci rsp->options |= BIT_13; 458862306a36Sopenharmony_ci 458962306a36Sopenharmony_ci mcp->mb[0] = MBC_INITIALIZE_MULTIQ; 459062306a36Sopenharmony_ci mcp->mb[1] = rsp->options; 459162306a36Sopenharmony_ci mcp->mb[2] = MSW(LSD(rsp->dma)); 459262306a36Sopenharmony_ci mcp->mb[3] = LSW(LSD(rsp->dma)); 459362306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(rsp->dma)); 459462306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(rsp->dma)); 459562306a36Sopenharmony_ci mcp->mb[5] = rsp->length; 459662306a36Sopenharmony_ci mcp->mb[14] = rsp->msix->entry; 459762306a36Sopenharmony_ci mcp->mb[13] = rsp->rid; 459862306a36Sopenharmony_ci if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) 459962306a36Sopenharmony_ci mcp->mb[15] = 0; 460062306a36Sopenharmony_ci 460162306a36Sopenharmony_ci mcp->mb[4] = rsp->id; 460262306a36Sopenharmony_ci /* que in ptr index */ 460362306a36Sopenharmony_ci mcp->mb[8] = *rsp->in_ptr = 0; 460462306a36Sopenharmony_ci /* que out ptr index */ 460562306a36Sopenharmony_ci mcp->mb[9] = 0; 460662306a36Sopenharmony_ci mcp->out_mb = MBX_14|MBX_13|MBX_9|MBX_8|MBX_7 460762306a36Sopenharmony_ci |MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 460862306a36Sopenharmony_ci mcp->in_mb = MBX_0; 460962306a36Sopenharmony_ci mcp->flags = MBX_DMA_OUT; 461062306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS * 2; 461162306a36Sopenharmony_ci 461262306a36Sopenharmony_ci if (IS_QLA81XX(ha)) { 461362306a36Sopenharmony_ci mcp->out_mb |= MBX_12|MBX_11|MBX_10; 461462306a36Sopenharmony_ci mcp->in_mb |= MBX_1; 461562306a36Sopenharmony_ci } else if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { 461662306a36Sopenharmony_ci mcp->out_mb |= MBX_15|MBX_12|MBX_11|MBX_10; 461762306a36Sopenharmony_ci mcp->in_mb |= MBX_1; 461862306a36Sopenharmony_ci /* debug q create issue in SR-IOV */ 461962306a36Sopenharmony_ci mcp->in_mb |= MBX_9 | MBX_8 | MBX_7; 462062306a36Sopenharmony_ci } 462162306a36Sopenharmony_ci 462262306a36Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 462362306a36Sopenharmony_ci if (!(rsp->options & BIT_0)) { 462462306a36Sopenharmony_ci wrt_reg_dword(rsp->rsp_q_out, 0); 462562306a36Sopenharmony_ci if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 462662306a36Sopenharmony_ci wrt_reg_dword(rsp->rsp_q_in, 0); 462762306a36Sopenharmony_ci } 462862306a36Sopenharmony_ci 462962306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 463062306a36Sopenharmony_ci 463162306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 463262306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 463362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10d7, 463462306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 463562306a36Sopenharmony_ci } else { 463662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d8, 463762306a36Sopenharmony_ci "Done %s.\n", __func__); 463862306a36Sopenharmony_ci } 463962306a36Sopenharmony_ci 464062306a36Sopenharmony_ci return rval; 464162306a36Sopenharmony_ci} 464262306a36Sopenharmony_ci 464362306a36Sopenharmony_ciint 464462306a36Sopenharmony_ciqla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb) 464562306a36Sopenharmony_ci{ 464662306a36Sopenharmony_ci int rval; 464762306a36Sopenharmony_ci mbx_cmd_t mc; 464862306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 464962306a36Sopenharmony_ci 465062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d9, 465162306a36Sopenharmony_ci "Entered %s.\n", __func__); 465262306a36Sopenharmony_ci 465362306a36Sopenharmony_ci mcp->mb[0] = MBC_IDC_ACK; 465462306a36Sopenharmony_ci memcpy(&mcp->mb[1], mb, QLA_IDC_ACK_REGS * sizeof(uint16_t)); 465562306a36Sopenharmony_ci mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 465662306a36Sopenharmony_ci mcp->in_mb = MBX_0; 465762306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 465862306a36Sopenharmony_ci mcp->flags = 0; 465962306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 466062306a36Sopenharmony_ci 466162306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 466262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10da, 466362306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 466462306a36Sopenharmony_ci } else { 466562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10db, 466662306a36Sopenharmony_ci "Done %s.\n", __func__); 466762306a36Sopenharmony_ci } 466862306a36Sopenharmony_ci 466962306a36Sopenharmony_ci return rval; 467062306a36Sopenharmony_ci} 467162306a36Sopenharmony_ci 467262306a36Sopenharmony_ciint 467362306a36Sopenharmony_ciqla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size) 467462306a36Sopenharmony_ci{ 467562306a36Sopenharmony_ci int rval; 467662306a36Sopenharmony_ci mbx_cmd_t mc; 467762306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 467862306a36Sopenharmony_ci 467962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10dc, 468062306a36Sopenharmony_ci "Entered %s.\n", __func__); 468162306a36Sopenharmony_ci 468262306a36Sopenharmony_ci if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) && 468362306a36Sopenharmony_ci !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw)) 468462306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 468562306a36Sopenharmony_ci 468662306a36Sopenharmony_ci mcp->mb[0] = MBC_FLASH_ACCESS_CTRL; 468762306a36Sopenharmony_ci mcp->mb[1] = FAC_OPT_CMD_GET_SECTOR_SIZE; 468862306a36Sopenharmony_ci mcp->out_mb = MBX_1|MBX_0; 468962306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 469062306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 469162306a36Sopenharmony_ci mcp->flags = 0; 469262306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 469362306a36Sopenharmony_ci 469462306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 469562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10dd, 469662306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x.\n", 469762306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1]); 469862306a36Sopenharmony_ci } else { 469962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10de, 470062306a36Sopenharmony_ci "Done %s.\n", __func__); 470162306a36Sopenharmony_ci *sector_size = mcp->mb[1]; 470262306a36Sopenharmony_ci } 470362306a36Sopenharmony_ci 470462306a36Sopenharmony_ci return rval; 470562306a36Sopenharmony_ci} 470662306a36Sopenharmony_ci 470762306a36Sopenharmony_ciint 470862306a36Sopenharmony_ciqla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable) 470962306a36Sopenharmony_ci{ 471062306a36Sopenharmony_ci int rval; 471162306a36Sopenharmony_ci mbx_cmd_t mc; 471262306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 471362306a36Sopenharmony_ci 471462306a36Sopenharmony_ci if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) && 471562306a36Sopenharmony_ci !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw)) 471662306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 471762306a36Sopenharmony_ci 471862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10df, 471962306a36Sopenharmony_ci "Entered %s.\n", __func__); 472062306a36Sopenharmony_ci 472162306a36Sopenharmony_ci mcp->mb[0] = MBC_FLASH_ACCESS_CTRL; 472262306a36Sopenharmony_ci mcp->mb[1] = enable ? FAC_OPT_CMD_WRITE_ENABLE : 472362306a36Sopenharmony_ci FAC_OPT_CMD_WRITE_PROTECT; 472462306a36Sopenharmony_ci mcp->out_mb = MBX_1|MBX_0; 472562306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 472662306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 472762306a36Sopenharmony_ci mcp->flags = 0; 472862306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 472962306a36Sopenharmony_ci 473062306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 473162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10e0, 473262306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x.\n", 473362306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1]); 473462306a36Sopenharmony_ci } else { 473562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e1, 473662306a36Sopenharmony_ci "Done %s.\n", __func__); 473762306a36Sopenharmony_ci } 473862306a36Sopenharmony_ci 473962306a36Sopenharmony_ci return rval; 474062306a36Sopenharmony_ci} 474162306a36Sopenharmony_ci 474262306a36Sopenharmony_ciint 474362306a36Sopenharmony_ciqla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish) 474462306a36Sopenharmony_ci{ 474562306a36Sopenharmony_ci int rval; 474662306a36Sopenharmony_ci mbx_cmd_t mc; 474762306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 474862306a36Sopenharmony_ci 474962306a36Sopenharmony_ci if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) && 475062306a36Sopenharmony_ci !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw)) 475162306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 475262306a36Sopenharmony_ci 475362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e2, 475462306a36Sopenharmony_ci "Entered %s.\n", __func__); 475562306a36Sopenharmony_ci 475662306a36Sopenharmony_ci mcp->mb[0] = MBC_FLASH_ACCESS_CTRL; 475762306a36Sopenharmony_ci mcp->mb[1] = FAC_OPT_CMD_ERASE_SECTOR; 475862306a36Sopenharmony_ci mcp->mb[2] = LSW(start); 475962306a36Sopenharmony_ci mcp->mb[3] = MSW(start); 476062306a36Sopenharmony_ci mcp->mb[4] = LSW(finish); 476162306a36Sopenharmony_ci mcp->mb[5] = MSW(finish); 476262306a36Sopenharmony_ci mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 476362306a36Sopenharmony_ci mcp->in_mb = MBX_2|MBX_1|MBX_0; 476462306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 476562306a36Sopenharmony_ci mcp->flags = 0; 476662306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 476762306a36Sopenharmony_ci 476862306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 476962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10e3, 477062306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n", 477162306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); 477262306a36Sopenharmony_ci } else { 477362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e4, 477462306a36Sopenharmony_ci "Done %s.\n", __func__); 477562306a36Sopenharmony_ci } 477662306a36Sopenharmony_ci 477762306a36Sopenharmony_ci return rval; 477862306a36Sopenharmony_ci} 477962306a36Sopenharmony_ci 478062306a36Sopenharmony_ciint 478162306a36Sopenharmony_ciqla81xx_fac_semaphore_access(scsi_qla_host_t *vha, int lock) 478262306a36Sopenharmony_ci{ 478362306a36Sopenharmony_ci int rval = QLA_SUCCESS; 478462306a36Sopenharmony_ci mbx_cmd_t mc; 478562306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 478662306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 478762306a36Sopenharmony_ci 478862306a36Sopenharmony_ci if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && 478962306a36Sopenharmony_ci !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 479062306a36Sopenharmony_ci return rval; 479162306a36Sopenharmony_ci 479262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e2, 479362306a36Sopenharmony_ci "Entered %s.\n", __func__); 479462306a36Sopenharmony_ci 479562306a36Sopenharmony_ci mcp->mb[0] = MBC_FLASH_ACCESS_CTRL; 479662306a36Sopenharmony_ci mcp->mb[1] = (lock ? FAC_OPT_CMD_LOCK_SEMAPHORE : 479762306a36Sopenharmony_ci FAC_OPT_CMD_UNLOCK_SEMAPHORE); 479862306a36Sopenharmony_ci mcp->out_mb = MBX_1|MBX_0; 479962306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 480062306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 480162306a36Sopenharmony_ci mcp->flags = 0; 480262306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 480362306a36Sopenharmony_ci 480462306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 480562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10e3, 480662306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n", 480762306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); 480862306a36Sopenharmony_ci } else { 480962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e4, 481062306a36Sopenharmony_ci "Done %s.\n", __func__); 481162306a36Sopenharmony_ci } 481262306a36Sopenharmony_ci 481362306a36Sopenharmony_ci return rval; 481462306a36Sopenharmony_ci} 481562306a36Sopenharmony_ci 481662306a36Sopenharmony_ciint 481762306a36Sopenharmony_ciqla81xx_restart_mpi_firmware(scsi_qla_host_t *vha) 481862306a36Sopenharmony_ci{ 481962306a36Sopenharmony_ci int rval = 0; 482062306a36Sopenharmony_ci mbx_cmd_t mc; 482162306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 482262306a36Sopenharmony_ci 482362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e5, 482462306a36Sopenharmony_ci "Entered %s.\n", __func__); 482562306a36Sopenharmony_ci 482662306a36Sopenharmony_ci mcp->mb[0] = MBC_RESTART_MPI_FW; 482762306a36Sopenharmony_ci mcp->out_mb = MBX_0; 482862306a36Sopenharmony_ci mcp->in_mb = MBX_0|MBX_1; 482962306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 483062306a36Sopenharmony_ci mcp->flags = 0; 483162306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 483262306a36Sopenharmony_ci 483362306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 483462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10e6, 483562306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x.\n", 483662306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1]); 483762306a36Sopenharmony_ci } else { 483862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e7, 483962306a36Sopenharmony_ci "Done %s.\n", __func__); 484062306a36Sopenharmony_ci } 484162306a36Sopenharmony_ci 484262306a36Sopenharmony_ci return rval; 484362306a36Sopenharmony_ci} 484462306a36Sopenharmony_ci 484562306a36Sopenharmony_ciint 484662306a36Sopenharmony_ciqla82xx_set_driver_version(scsi_qla_host_t *vha, char *version) 484762306a36Sopenharmony_ci{ 484862306a36Sopenharmony_ci int rval; 484962306a36Sopenharmony_ci mbx_cmd_t mc; 485062306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 485162306a36Sopenharmony_ci int i; 485262306a36Sopenharmony_ci int len; 485362306a36Sopenharmony_ci __le16 *str; 485462306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 485562306a36Sopenharmony_ci 485662306a36Sopenharmony_ci if (!IS_P3P_TYPE(ha)) 485762306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 485862306a36Sopenharmony_ci 485962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x117b, 486062306a36Sopenharmony_ci "Entered %s.\n", __func__); 486162306a36Sopenharmony_ci 486262306a36Sopenharmony_ci str = (__force __le16 *)version; 486362306a36Sopenharmony_ci len = strlen(version); 486462306a36Sopenharmony_ci 486562306a36Sopenharmony_ci mcp->mb[0] = MBC_SET_RNID_PARAMS; 486662306a36Sopenharmony_ci mcp->mb[1] = RNID_TYPE_SET_VERSION << 8; 486762306a36Sopenharmony_ci mcp->out_mb = MBX_1|MBX_0; 486862306a36Sopenharmony_ci for (i = 4; i < 16 && len; i++, str++, len -= 2) { 486962306a36Sopenharmony_ci mcp->mb[i] = le16_to_cpup(str); 487062306a36Sopenharmony_ci mcp->out_mb |= 1<<i; 487162306a36Sopenharmony_ci } 487262306a36Sopenharmony_ci for (; i < 16; i++) { 487362306a36Sopenharmony_ci mcp->mb[i] = 0; 487462306a36Sopenharmony_ci mcp->out_mb |= 1<<i; 487562306a36Sopenharmony_ci } 487662306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 487762306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 487862306a36Sopenharmony_ci mcp->flags = 0; 487962306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 488062306a36Sopenharmony_ci 488162306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 488262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x117c, 488362306a36Sopenharmony_ci "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]); 488462306a36Sopenharmony_ci } else { 488562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x117d, 488662306a36Sopenharmony_ci "Done %s.\n", __func__); 488762306a36Sopenharmony_ci } 488862306a36Sopenharmony_ci 488962306a36Sopenharmony_ci return rval; 489062306a36Sopenharmony_ci} 489162306a36Sopenharmony_ci 489262306a36Sopenharmony_ciint 489362306a36Sopenharmony_ciqla25xx_set_driver_version(scsi_qla_host_t *vha, char *version) 489462306a36Sopenharmony_ci{ 489562306a36Sopenharmony_ci int rval; 489662306a36Sopenharmony_ci mbx_cmd_t mc; 489762306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 489862306a36Sopenharmony_ci int len; 489962306a36Sopenharmony_ci uint16_t dwlen; 490062306a36Sopenharmony_ci uint8_t *str; 490162306a36Sopenharmony_ci dma_addr_t str_dma; 490262306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 490362306a36Sopenharmony_ci 490462306a36Sopenharmony_ci if (!IS_FWI2_CAPABLE(ha) || IS_QLA24XX_TYPE(ha) || IS_QLA81XX(ha) || 490562306a36Sopenharmony_ci IS_P3P_TYPE(ha)) 490662306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 490762306a36Sopenharmony_ci 490862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x117e, 490962306a36Sopenharmony_ci "Entered %s.\n", __func__); 491062306a36Sopenharmony_ci 491162306a36Sopenharmony_ci str = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &str_dma); 491262306a36Sopenharmony_ci if (!str) { 491362306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x117f, 491462306a36Sopenharmony_ci "Failed to allocate driver version param.\n"); 491562306a36Sopenharmony_ci return QLA_MEMORY_ALLOC_FAILED; 491662306a36Sopenharmony_ci } 491762306a36Sopenharmony_ci 491862306a36Sopenharmony_ci memcpy(str, "\x7\x3\x11\x0", 4); 491962306a36Sopenharmony_ci dwlen = str[0]; 492062306a36Sopenharmony_ci len = dwlen * 4 - 4; 492162306a36Sopenharmony_ci memset(str + 4, 0, len); 492262306a36Sopenharmony_ci if (len > strlen(version)) 492362306a36Sopenharmony_ci len = strlen(version); 492462306a36Sopenharmony_ci memcpy(str + 4, version, len); 492562306a36Sopenharmony_ci 492662306a36Sopenharmony_ci mcp->mb[0] = MBC_SET_RNID_PARAMS; 492762306a36Sopenharmony_ci mcp->mb[1] = RNID_TYPE_SET_VERSION << 8 | dwlen; 492862306a36Sopenharmony_ci mcp->mb[2] = MSW(LSD(str_dma)); 492962306a36Sopenharmony_ci mcp->mb[3] = LSW(LSD(str_dma)); 493062306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(str_dma)); 493162306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(str_dma)); 493262306a36Sopenharmony_ci mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; 493362306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 493462306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 493562306a36Sopenharmony_ci mcp->flags = 0; 493662306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 493762306a36Sopenharmony_ci 493862306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 493962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1180, 494062306a36Sopenharmony_ci "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]); 494162306a36Sopenharmony_ci } else { 494262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1181, 494362306a36Sopenharmony_ci "Done %s.\n", __func__); 494462306a36Sopenharmony_ci } 494562306a36Sopenharmony_ci 494662306a36Sopenharmony_ci dma_pool_free(ha->s_dma_pool, str, str_dma); 494762306a36Sopenharmony_ci 494862306a36Sopenharmony_ci return rval; 494962306a36Sopenharmony_ci} 495062306a36Sopenharmony_ci 495162306a36Sopenharmony_ciint 495262306a36Sopenharmony_ciqla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma, 495362306a36Sopenharmony_ci void *buf, uint16_t bufsiz) 495462306a36Sopenharmony_ci{ 495562306a36Sopenharmony_ci int rval, i; 495662306a36Sopenharmony_ci mbx_cmd_t mc; 495762306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 495862306a36Sopenharmony_ci uint32_t *bp; 495962306a36Sopenharmony_ci 496062306a36Sopenharmony_ci if (!IS_FWI2_CAPABLE(vha->hw)) 496162306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 496262306a36Sopenharmony_ci 496362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1159, 496462306a36Sopenharmony_ci "Entered %s.\n", __func__); 496562306a36Sopenharmony_ci 496662306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_RNID_PARAMS; 496762306a36Sopenharmony_ci mcp->mb[1] = RNID_TYPE_PORT_LOGIN << 8; 496862306a36Sopenharmony_ci mcp->mb[2] = MSW(buf_dma); 496962306a36Sopenharmony_ci mcp->mb[3] = LSW(buf_dma); 497062306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(buf_dma)); 497162306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(buf_dma)); 497262306a36Sopenharmony_ci mcp->mb[8] = bufsiz/4; 497362306a36Sopenharmony_ci mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 497462306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 497562306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 497662306a36Sopenharmony_ci mcp->flags = 0; 497762306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 497862306a36Sopenharmony_ci 497962306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 498062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x115a, 498162306a36Sopenharmony_ci "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]); 498262306a36Sopenharmony_ci } else { 498362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x115b, 498462306a36Sopenharmony_ci "Done %s.\n", __func__); 498562306a36Sopenharmony_ci bp = (uint32_t *) buf; 498662306a36Sopenharmony_ci for (i = 0; i < (bufsiz-4)/4; i++, bp++) 498762306a36Sopenharmony_ci *bp = le32_to_cpu((__force __le32)*bp); 498862306a36Sopenharmony_ci } 498962306a36Sopenharmony_ci 499062306a36Sopenharmony_ci return rval; 499162306a36Sopenharmony_ci} 499262306a36Sopenharmony_ci 499362306a36Sopenharmony_ci#define PUREX_CMD_COUNT 4 499462306a36Sopenharmony_ciint 499562306a36Sopenharmony_ciqla25xx_set_els_cmds_supported(scsi_qla_host_t *vha) 499662306a36Sopenharmony_ci{ 499762306a36Sopenharmony_ci int rval; 499862306a36Sopenharmony_ci mbx_cmd_t mc; 499962306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 500062306a36Sopenharmony_ci uint8_t *els_cmd_map; 500162306a36Sopenharmony_ci uint8_t active_cnt = 0; 500262306a36Sopenharmony_ci dma_addr_t els_cmd_map_dma; 500362306a36Sopenharmony_ci uint8_t cmd_opcode[PUREX_CMD_COUNT]; 500462306a36Sopenharmony_ci uint8_t i, index, purex_bit; 500562306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 500662306a36Sopenharmony_ci 500762306a36Sopenharmony_ci if (!IS_QLA25XX(ha) && !IS_QLA2031(ha) && 500862306a36Sopenharmony_ci !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 500962306a36Sopenharmony_ci return QLA_SUCCESS; 501062306a36Sopenharmony_ci 501162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1197, 501262306a36Sopenharmony_ci "Entered %s.\n", __func__); 501362306a36Sopenharmony_ci 501462306a36Sopenharmony_ci els_cmd_map = dma_alloc_coherent(&ha->pdev->dev, ELS_CMD_MAP_SIZE, 501562306a36Sopenharmony_ci &els_cmd_map_dma, GFP_KERNEL); 501662306a36Sopenharmony_ci if (!els_cmd_map) { 501762306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x7101, 501862306a36Sopenharmony_ci "Failed to allocate RDP els command param.\n"); 501962306a36Sopenharmony_ci return QLA_MEMORY_ALLOC_FAILED; 502062306a36Sopenharmony_ci } 502162306a36Sopenharmony_ci 502262306a36Sopenharmony_ci /* List of Purex ELS */ 502362306a36Sopenharmony_ci if (ql2xrdpenable) { 502462306a36Sopenharmony_ci cmd_opcode[active_cnt] = ELS_RDP; 502562306a36Sopenharmony_ci active_cnt++; 502662306a36Sopenharmony_ci } 502762306a36Sopenharmony_ci if (ha->flags.scm_supported_f) { 502862306a36Sopenharmony_ci cmd_opcode[active_cnt] = ELS_FPIN; 502962306a36Sopenharmony_ci active_cnt++; 503062306a36Sopenharmony_ci } 503162306a36Sopenharmony_ci if (ha->flags.edif_enabled) { 503262306a36Sopenharmony_ci cmd_opcode[active_cnt] = ELS_AUTH_ELS; 503362306a36Sopenharmony_ci active_cnt++; 503462306a36Sopenharmony_ci } 503562306a36Sopenharmony_ci 503662306a36Sopenharmony_ci for (i = 0; i < active_cnt; i++) { 503762306a36Sopenharmony_ci index = cmd_opcode[i] / 8; 503862306a36Sopenharmony_ci purex_bit = cmd_opcode[i] % 8; 503962306a36Sopenharmony_ci els_cmd_map[index] |= 1 << purex_bit; 504062306a36Sopenharmony_ci } 504162306a36Sopenharmony_ci 504262306a36Sopenharmony_ci mcp->mb[0] = MBC_SET_RNID_PARAMS; 504362306a36Sopenharmony_ci mcp->mb[1] = RNID_TYPE_ELS_CMD << 8; 504462306a36Sopenharmony_ci mcp->mb[2] = MSW(LSD(els_cmd_map_dma)); 504562306a36Sopenharmony_ci mcp->mb[3] = LSW(LSD(els_cmd_map_dma)); 504662306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(els_cmd_map_dma)); 504762306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(els_cmd_map_dma)); 504862306a36Sopenharmony_ci mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; 504962306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 505062306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 505162306a36Sopenharmony_ci mcp->flags = MBX_DMA_OUT; 505262306a36Sopenharmony_ci mcp->buf_size = ELS_CMD_MAP_SIZE; 505362306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 505462306a36Sopenharmony_ci 505562306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 505662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x118d, 505762306a36Sopenharmony_ci "Failed=%x (%x,%x).\n", rval, mcp->mb[0], mcp->mb[1]); 505862306a36Sopenharmony_ci } else { 505962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118c, 506062306a36Sopenharmony_ci "Done %s.\n", __func__); 506162306a36Sopenharmony_ci } 506262306a36Sopenharmony_ci 506362306a36Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, ELS_CMD_MAP_SIZE, 506462306a36Sopenharmony_ci els_cmd_map, els_cmd_map_dma); 506562306a36Sopenharmony_ci 506662306a36Sopenharmony_ci return rval; 506762306a36Sopenharmony_ci} 506862306a36Sopenharmony_ci 506962306a36Sopenharmony_cistatic int 507062306a36Sopenharmony_ciqla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp) 507162306a36Sopenharmony_ci{ 507262306a36Sopenharmony_ci int rval; 507362306a36Sopenharmony_ci mbx_cmd_t mc; 507462306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 507562306a36Sopenharmony_ci 507662306a36Sopenharmony_ci if (!IS_FWI2_CAPABLE(vha->hw)) 507762306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 507862306a36Sopenharmony_ci 507962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1159, 508062306a36Sopenharmony_ci "Entered %s.\n", __func__); 508162306a36Sopenharmony_ci 508262306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_RNID_PARAMS; 508362306a36Sopenharmony_ci mcp->mb[1] = RNID_TYPE_ASIC_TEMP << 8; 508462306a36Sopenharmony_ci mcp->out_mb = MBX_1|MBX_0; 508562306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 508662306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 508762306a36Sopenharmony_ci mcp->flags = 0; 508862306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 508962306a36Sopenharmony_ci *temp = mcp->mb[1]; 509062306a36Sopenharmony_ci 509162306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 509262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x115a, 509362306a36Sopenharmony_ci "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]); 509462306a36Sopenharmony_ci } else { 509562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x115b, 509662306a36Sopenharmony_ci "Done %s.\n", __func__); 509762306a36Sopenharmony_ci } 509862306a36Sopenharmony_ci 509962306a36Sopenharmony_ci return rval; 510062306a36Sopenharmony_ci} 510162306a36Sopenharmony_ci 510262306a36Sopenharmony_ciint 510362306a36Sopenharmony_ciqla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, 510462306a36Sopenharmony_ci uint16_t dev, uint16_t off, uint16_t len, uint16_t opt) 510562306a36Sopenharmony_ci{ 510662306a36Sopenharmony_ci int rval; 510762306a36Sopenharmony_ci mbx_cmd_t mc; 510862306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 510962306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 511062306a36Sopenharmony_ci 511162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e8, 511262306a36Sopenharmony_ci "Entered %s.\n", __func__); 511362306a36Sopenharmony_ci 511462306a36Sopenharmony_ci if (!IS_FWI2_CAPABLE(ha)) 511562306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 511662306a36Sopenharmony_ci 511762306a36Sopenharmony_ci if (len == 1) 511862306a36Sopenharmony_ci opt |= BIT_0; 511962306a36Sopenharmony_ci 512062306a36Sopenharmony_ci mcp->mb[0] = MBC_READ_SFP; 512162306a36Sopenharmony_ci mcp->mb[1] = dev; 512262306a36Sopenharmony_ci mcp->mb[2] = MSW(LSD(sfp_dma)); 512362306a36Sopenharmony_ci mcp->mb[3] = LSW(LSD(sfp_dma)); 512462306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(sfp_dma)); 512562306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(sfp_dma)); 512662306a36Sopenharmony_ci mcp->mb[8] = len; 512762306a36Sopenharmony_ci mcp->mb[9] = off; 512862306a36Sopenharmony_ci mcp->mb[10] = opt; 512962306a36Sopenharmony_ci mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; 513062306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 513162306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 513262306a36Sopenharmony_ci mcp->flags = 0; 513362306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 513462306a36Sopenharmony_ci 513562306a36Sopenharmony_ci if (opt & BIT_0) 513662306a36Sopenharmony_ci *sfp = mcp->mb[1]; 513762306a36Sopenharmony_ci 513862306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 513962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10e9, 514062306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 514162306a36Sopenharmony_ci if (mcp->mb[0] == MBS_COMMAND_ERROR && mcp->mb[1] == 0x22) { 514262306a36Sopenharmony_ci /* sfp is not there */ 514362306a36Sopenharmony_ci rval = QLA_INTERFACE_ERROR; 514462306a36Sopenharmony_ci } 514562306a36Sopenharmony_ci } else { 514662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea, 514762306a36Sopenharmony_ci "Done %s.\n", __func__); 514862306a36Sopenharmony_ci } 514962306a36Sopenharmony_ci 515062306a36Sopenharmony_ci return rval; 515162306a36Sopenharmony_ci} 515262306a36Sopenharmony_ci 515362306a36Sopenharmony_ciint 515462306a36Sopenharmony_ciqla2x00_write_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, 515562306a36Sopenharmony_ci uint16_t dev, uint16_t off, uint16_t len, uint16_t opt) 515662306a36Sopenharmony_ci{ 515762306a36Sopenharmony_ci int rval; 515862306a36Sopenharmony_ci mbx_cmd_t mc; 515962306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 516062306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 516162306a36Sopenharmony_ci 516262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10eb, 516362306a36Sopenharmony_ci "Entered %s.\n", __func__); 516462306a36Sopenharmony_ci 516562306a36Sopenharmony_ci if (!IS_FWI2_CAPABLE(ha)) 516662306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 516762306a36Sopenharmony_ci 516862306a36Sopenharmony_ci if (len == 1) 516962306a36Sopenharmony_ci opt |= BIT_0; 517062306a36Sopenharmony_ci 517162306a36Sopenharmony_ci if (opt & BIT_0) 517262306a36Sopenharmony_ci len = *sfp; 517362306a36Sopenharmony_ci 517462306a36Sopenharmony_ci mcp->mb[0] = MBC_WRITE_SFP; 517562306a36Sopenharmony_ci mcp->mb[1] = dev; 517662306a36Sopenharmony_ci mcp->mb[2] = MSW(LSD(sfp_dma)); 517762306a36Sopenharmony_ci mcp->mb[3] = LSW(LSD(sfp_dma)); 517862306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(sfp_dma)); 517962306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(sfp_dma)); 518062306a36Sopenharmony_ci mcp->mb[8] = len; 518162306a36Sopenharmony_ci mcp->mb[9] = off; 518262306a36Sopenharmony_ci mcp->mb[10] = opt; 518362306a36Sopenharmony_ci mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; 518462306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 518562306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 518662306a36Sopenharmony_ci mcp->flags = 0; 518762306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 518862306a36Sopenharmony_ci 518962306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 519062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10ec, 519162306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 519262306a36Sopenharmony_ci } else { 519362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ed, 519462306a36Sopenharmony_ci "Done %s.\n", __func__); 519562306a36Sopenharmony_ci } 519662306a36Sopenharmony_ci 519762306a36Sopenharmony_ci return rval; 519862306a36Sopenharmony_ci} 519962306a36Sopenharmony_ci 520062306a36Sopenharmony_ciint 520162306a36Sopenharmony_ciqla2x00_get_xgmac_stats(scsi_qla_host_t *vha, dma_addr_t stats_dma, 520262306a36Sopenharmony_ci uint16_t size_in_bytes, uint16_t *actual_size) 520362306a36Sopenharmony_ci{ 520462306a36Sopenharmony_ci int rval; 520562306a36Sopenharmony_ci mbx_cmd_t mc; 520662306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 520762306a36Sopenharmony_ci 520862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ee, 520962306a36Sopenharmony_ci "Entered %s.\n", __func__); 521062306a36Sopenharmony_ci 521162306a36Sopenharmony_ci if (!IS_CNA_CAPABLE(vha->hw)) 521262306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 521362306a36Sopenharmony_ci 521462306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_XGMAC_STATS; 521562306a36Sopenharmony_ci mcp->mb[2] = MSW(stats_dma); 521662306a36Sopenharmony_ci mcp->mb[3] = LSW(stats_dma); 521762306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(stats_dma)); 521862306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(stats_dma)); 521962306a36Sopenharmony_ci mcp->mb[8] = size_in_bytes >> 2; 522062306a36Sopenharmony_ci mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; 522162306a36Sopenharmony_ci mcp->in_mb = MBX_2|MBX_1|MBX_0; 522262306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 522362306a36Sopenharmony_ci mcp->flags = 0; 522462306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 522562306a36Sopenharmony_ci 522662306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 522762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10ef, 522862306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n", 522962306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); 523062306a36Sopenharmony_ci } else { 523162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f0, 523262306a36Sopenharmony_ci "Done %s.\n", __func__); 523362306a36Sopenharmony_ci 523462306a36Sopenharmony_ci 523562306a36Sopenharmony_ci *actual_size = mcp->mb[2] << 2; 523662306a36Sopenharmony_ci } 523762306a36Sopenharmony_ci 523862306a36Sopenharmony_ci return rval; 523962306a36Sopenharmony_ci} 524062306a36Sopenharmony_ci 524162306a36Sopenharmony_ciint 524262306a36Sopenharmony_ciqla2x00_get_dcbx_params(scsi_qla_host_t *vha, dma_addr_t tlv_dma, 524362306a36Sopenharmony_ci uint16_t size) 524462306a36Sopenharmony_ci{ 524562306a36Sopenharmony_ci int rval; 524662306a36Sopenharmony_ci mbx_cmd_t mc; 524762306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 524862306a36Sopenharmony_ci 524962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f1, 525062306a36Sopenharmony_ci "Entered %s.\n", __func__); 525162306a36Sopenharmony_ci 525262306a36Sopenharmony_ci if (!IS_CNA_CAPABLE(vha->hw)) 525362306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 525462306a36Sopenharmony_ci 525562306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_DCBX_PARAMS; 525662306a36Sopenharmony_ci mcp->mb[1] = 0; 525762306a36Sopenharmony_ci mcp->mb[2] = MSW(tlv_dma); 525862306a36Sopenharmony_ci mcp->mb[3] = LSW(tlv_dma); 525962306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(tlv_dma)); 526062306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(tlv_dma)); 526162306a36Sopenharmony_ci mcp->mb[8] = size; 526262306a36Sopenharmony_ci mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; 526362306a36Sopenharmony_ci mcp->in_mb = MBX_2|MBX_1|MBX_0; 526462306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 526562306a36Sopenharmony_ci mcp->flags = 0; 526662306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 526762306a36Sopenharmony_ci 526862306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 526962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10f2, 527062306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n", 527162306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); 527262306a36Sopenharmony_ci } else { 527362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f3, 527462306a36Sopenharmony_ci "Done %s.\n", __func__); 527562306a36Sopenharmony_ci } 527662306a36Sopenharmony_ci 527762306a36Sopenharmony_ci return rval; 527862306a36Sopenharmony_ci} 527962306a36Sopenharmony_ci 528062306a36Sopenharmony_ciint 528162306a36Sopenharmony_ciqla2x00_read_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t *data) 528262306a36Sopenharmony_ci{ 528362306a36Sopenharmony_ci int rval; 528462306a36Sopenharmony_ci mbx_cmd_t mc; 528562306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 528662306a36Sopenharmony_ci 528762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f4, 528862306a36Sopenharmony_ci "Entered %s.\n", __func__); 528962306a36Sopenharmony_ci 529062306a36Sopenharmony_ci if (!IS_FWI2_CAPABLE(vha->hw)) 529162306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 529262306a36Sopenharmony_ci 529362306a36Sopenharmony_ci mcp->mb[0] = MBC_READ_RAM_EXTENDED; 529462306a36Sopenharmony_ci mcp->mb[1] = LSW(risc_addr); 529562306a36Sopenharmony_ci mcp->mb[8] = MSW(risc_addr); 529662306a36Sopenharmony_ci mcp->out_mb = MBX_8|MBX_1|MBX_0; 529762306a36Sopenharmony_ci mcp->in_mb = MBX_3|MBX_2|MBX_0; 529862306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 529962306a36Sopenharmony_ci mcp->flags = 0; 530062306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 530162306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 530262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10f5, 530362306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 530462306a36Sopenharmony_ci } else { 530562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f6, 530662306a36Sopenharmony_ci "Done %s.\n", __func__); 530762306a36Sopenharmony_ci *data = mcp->mb[3] << 16 | mcp->mb[2]; 530862306a36Sopenharmony_ci } 530962306a36Sopenharmony_ci 531062306a36Sopenharmony_ci return rval; 531162306a36Sopenharmony_ci} 531262306a36Sopenharmony_ci 531362306a36Sopenharmony_ciint 531462306a36Sopenharmony_ciqla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, 531562306a36Sopenharmony_ci uint16_t *mresp) 531662306a36Sopenharmony_ci{ 531762306a36Sopenharmony_ci int rval; 531862306a36Sopenharmony_ci mbx_cmd_t mc; 531962306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 532062306a36Sopenharmony_ci 532162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f7, 532262306a36Sopenharmony_ci "Entered %s.\n", __func__); 532362306a36Sopenharmony_ci 532462306a36Sopenharmony_ci memset(mcp->mb, 0 , sizeof(mcp->mb)); 532562306a36Sopenharmony_ci mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK; 532662306a36Sopenharmony_ci mcp->mb[1] = mreq->options | BIT_6; // BIT_6 specifies 64 bit addressing 532762306a36Sopenharmony_ci 532862306a36Sopenharmony_ci /* transfer count */ 532962306a36Sopenharmony_ci mcp->mb[10] = LSW(mreq->transfer_size); 533062306a36Sopenharmony_ci mcp->mb[11] = MSW(mreq->transfer_size); 533162306a36Sopenharmony_ci 533262306a36Sopenharmony_ci /* send data address */ 533362306a36Sopenharmony_ci mcp->mb[14] = LSW(mreq->send_dma); 533462306a36Sopenharmony_ci mcp->mb[15] = MSW(mreq->send_dma); 533562306a36Sopenharmony_ci mcp->mb[20] = LSW(MSD(mreq->send_dma)); 533662306a36Sopenharmony_ci mcp->mb[21] = MSW(MSD(mreq->send_dma)); 533762306a36Sopenharmony_ci 533862306a36Sopenharmony_ci /* receive data address */ 533962306a36Sopenharmony_ci mcp->mb[16] = LSW(mreq->rcv_dma); 534062306a36Sopenharmony_ci mcp->mb[17] = MSW(mreq->rcv_dma); 534162306a36Sopenharmony_ci mcp->mb[6] = LSW(MSD(mreq->rcv_dma)); 534262306a36Sopenharmony_ci mcp->mb[7] = MSW(MSD(mreq->rcv_dma)); 534362306a36Sopenharmony_ci 534462306a36Sopenharmony_ci /* Iteration count */ 534562306a36Sopenharmony_ci mcp->mb[18] = LSW(mreq->iteration_count); 534662306a36Sopenharmony_ci mcp->mb[19] = MSW(mreq->iteration_count); 534762306a36Sopenharmony_ci 534862306a36Sopenharmony_ci mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15| 534962306a36Sopenharmony_ci MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0; 535062306a36Sopenharmony_ci if (IS_CNA_CAPABLE(vha->hw)) 535162306a36Sopenharmony_ci mcp->out_mb |= MBX_2; 535262306a36Sopenharmony_ci mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0; 535362306a36Sopenharmony_ci 535462306a36Sopenharmony_ci mcp->buf_size = mreq->transfer_size; 535562306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 535662306a36Sopenharmony_ci mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; 535762306a36Sopenharmony_ci 535862306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 535962306a36Sopenharmony_ci 536062306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 536162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10f8, 536262306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[3]=%x mb[18]=%x " 536362306a36Sopenharmony_ci "mb[19]=%x.\n", rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], 536462306a36Sopenharmony_ci mcp->mb[3], mcp->mb[18], mcp->mb[19]); 536562306a36Sopenharmony_ci } else { 536662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f9, 536762306a36Sopenharmony_ci "Done %s.\n", __func__); 536862306a36Sopenharmony_ci } 536962306a36Sopenharmony_ci 537062306a36Sopenharmony_ci /* Copy mailbox information */ 537162306a36Sopenharmony_ci memcpy( mresp, mcp->mb, 64); 537262306a36Sopenharmony_ci return rval; 537362306a36Sopenharmony_ci} 537462306a36Sopenharmony_ci 537562306a36Sopenharmony_ciint 537662306a36Sopenharmony_ciqla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, 537762306a36Sopenharmony_ci uint16_t *mresp) 537862306a36Sopenharmony_ci{ 537962306a36Sopenharmony_ci int rval; 538062306a36Sopenharmony_ci mbx_cmd_t mc; 538162306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 538262306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 538362306a36Sopenharmony_ci 538462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10fa, 538562306a36Sopenharmony_ci "Entered %s.\n", __func__); 538662306a36Sopenharmony_ci 538762306a36Sopenharmony_ci memset(mcp->mb, 0 , sizeof(mcp->mb)); 538862306a36Sopenharmony_ci mcp->mb[0] = MBC_DIAGNOSTIC_ECHO; 538962306a36Sopenharmony_ci /* BIT_6 specifies 64bit address */ 539062306a36Sopenharmony_ci mcp->mb[1] = mreq->options | BIT_15 | BIT_6; 539162306a36Sopenharmony_ci if (IS_CNA_CAPABLE(ha)) { 539262306a36Sopenharmony_ci mcp->mb[2] = vha->fcoe_fcf_idx; 539362306a36Sopenharmony_ci } 539462306a36Sopenharmony_ci mcp->mb[16] = LSW(mreq->rcv_dma); 539562306a36Sopenharmony_ci mcp->mb[17] = MSW(mreq->rcv_dma); 539662306a36Sopenharmony_ci mcp->mb[6] = LSW(MSD(mreq->rcv_dma)); 539762306a36Sopenharmony_ci mcp->mb[7] = MSW(MSD(mreq->rcv_dma)); 539862306a36Sopenharmony_ci 539962306a36Sopenharmony_ci mcp->mb[10] = LSW(mreq->transfer_size); 540062306a36Sopenharmony_ci 540162306a36Sopenharmony_ci mcp->mb[14] = LSW(mreq->send_dma); 540262306a36Sopenharmony_ci mcp->mb[15] = MSW(mreq->send_dma); 540362306a36Sopenharmony_ci mcp->mb[20] = LSW(MSD(mreq->send_dma)); 540462306a36Sopenharmony_ci mcp->mb[21] = MSW(MSD(mreq->send_dma)); 540562306a36Sopenharmony_ci 540662306a36Sopenharmony_ci mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15| 540762306a36Sopenharmony_ci MBX_14|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0; 540862306a36Sopenharmony_ci if (IS_CNA_CAPABLE(ha)) 540962306a36Sopenharmony_ci mcp->out_mb |= MBX_2; 541062306a36Sopenharmony_ci 541162306a36Sopenharmony_ci mcp->in_mb = MBX_0; 541262306a36Sopenharmony_ci if (IS_CNA_CAPABLE(ha) || IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || 541362306a36Sopenharmony_ci IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) 541462306a36Sopenharmony_ci mcp->in_mb |= MBX_1; 541562306a36Sopenharmony_ci if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || 541662306a36Sopenharmony_ci IS_QLA28XX(ha)) 541762306a36Sopenharmony_ci mcp->in_mb |= MBX_3; 541862306a36Sopenharmony_ci 541962306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 542062306a36Sopenharmony_ci mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; 542162306a36Sopenharmony_ci mcp->buf_size = mreq->transfer_size; 542262306a36Sopenharmony_ci 542362306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 542462306a36Sopenharmony_ci 542562306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 542662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10fb, 542762306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x.\n", 542862306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1]); 542962306a36Sopenharmony_ci } else { 543062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10fc, 543162306a36Sopenharmony_ci "Done %s.\n", __func__); 543262306a36Sopenharmony_ci } 543362306a36Sopenharmony_ci 543462306a36Sopenharmony_ci /* Copy mailbox information */ 543562306a36Sopenharmony_ci memcpy(mresp, mcp->mb, 64); 543662306a36Sopenharmony_ci return rval; 543762306a36Sopenharmony_ci} 543862306a36Sopenharmony_ci 543962306a36Sopenharmony_ciint 544062306a36Sopenharmony_ciqla84xx_reset_chip(scsi_qla_host_t *vha, uint16_t enable_diagnostic) 544162306a36Sopenharmony_ci{ 544262306a36Sopenharmony_ci int rval; 544362306a36Sopenharmony_ci mbx_cmd_t mc; 544462306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 544562306a36Sopenharmony_ci 544662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10fd, 544762306a36Sopenharmony_ci "Entered %s enable_diag=%d.\n", __func__, enable_diagnostic); 544862306a36Sopenharmony_ci 544962306a36Sopenharmony_ci mcp->mb[0] = MBC_ISP84XX_RESET; 545062306a36Sopenharmony_ci mcp->mb[1] = enable_diagnostic; 545162306a36Sopenharmony_ci mcp->out_mb = MBX_1|MBX_0; 545262306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 545362306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 545462306a36Sopenharmony_ci mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; 545562306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 545662306a36Sopenharmony_ci 545762306a36Sopenharmony_ci if (rval != QLA_SUCCESS) 545862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10fe, "Failed=%x.\n", rval); 545962306a36Sopenharmony_ci else 546062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ff, 546162306a36Sopenharmony_ci "Done %s.\n", __func__); 546262306a36Sopenharmony_ci 546362306a36Sopenharmony_ci return rval; 546462306a36Sopenharmony_ci} 546562306a36Sopenharmony_ci 546662306a36Sopenharmony_ciint 546762306a36Sopenharmony_ciqla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data) 546862306a36Sopenharmony_ci{ 546962306a36Sopenharmony_ci int rval; 547062306a36Sopenharmony_ci mbx_cmd_t mc; 547162306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 547262306a36Sopenharmony_ci 547362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1100, 547462306a36Sopenharmony_ci "Entered %s.\n", __func__); 547562306a36Sopenharmony_ci 547662306a36Sopenharmony_ci if (!IS_FWI2_CAPABLE(vha->hw)) 547762306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 547862306a36Sopenharmony_ci 547962306a36Sopenharmony_ci mcp->mb[0] = MBC_WRITE_RAM_WORD_EXTENDED; 548062306a36Sopenharmony_ci mcp->mb[1] = LSW(risc_addr); 548162306a36Sopenharmony_ci mcp->mb[2] = LSW(data); 548262306a36Sopenharmony_ci mcp->mb[3] = MSW(data); 548362306a36Sopenharmony_ci mcp->mb[8] = MSW(risc_addr); 548462306a36Sopenharmony_ci mcp->out_mb = MBX_8|MBX_3|MBX_2|MBX_1|MBX_0; 548562306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 548662306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 548762306a36Sopenharmony_ci mcp->flags = 0; 548862306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 548962306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 549062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1101, 549162306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x.\n", 549262306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1]); 549362306a36Sopenharmony_ci } else { 549462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1102, 549562306a36Sopenharmony_ci "Done %s.\n", __func__); 549662306a36Sopenharmony_ci } 549762306a36Sopenharmony_ci 549862306a36Sopenharmony_ci return rval; 549962306a36Sopenharmony_ci} 550062306a36Sopenharmony_ci 550162306a36Sopenharmony_ciint 550262306a36Sopenharmony_ciqla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb) 550362306a36Sopenharmony_ci{ 550462306a36Sopenharmony_ci int rval; 550562306a36Sopenharmony_ci uint32_t stat, timer; 550662306a36Sopenharmony_ci uint16_t mb0 = 0; 550762306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 550862306a36Sopenharmony_ci struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; 550962306a36Sopenharmony_ci 551062306a36Sopenharmony_ci rval = QLA_SUCCESS; 551162306a36Sopenharmony_ci 551262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1103, 551362306a36Sopenharmony_ci "Entered %s.\n", __func__); 551462306a36Sopenharmony_ci 551562306a36Sopenharmony_ci clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); 551662306a36Sopenharmony_ci 551762306a36Sopenharmony_ci /* Write the MBC data to the registers */ 551862306a36Sopenharmony_ci wrt_reg_word(®->mailbox0, MBC_WRITE_MPI_REGISTER); 551962306a36Sopenharmony_ci wrt_reg_word(®->mailbox1, mb[0]); 552062306a36Sopenharmony_ci wrt_reg_word(®->mailbox2, mb[1]); 552162306a36Sopenharmony_ci wrt_reg_word(®->mailbox3, mb[2]); 552262306a36Sopenharmony_ci wrt_reg_word(®->mailbox4, mb[3]); 552362306a36Sopenharmony_ci 552462306a36Sopenharmony_ci wrt_reg_dword(®->hccr, HCCRX_SET_HOST_INT); 552562306a36Sopenharmony_ci 552662306a36Sopenharmony_ci /* Poll for MBC interrupt */ 552762306a36Sopenharmony_ci for (timer = 6000000; timer; timer--) { 552862306a36Sopenharmony_ci /* Check for pending interrupts. */ 552962306a36Sopenharmony_ci stat = rd_reg_dword(®->host_status); 553062306a36Sopenharmony_ci if (stat & HSRX_RISC_INT) { 553162306a36Sopenharmony_ci stat &= 0xff; 553262306a36Sopenharmony_ci 553362306a36Sopenharmony_ci if (stat == 0x1 || stat == 0x2 || 553462306a36Sopenharmony_ci stat == 0x10 || stat == 0x11) { 553562306a36Sopenharmony_ci set_bit(MBX_INTERRUPT, 553662306a36Sopenharmony_ci &ha->mbx_cmd_flags); 553762306a36Sopenharmony_ci mb0 = rd_reg_word(®->mailbox0); 553862306a36Sopenharmony_ci wrt_reg_dword(®->hccr, 553962306a36Sopenharmony_ci HCCRX_CLR_RISC_INT); 554062306a36Sopenharmony_ci rd_reg_dword(®->hccr); 554162306a36Sopenharmony_ci break; 554262306a36Sopenharmony_ci } 554362306a36Sopenharmony_ci } 554462306a36Sopenharmony_ci udelay(5); 554562306a36Sopenharmony_ci } 554662306a36Sopenharmony_ci 554762306a36Sopenharmony_ci if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) 554862306a36Sopenharmony_ci rval = mb0 & MBS_MASK; 554962306a36Sopenharmony_ci else 555062306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 555162306a36Sopenharmony_ci 555262306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 555362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1104, 555462306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mb[0]); 555562306a36Sopenharmony_ci } else { 555662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1105, 555762306a36Sopenharmony_ci "Done %s.\n", __func__); 555862306a36Sopenharmony_ci } 555962306a36Sopenharmony_ci 556062306a36Sopenharmony_ci return rval; 556162306a36Sopenharmony_ci} 556262306a36Sopenharmony_ci 556362306a36Sopenharmony_ci/* Set the specified data rate */ 556462306a36Sopenharmony_ciint 556562306a36Sopenharmony_ciqla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode) 556662306a36Sopenharmony_ci{ 556762306a36Sopenharmony_ci int rval; 556862306a36Sopenharmony_ci mbx_cmd_t mc; 556962306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 557062306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 557162306a36Sopenharmony_ci uint16_t val; 557262306a36Sopenharmony_ci 557362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1106, 557462306a36Sopenharmony_ci "Entered %s speed:0x%x mode:0x%x.\n", __func__, ha->set_data_rate, 557562306a36Sopenharmony_ci mode); 557662306a36Sopenharmony_ci 557762306a36Sopenharmony_ci if (!IS_FWI2_CAPABLE(ha)) 557862306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 557962306a36Sopenharmony_ci 558062306a36Sopenharmony_ci memset(mcp, 0, sizeof(*mcp)); 558162306a36Sopenharmony_ci switch (ha->set_data_rate) { 558262306a36Sopenharmony_ci case PORT_SPEED_AUTO: 558362306a36Sopenharmony_ci case PORT_SPEED_4GB: 558462306a36Sopenharmony_ci case PORT_SPEED_8GB: 558562306a36Sopenharmony_ci case PORT_SPEED_16GB: 558662306a36Sopenharmony_ci case PORT_SPEED_32GB: 558762306a36Sopenharmony_ci val = ha->set_data_rate; 558862306a36Sopenharmony_ci break; 558962306a36Sopenharmony_ci default: 559062306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1199, 559162306a36Sopenharmony_ci "Unrecognized speed setting:%d. Setting Autoneg\n", 559262306a36Sopenharmony_ci ha->set_data_rate); 559362306a36Sopenharmony_ci val = ha->set_data_rate = PORT_SPEED_AUTO; 559462306a36Sopenharmony_ci break; 559562306a36Sopenharmony_ci } 559662306a36Sopenharmony_ci 559762306a36Sopenharmony_ci mcp->mb[0] = MBC_DATA_RATE; 559862306a36Sopenharmony_ci mcp->mb[1] = mode; 559962306a36Sopenharmony_ci mcp->mb[2] = val; 560062306a36Sopenharmony_ci 560162306a36Sopenharmony_ci mcp->out_mb = MBX_2|MBX_1|MBX_0; 560262306a36Sopenharmony_ci mcp->in_mb = MBX_2|MBX_1|MBX_0; 560362306a36Sopenharmony_ci if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) 560462306a36Sopenharmony_ci mcp->in_mb |= MBX_4|MBX_3; 560562306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 560662306a36Sopenharmony_ci mcp->flags = 0; 560762306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 560862306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 560962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1107, 561062306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 561162306a36Sopenharmony_ci } else { 561262306a36Sopenharmony_ci if (mcp->mb[1] != 0x7) 561362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1179, 561462306a36Sopenharmony_ci "Speed set:0x%x\n", mcp->mb[1]); 561562306a36Sopenharmony_ci 561662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1108, 561762306a36Sopenharmony_ci "Done %s.\n", __func__); 561862306a36Sopenharmony_ci } 561962306a36Sopenharmony_ci 562062306a36Sopenharmony_ci return rval; 562162306a36Sopenharmony_ci} 562262306a36Sopenharmony_ci 562362306a36Sopenharmony_ciint 562462306a36Sopenharmony_ciqla2x00_get_data_rate(scsi_qla_host_t *vha) 562562306a36Sopenharmony_ci{ 562662306a36Sopenharmony_ci int rval; 562762306a36Sopenharmony_ci mbx_cmd_t mc; 562862306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 562962306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 563062306a36Sopenharmony_ci 563162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1106, 563262306a36Sopenharmony_ci "Entered %s.\n", __func__); 563362306a36Sopenharmony_ci 563462306a36Sopenharmony_ci if (!IS_FWI2_CAPABLE(ha)) 563562306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 563662306a36Sopenharmony_ci 563762306a36Sopenharmony_ci mcp->mb[0] = MBC_DATA_RATE; 563862306a36Sopenharmony_ci mcp->mb[1] = QLA_GET_DATA_RATE; 563962306a36Sopenharmony_ci mcp->out_mb = MBX_1|MBX_0; 564062306a36Sopenharmony_ci mcp->in_mb = MBX_2|MBX_1|MBX_0; 564162306a36Sopenharmony_ci if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) 564262306a36Sopenharmony_ci mcp->in_mb |= MBX_4|MBX_3; 564362306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 564462306a36Sopenharmony_ci mcp->flags = 0; 564562306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 564662306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 564762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1107, 564862306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 564962306a36Sopenharmony_ci } else { 565062306a36Sopenharmony_ci if (mcp->mb[1] != 0x7) 565162306a36Sopenharmony_ci ha->link_data_rate = mcp->mb[1]; 565262306a36Sopenharmony_ci 565362306a36Sopenharmony_ci if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { 565462306a36Sopenharmony_ci if (mcp->mb[4] & BIT_0) 565562306a36Sopenharmony_ci ql_log(ql_log_info, vha, 0x11a2, 565662306a36Sopenharmony_ci "FEC=enabled (data rate).\n"); 565762306a36Sopenharmony_ci } 565862306a36Sopenharmony_ci 565962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1108, 566062306a36Sopenharmony_ci "Done %s.\n", __func__); 566162306a36Sopenharmony_ci if (mcp->mb[1] != 0x7) 566262306a36Sopenharmony_ci ha->link_data_rate = mcp->mb[1]; 566362306a36Sopenharmony_ci } 566462306a36Sopenharmony_ci 566562306a36Sopenharmony_ci return rval; 566662306a36Sopenharmony_ci} 566762306a36Sopenharmony_ci 566862306a36Sopenharmony_ciint 566962306a36Sopenharmony_ciqla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb) 567062306a36Sopenharmony_ci{ 567162306a36Sopenharmony_ci int rval; 567262306a36Sopenharmony_ci mbx_cmd_t mc; 567362306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 567462306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 567562306a36Sopenharmony_ci 567662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1109, 567762306a36Sopenharmony_ci "Entered %s.\n", __func__); 567862306a36Sopenharmony_ci 567962306a36Sopenharmony_ci if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && !IS_QLA8044(ha) && 568062306a36Sopenharmony_ci !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 568162306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 568262306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_PORT_CONFIG; 568362306a36Sopenharmony_ci mcp->out_mb = MBX_0; 568462306a36Sopenharmony_ci mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 568562306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 568662306a36Sopenharmony_ci mcp->flags = 0; 568762306a36Sopenharmony_ci 568862306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 568962306a36Sopenharmony_ci 569062306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 569162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x110a, 569262306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 569362306a36Sopenharmony_ci } else { 569462306a36Sopenharmony_ci /* Copy all bits to preserve original value */ 569562306a36Sopenharmony_ci memcpy(mb, &mcp->mb[1], sizeof(uint16_t) * 4); 569662306a36Sopenharmony_ci 569762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110b, 569862306a36Sopenharmony_ci "Done %s.\n", __func__); 569962306a36Sopenharmony_ci } 570062306a36Sopenharmony_ci return rval; 570162306a36Sopenharmony_ci} 570262306a36Sopenharmony_ci 570362306a36Sopenharmony_ciint 570462306a36Sopenharmony_ciqla81xx_set_port_config(scsi_qla_host_t *vha, uint16_t *mb) 570562306a36Sopenharmony_ci{ 570662306a36Sopenharmony_ci int rval; 570762306a36Sopenharmony_ci mbx_cmd_t mc; 570862306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 570962306a36Sopenharmony_ci 571062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110c, 571162306a36Sopenharmony_ci "Entered %s.\n", __func__); 571262306a36Sopenharmony_ci 571362306a36Sopenharmony_ci mcp->mb[0] = MBC_SET_PORT_CONFIG; 571462306a36Sopenharmony_ci /* Copy all bits to preserve original setting */ 571562306a36Sopenharmony_ci memcpy(&mcp->mb[1], mb, sizeof(uint16_t) * 4); 571662306a36Sopenharmony_ci mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 571762306a36Sopenharmony_ci mcp->in_mb = MBX_0; 571862306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 571962306a36Sopenharmony_ci mcp->flags = 0; 572062306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 572162306a36Sopenharmony_ci 572262306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 572362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x110d, 572462306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 572562306a36Sopenharmony_ci } else 572662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110e, 572762306a36Sopenharmony_ci "Done %s.\n", __func__); 572862306a36Sopenharmony_ci 572962306a36Sopenharmony_ci return rval; 573062306a36Sopenharmony_ci} 573162306a36Sopenharmony_ci 573262306a36Sopenharmony_ci 573362306a36Sopenharmony_ciint 573462306a36Sopenharmony_ciqla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority, 573562306a36Sopenharmony_ci uint16_t *mb) 573662306a36Sopenharmony_ci{ 573762306a36Sopenharmony_ci int rval; 573862306a36Sopenharmony_ci mbx_cmd_t mc; 573962306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 574062306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 574162306a36Sopenharmony_ci 574262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110f, 574362306a36Sopenharmony_ci "Entered %s.\n", __func__); 574462306a36Sopenharmony_ci 574562306a36Sopenharmony_ci if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha)) 574662306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 574762306a36Sopenharmony_ci 574862306a36Sopenharmony_ci mcp->mb[0] = MBC_PORT_PARAMS; 574962306a36Sopenharmony_ci mcp->mb[1] = loop_id; 575062306a36Sopenharmony_ci if (ha->flags.fcp_prio_enabled) 575162306a36Sopenharmony_ci mcp->mb[2] = BIT_1; 575262306a36Sopenharmony_ci else 575362306a36Sopenharmony_ci mcp->mb[2] = BIT_2; 575462306a36Sopenharmony_ci mcp->mb[4] = priority & 0xf; 575562306a36Sopenharmony_ci mcp->mb[9] = vha->vp_idx; 575662306a36Sopenharmony_ci mcp->out_mb = MBX_9|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 575762306a36Sopenharmony_ci mcp->in_mb = MBX_4|MBX_3|MBX_1|MBX_0; 575862306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 575962306a36Sopenharmony_ci mcp->flags = 0; 576062306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 576162306a36Sopenharmony_ci if (mb != NULL) { 576262306a36Sopenharmony_ci mb[0] = mcp->mb[0]; 576362306a36Sopenharmony_ci mb[1] = mcp->mb[1]; 576462306a36Sopenharmony_ci mb[3] = mcp->mb[3]; 576562306a36Sopenharmony_ci mb[4] = mcp->mb[4]; 576662306a36Sopenharmony_ci } 576762306a36Sopenharmony_ci 576862306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 576962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10cd, "Failed=%x.\n", rval); 577062306a36Sopenharmony_ci } else { 577162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10cc, 577262306a36Sopenharmony_ci "Done %s.\n", __func__); 577362306a36Sopenharmony_ci } 577462306a36Sopenharmony_ci 577562306a36Sopenharmony_ci return rval; 577662306a36Sopenharmony_ci} 577762306a36Sopenharmony_ci 577862306a36Sopenharmony_ciint 577962306a36Sopenharmony_ciqla2x00_get_thermal_temp(scsi_qla_host_t *vha, uint16_t *temp) 578062306a36Sopenharmony_ci{ 578162306a36Sopenharmony_ci int rval = QLA_FUNCTION_FAILED; 578262306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 578362306a36Sopenharmony_ci uint8_t byte; 578462306a36Sopenharmony_ci 578562306a36Sopenharmony_ci if (!IS_FWI2_CAPABLE(ha) || IS_QLA24XX_TYPE(ha) || IS_QLA81XX(ha)) { 578662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1150, 578762306a36Sopenharmony_ci "Thermal not supported by this card.\n"); 578862306a36Sopenharmony_ci return rval; 578962306a36Sopenharmony_ci } 579062306a36Sopenharmony_ci 579162306a36Sopenharmony_ci if (IS_QLA25XX(ha)) { 579262306a36Sopenharmony_ci if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && 579362306a36Sopenharmony_ci ha->pdev->subsystem_device == 0x0175) { 579462306a36Sopenharmony_ci rval = qla2x00_read_sfp(vha, 0, &byte, 579562306a36Sopenharmony_ci 0x98, 0x1, 1, BIT_13|BIT_0); 579662306a36Sopenharmony_ci *temp = byte; 579762306a36Sopenharmony_ci return rval; 579862306a36Sopenharmony_ci } 579962306a36Sopenharmony_ci if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP && 580062306a36Sopenharmony_ci ha->pdev->subsystem_device == 0x338e) { 580162306a36Sopenharmony_ci rval = qla2x00_read_sfp(vha, 0, &byte, 580262306a36Sopenharmony_ci 0x98, 0x1, 1, BIT_15|BIT_14|BIT_0); 580362306a36Sopenharmony_ci *temp = byte; 580462306a36Sopenharmony_ci return rval; 580562306a36Sopenharmony_ci } 580662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10c9, 580762306a36Sopenharmony_ci "Thermal not supported by this card.\n"); 580862306a36Sopenharmony_ci return rval; 580962306a36Sopenharmony_ci } 581062306a36Sopenharmony_ci 581162306a36Sopenharmony_ci if (IS_QLA82XX(ha)) { 581262306a36Sopenharmony_ci *temp = qla82xx_read_temperature(vha); 581362306a36Sopenharmony_ci rval = QLA_SUCCESS; 581462306a36Sopenharmony_ci return rval; 581562306a36Sopenharmony_ci } else if (IS_QLA8044(ha)) { 581662306a36Sopenharmony_ci *temp = qla8044_read_temperature(vha); 581762306a36Sopenharmony_ci rval = QLA_SUCCESS; 581862306a36Sopenharmony_ci return rval; 581962306a36Sopenharmony_ci } 582062306a36Sopenharmony_ci 582162306a36Sopenharmony_ci rval = qla2x00_read_asic_temperature(vha, temp); 582262306a36Sopenharmony_ci return rval; 582362306a36Sopenharmony_ci} 582462306a36Sopenharmony_ci 582562306a36Sopenharmony_ciint 582662306a36Sopenharmony_ciqla82xx_mbx_intr_enable(scsi_qla_host_t *vha) 582762306a36Sopenharmony_ci{ 582862306a36Sopenharmony_ci int rval; 582962306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 583062306a36Sopenharmony_ci mbx_cmd_t mc; 583162306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 583262306a36Sopenharmony_ci 583362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1017, 583462306a36Sopenharmony_ci "Entered %s.\n", __func__); 583562306a36Sopenharmony_ci 583662306a36Sopenharmony_ci if (!IS_FWI2_CAPABLE(ha)) 583762306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 583862306a36Sopenharmony_ci 583962306a36Sopenharmony_ci memset(mcp, 0, sizeof(mbx_cmd_t)); 584062306a36Sopenharmony_ci mcp->mb[0] = MBC_TOGGLE_INTERRUPT; 584162306a36Sopenharmony_ci mcp->mb[1] = 1; 584262306a36Sopenharmony_ci 584362306a36Sopenharmony_ci mcp->out_mb = MBX_1|MBX_0; 584462306a36Sopenharmony_ci mcp->in_mb = MBX_0; 584562306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 584662306a36Sopenharmony_ci mcp->flags = 0; 584762306a36Sopenharmony_ci 584862306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 584962306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 585062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1016, 585162306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 585262306a36Sopenharmony_ci } else { 585362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x100e, 585462306a36Sopenharmony_ci "Done %s.\n", __func__); 585562306a36Sopenharmony_ci } 585662306a36Sopenharmony_ci 585762306a36Sopenharmony_ci return rval; 585862306a36Sopenharmony_ci} 585962306a36Sopenharmony_ci 586062306a36Sopenharmony_ciint 586162306a36Sopenharmony_ciqla82xx_mbx_intr_disable(scsi_qla_host_t *vha) 586262306a36Sopenharmony_ci{ 586362306a36Sopenharmony_ci int rval; 586462306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 586562306a36Sopenharmony_ci mbx_cmd_t mc; 586662306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 586762306a36Sopenharmony_ci 586862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x100d, 586962306a36Sopenharmony_ci "Entered %s.\n", __func__); 587062306a36Sopenharmony_ci 587162306a36Sopenharmony_ci if (!IS_P3P_TYPE(ha)) 587262306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 587362306a36Sopenharmony_ci 587462306a36Sopenharmony_ci memset(mcp, 0, sizeof(mbx_cmd_t)); 587562306a36Sopenharmony_ci mcp->mb[0] = MBC_TOGGLE_INTERRUPT; 587662306a36Sopenharmony_ci mcp->mb[1] = 0; 587762306a36Sopenharmony_ci 587862306a36Sopenharmony_ci mcp->out_mb = MBX_1|MBX_0; 587962306a36Sopenharmony_ci mcp->in_mb = MBX_0; 588062306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 588162306a36Sopenharmony_ci mcp->flags = 0; 588262306a36Sopenharmony_ci 588362306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 588462306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 588562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x100c, 588662306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 588762306a36Sopenharmony_ci } else { 588862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x100b, 588962306a36Sopenharmony_ci "Done %s.\n", __func__); 589062306a36Sopenharmony_ci } 589162306a36Sopenharmony_ci 589262306a36Sopenharmony_ci return rval; 589362306a36Sopenharmony_ci} 589462306a36Sopenharmony_ci 589562306a36Sopenharmony_ciint 589662306a36Sopenharmony_ciqla82xx_md_get_template_size(scsi_qla_host_t *vha) 589762306a36Sopenharmony_ci{ 589862306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 589962306a36Sopenharmony_ci mbx_cmd_t mc; 590062306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 590162306a36Sopenharmony_ci int rval = QLA_FUNCTION_FAILED; 590262306a36Sopenharmony_ci 590362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x111f, 590462306a36Sopenharmony_ci "Entered %s.\n", __func__); 590562306a36Sopenharmony_ci 590662306a36Sopenharmony_ci memset(mcp->mb, 0 , sizeof(mcp->mb)); 590762306a36Sopenharmony_ci mcp->mb[0] = LSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE); 590862306a36Sopenharmony_ci mcp->mb[1] = MSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE); 590962306a36Sopenharmony_ci mcp->mb[2] = LSW(RQST_TMPLT_SIZE); 591062306a36Sopenharmony_ci mcp->mb[3] = MSW(RQST_TMPLT_SIZE); 591162306a36Sopenharmony_ci 591262306a36Sopenharmony_ci mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; 591362306a36Sopenharmony_ci mcp->in_mb = MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8| 591462306a36Sopenharmony_ci MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 591562306a36Sopenharmony_ci 591662306a36Sopenharmony_ci mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; 591762306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 591862306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 591962306a36Sopenharmony_ci 592062306a36Sopenharmony_ci /* Always copy back return mailbox values. */ 592162306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 592262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1120, 592362306a36Sopenharmony_ci "mailbox command FAILED=0x%x, subcode=%x.\n", 592462306a36Sopenharmony_ci (mcp->mb[1] << 16) | mcp->mb[0], 592562306a36Sopenharmony_ci (mcp->mb[3] << 16) | mcp->mb[2]); 592662306a36Sopenharmony_ci } else { 592762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1121, 592862306a36Sopenharmony_ci "Done %s.\n", __func__); 592962306a36Sopenharmony_ci ha->md_template_size = ((mcp->mb[3] << 16) | mcp->mb[2]); 593062306a36Sopenharmony_ci if (!ha->md_template_size) { 593162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1122, 593262306a36Sopenharmony_ci "Null template size obtained.\n"); 593362306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 593462306a36Sopenharmony_ci } 593562306a36Sopenharmony_ci } 593662306a36Sopenharmony_ci return rval; 593762306a36Sopenharmony_ci} 593862306a36Sopenharmony_ci 593962306a36Sopenharmony_ciint 594062306a36Sopenharmony_ciqla82xx_md_get_template(scsi_qla_host_t *vha) 594162306a36Sopenharmony_ci{ 594262306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 594362306a36Sopenharmony_ci mbx_cmd_t mc; 594462306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 594562306a36Sopenharmony_ci int rval = QLA_FUNCTION_FAILED; 594662306a36Sopenharmony_ci 594762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1123, 594862306a36Sopenharmony_ci "Entered %s.\n", __func__); 594962306a36Sopenharmony_ci 595062306a36Sopenharmony_ci ha->md_tmplt_hdr = dma_alloc_coherent(&ha->pdev->dev, 595162306a36Sopenharmony_ci ha->md_template_size, &ha->md_tmplt_hdr_dma, GFP_KERNEL); 595262306a36Sopenharmony_ci if (!ha->md_tmplt_hdr) { 595362306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1124, 595462306a36Sopenharmony_ci "Unable to allocate memory for Minidump template.\n"); 595562306a36Sopenharmony_ci return rval; 595662306a36Sopenharmony_ci } 595762306a36Sopenharmony_ci 595862306a36Sopenharmony_ci memset(mcp->mb, 0 , sizeof(mcp->mb)); 595962306a36Sopenharmony_ci mcp->mb[0] = LSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE); 596062306a36Sopenharmony_ci mcp->mb[1] = MSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE); 596162306a36Sopenharmony_ci mcp->mb[2] = LSW(RQST_TMPLT); 596262306a36Sopenharmony_ci mcp->mb[3] = MSW(RQST_TMPLT); 596362306a36Sopenharmony_ci mcp->mb[4] = LSW(LSD(ha->md_tmplt_hdr_dma)); 596462306a36Sopenharmony_ci mcp->mb[5] = MSW(LSD(ha->md_tmplt_hdr_dma)); 596562306a36Sopenharmony_ci mcp->mb[6] = LSW(MSD(ha->md_tmplt_hdr_dma)); 596662306a36Sopenharmony_ci mcp->mb[7] = MSW(MSD(ha->md_tmplt_hdr_dma)); 596762306a36Sopenharmony_ci mcp->mb[8] = LSW(ha->md_template_size); 596862306a36Sopenharmony_ci mcp->mb[9] = MSW(ha->md_template_size); 596962306a36Sopenharmony_ci 597062306a36Sopenharmony_ci mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; 597162306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 597262306a36Sopenharmony_ci mcp->out_mb = MBX_11|MBX_10|MBX_9|MBX_8| 597362306a36Sopenharmony_ci MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 597462306a36Sopenharmony_ci mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0; 597562306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 597662306a36Sopenharmony_ci 597762306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 597862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1125, 597962306a36Sopenharmony_ci "mailbox command FAILED=0x%x, subcode=%x.\n", 598062306a36Sopenharmony_ci ((mcp->mb[1] << 16) | mcp->mb[0]), 598162306a36Sopenharmony_ci ((mcp->mb[3] << 16) | mcp->mb[2])); 598262306a36Sopenharmony_ci } else 598362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1126, 598462306a36Sopenharmony_ci "Done %s.\n", __func__); 598562306a36Sopenharmony_ci return rval; 598662306a36Sopenharmony_ci} 598762306a36Sopenharmony_ci 598862306a36Sopenharmony_ciint 598962306a36Sopenharmony_ciqla8044_md_get_template(scsi_qla_host_t *vha) 599062306a36Sopenharmony_ci{ 599162306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 599262306a36Sopenharmony_ci mbx_cmd_t mc; 599362306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 599462306a36Sopenharmony_ci int rval = QLA_FUNCTION_FAILED; 599562306a36Sopenharmony_ci int offset = 0, size = MINIDUMP_SIZE_36K; 599662306a36Sopenharmony_ci 599762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0xb11f, 599862306a36Sopenharmony_ci "Entered %s.\n", __func__); 599962306a36Sopenharmony_ci 600062306a36Sopenharmony_ci ha->md_tmplt_hdr = dma_alloc_coherent(&ha->pdev->dev, 600162306a36Sopenharmony_ci ha->md_template_size, &ha->md_tmplt_hdr_dma, GFP_KERNEL); 600262306a36Sopenharmony_ci if (!ha->md_tmplt_hdr) { 600362306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0xb11b, 600462306a36Sopenharmony_ci "Unable to allocate memory for Minidump template.\n"); 600562306a36Sopenharmony_ci return rval; 600662306a36Sopenharmony_ci } 600762306a36Sopenharmony_ci 600862306a36Sopenharmony_ci memset(mcp->mb, 0 , sizeof(mcp->mb)); 600962306a36Sopenharmony_ci while (offset < ha->md_template_size) { 601062306a36Sopenharmony_ci mcp->mb[0] = LSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE); 601162306a36Sopenharmony_ci mcp->mb[1] = MSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE); 601262306a36Sopenharmony_ci mcp->mb[2] = LSW(RQST_TMPLT); 601362306a36Sopenharmony_ci mcp->mb[3] = MSW(RQST_TMPLT); 601462306a36Sopenharmony_ci mcp->mb[4] = LSW(LSD(ha->md_tmplt_hdr_dma + offset)); 601562306a36Sopenharmony_ci mcp->mb[5] = MSW(LSD(ha->md_tmplt_hdr_dma + offset)); 601662306a36Sopenharmony_ci mcp->mb[6] = LSW(MSD(ha->md_tmplt_hdr_dma + offset)); 601762306a36Sopenharmony_ci mcp->mb[7] = MSW(MSD(ha->md_tmplt_hdr_dma + offset)); 601862306a36Sopenharmony_ci mcp->mb[8] = LSW(size); 601962306a36Sopenharmony_ci mcp->mb[9] = MSW(size); 602062306a36Sopenharmony_ci mcp->mb[10] = offset & 0x0000FFFF; 602162306a36Sopenharmony_ci mcp->mb[11] = offset & 0xFFFF0000; 602262306a36Sopenharmony_ci mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; 602362306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 602462306a36Sopenharmony_ci mcp->out_mb = MBX_11|MBX_10|MBX_9|MBX_8| 602562306a36Sopenharmony_ci MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 602662306a36Sopenharmony_ci mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0; 602762306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 602862306a36Sopenharmony_ci 602962306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 603062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0xb11c, 603162306a36Sopenharmony_ci "mailbox command FAILED=0x%x, subcode=%x.\n", 603262306a36Sopenharmony_ci ((mcp->mb[1] << 16) | mcp->mb[0]), 603362306a36Sopenharmony_ci ((mcp->mb[3] << 16) | mcp->mb[2])); 603462306a36Sopenharmony_ci return rval; 603562306a36Sopenharmony_ci } else 603662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0xb11d, 603762306a36Sopenharmony_ci "Done %s.\n", __func__); 603862306a36Sopenharmony_ci offset = offset + size; 603962306a36Sopenharmony_ci } 604062306a36Sopenharmony_ci return rval; 604162306a36Sopenharmony_ci} 604262306a36Sopenharmony_ci 604362306a36Sopenharmony_ciint 604462306a36Sopenharmony_ciqla81xx_set_led_config(scsi_qla_host_t *vha, uint16_t *led_cfg) 604562306a36Sopenharmony_ci{ 604662306a36Sopenharmony_ci int rval; 604762306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 604862306a36Sopenharmony_ci mbx_cmd_t mc; 604962306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 605062306a36Sopenharmony_ci 605162306a36Sopenharmony_ci if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) 605262306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 605362306a36Sopenharmony_ci 605462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1133, 605562306a36Sopenharmony_ci "Entered %s.\n", __func__); 605662306a36Sopenharmony_ci 605762306a36Sopenharmony_ci memset(mcp, 0, sizeof(mbx_cmd_t)); 605862306a36Sopenharmony_ci mcp->mb[0] = MBC_SET_LED_CONFIG; 605962306a36Sopenharmony_ci mcp->mb[1] = led_cfg[0]; 606062306a36Sopenharmony_ci mcp->mb[2] = led_cfg[1]; 606162306a36Sopenharmony_ci if (IS_QLA8031(ha)) { 606262306a36Sopenharmony_ci mcp->mb[3] = led_cfg[2]; 606362306a36Sopenharmony_ci mcp->mb[4] = led_cfg[3]; 606462306a36Sopenharmony_ci mcp->mb[5] = led_cfg[4]; 606562306a36Sopenharmony_ci mcp->mb[6] = led_cfg[5]; 606662306a36Sopenharmony_ci } 606762306a36Sopenharmony_ci 606862306a36Sopenharmony_ci mcp->out_mb = MBX_2|MBX_1|MBX_0; 606962306a36Sopenharmony_ci if (IS_QLA8031(ha)) 607062306a36Sopenharmony_ci mcp->out_mb |= MBX_6|MBX_5|MBX_4|MBX_3; 607162306a36Sopenharmony_ci mcp->in_mb = MBX_0; 607262306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 607362306a36Sopenharmony_ci mcp->flags = 0; 607462306a36Sopenharmony_ci 607562306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 607662306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 607762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1134, 607862306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 607962306a36Sopenharmony_ci } else { 608062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1135, 608162306a36Sopenharmony_ci "Done %s.\n", __func__); 608262306a36Sopenharmony_ci } 608362306a36Sopenharmony_ci 608462306a36Sopenharmony_ci return rval; 608562306a36Sopenharmony_ci} 608662306a36Sopenharmony_ci 608762306a36Sopenharmony_ciint 608862306a36Sopenharmony_ciqla81xx_get_led_config(scsi_qla_host_t *vha, uint16_t *led_cfg) 608962306a36Sopenharmony_ci{ 609062306a36Sopenharmony_ci int rval; 609162306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 609262306a36Sopenharmony_ci mbx_cmd_t mc; 609362306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 609462306a36Sopenharmony_ci 609562306a36Sopenharmony_ci if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) 609662306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 609762306a36Sopenharmony_ci 609862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1136, 609962306a36Sopenharmony_ci "Entered %s.\n", __func__); 610062306a36Sopenharmony_ci 610162306a36Sopenharmony_ci memset(mcp, 0, sizeof(mbx_cmd_t)); 610262306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_LED_CONFIG; 610362306a36Sopenharmony_ci 610462306a36Sopenharmony_ci mcp->out_mb = MBX_0; 610562306a36Sopenharmony_ci mcp->in_mb = MBX_2|MBX_1|MBX_0; 610662306a36Sopenharmony_ci if (IS_QLA8031(ha)) 610762306a36Sopenharmony_ci mcp->in_mb |= MBX_6|MBX_5|MBX_4|MBX_3; 610862306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 610962306a36Sopenharmony_ci mcp->flags = 0; 611062306a36Sopenharmony_ci 611162306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 611262306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 611362306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1137, 611462306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 611562306a36Sopenharmony_ci } else { 611662306a36Sopenharmony_ci led_cfg[0] = mcp->mb[1]; 611762306a36Sopenharmony_ci led_cfg[1] = mcp->mb[2]; 611862306a36Sopenharmony_ci if (IS_QLA8031(ha)) { 611962306a36Sopenharmony_ci led_cfg[2] = mcp->mb[3]; 612062306a36Sopenharmony_ci led_cfg[3] = mcp->mb[4]; 612162306a36Sopenharmony_ci led_cfg[4] = mcp->mb[5]; 612262306a36Sopenharmony_ci led_cfg[5] = mcp->mb[6]; 612362306a36Sopenharmony_ci } 612462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1138, 612562306a36Sopenharmony_ci "Done %s.\n", __func__); 612662306a36Sopenharmony_ci } 612762306a36Sopenharmony_ci 612862306a36Sopenharmony_ci return rval; 612962306a36Sopenharmony_ci} 613062306a36Sopenharmony_ci 613162306a36Sopenharmony_ciint 613262306a36Sopenharmony_ciqla82xx_mbx_beacon_ctl(scsi_qla_host_t *vha, int enable) 613362306a36Sopenharmony_ci{ 613462306a36Sopenharmony_ci int rval; 613562306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 613662306a36Sopenharmony_ci mbx_cmd_t mc; 613762306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 613862306a36Sopenharmony_ci 613962306a36Sopenharmony_ci if (!IS_P3P_TYPE(ha)) 614062306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 614162306a36Sopenharmony_ci 614262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1127, 614362306a36Sopenharmony_ci "Entered %s.\n", __func__); 614462306a36Sopenharmony_ci 614562306a36Sopenharmony_ci memset(mcp, 0, sizeof(mbx_cmd_t)); 614662306a36Sopenharmony_ci mcp->mb[0] = MBC_SET_LED_CONFIG; 614762306a36Sopenharmony_ci if (enable) 614862306a36Sopenharmony_ci mcp->mb[7] = 0xE; 614962306a36Sopenharmony_ci else 615062306a36Sopenharmony_ci mcp->mb[7] = 0xD; 615162306a36Sopenharmony_ci 615262306a36Sopenharmony_ci mcp->out_mb = MBX_7|MBX_0; 615362306a36Sopenharmony_ci mcp->in_mb = MBX_0; 615462306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 615562306a36Sopenharmony_ci mcp->flags = 0; 615662306a36Sopenharmony_ci 615762306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 615862306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 615962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1128, 616062306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 616162306a36Sopenharmony_ci } else { 616262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1129, 616362306a36Sopenharmony_ci "Done %s.\n", __func__); 616462306a36Sopenharmony_ci } 616562306a36Sopenharmony_ci 616662306a36Sopenharmony_ci return rval; 616762306a36Sopenharmony_ci} 616862306a36Sopenharmony_ci 616962306a36Sopenharmony_ciint 617062306a36Sopenharmony_ciqla83xx_wr_reg(scsi_qla_host_t *vha, uint32_t reg, uint32_t data) 617162306a36Sopenharmony_ci{ 617262306a36Sopenharmony_ci int rval; 617362306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 617462306a36Sopenharmony_ci mbx_cmd_t mc; 617562306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 617662306a36Sopenharmony_ci 617762306a36Sopenharmony_ci if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 617862306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 617962306a36Sopenharmony_ci 618062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1130, 618162306a36Sopenharmony_ci "Entered %s.\n", __func__); 618262306a36Sopenharmony_ci 618362306a36Sopenharmony_ci mcp->mb[0] = MBC_WRITE_REMOTE_REG; 618462306a36Sopenharmony_ci mcp->mb[1] = LSW(reg); 618562306a36Sopenharmony_ci mcp->mb[2] = MSW(reg); 618662306a36Sopenharmony_ci mcp->mb[3] = LSW(data); 618762306a36Sopenharmony_ci mcp->mb[4] = MSW(data); 618862306a36Sopenharmony_ci mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 618962306a36Sopenharmony_ci 619062306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 619162306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 619262306a36Sopenharmony_ci mcp->flags = 0; 619362306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 619462306a36Sopenharmony_ci 619562306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 619662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1131, 619762306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 619862306a36Sopenharmony_ci } else { 619962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1132, 620062306a36Sopenharmony_ci "Done %s.\n", __func__); 620162306a36Sopenharmony_ci } 620262306a36Sopenharmony_ci 620362306a36Sopenharmony_ci return rval; 620462306a36Sopenharmony_ci} 620562306a36Sopenharmony_ci 620662306a36Sopenharmony_ciint 620762306a36Sopenharmony_ciqla2x00_port_logout(scsi_qla_host_t *vha, struct fc_port *fcport) 620862306a36Sopenharmony_ci{ 620962306a36Sopenharmony_ci int rval; 621062306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 621162306a36Sopenharmony_ci mbx_cmd_t mc; 621262306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 621362306a36Sopenharmony_ci 621462306a36Sopenharmony_ci if (IS_QLA2100(ha) || IS_QLA2200(ha)) { 621562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x113b, 621662306a36Sopenharmony_ci "Implicit LOGO Unsupported.\n"); 621762306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 621862306a36Sopenharmony_ci } 621962306a36Sopenharmony_ci 622062306a36Sopenharmony_ci 622162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x113c, 622262306a36Sopenharmony_ci "Entering %s.\n", __func__); 622362306a36Sopenharmony_ci 622462306a36Sopenharmony_ci /* Perform Implicit LOGO. */ 622562306a36Sopenharmony_ci mcp->mb[0] = MBC_PORT_LOGOUT; 622662306a36Sopenharmony_ci mcp->mb[1] = fcport->loop_id; 622762306a36Sopenharmony_ci mcp->mb[10] = BIT_15; 622862306a36Sopenharmony_ci mcp->out_mb = MBX_10|MBX_1|MBX_0; 622962306a36Sopenharmony_ci mcp->in_mb = MBX_0; 623062306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 623162306a36Sopenharmony_ci mcp->flags = 0; 623262306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 623362306a36Sopenharmony_ci if (rval != QLA_SUCCESS) 623462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x113d, 623562306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 623662306a36Sopenharmony_ci else 623762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x113e, 623862306a36Sopenharmony_ci "Done %s.\n", __func__); 623962306a36Sopenharmony_ci 624062306a36Sopenharmony_ci return rval; 624162306a36Sopenharmony_ci} 624262306a36Sopenharmony_ci 624362306a36Sopenharmony_ciint 624462306a36Sopenharmony_ciqla83xx_rd_reg(scsi_qla_host_t *vha, uint32_t reg, uint32_t *data) 624562306a36Sopenharmony_ci{ 624662306a36Sopenharmony_ci int rval; 624762306a36Sopenharmony_ci mbx_cmd_t mc; 624862306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 624962306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 625062306a36Sopenharmony_ci unsigned long retry_max_time = jiffies + (2 * HZ); 625162306a36Sopenharmony_ci 625262306a36Sopenharmony_ci if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 625362306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 625462306a36Sopenharmony_ci 625562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x114b, "Entered %s.\n", __func__); 625662306a36Sopenharmony_ci 625762306a36Sopenharmony_ciretry_rd_reg: 625862306a36Sopenharmony_ci mcp->mb[0] = MBC_READ_REMOTE_REG; 625962306a36Sopenharmony_ci mcp->mb[1] = LSW(reg); 626062306a36Sopenharmony_ci mcp->mb[2] = MSW(reg); 626162306a36Sopenharmony_ci mcp->out_mb = MBX_2|MBX_1|MBX_0; 626262306a36Sopenharmony_ci mcp->in_mb = MBX_4|MBX_3|MBX_1|MBX_0; 626362306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 626462306a36Sopenharmony_ci mcp->flags = 0; 626562306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 626662306a36Sopenharmony_ci 626762306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 626862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x114c, 626962306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x.\n", 627062306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1]); 627162306a36Sopenharmony_ci } else { 627262306a36Sopenharmony_ci *data = (mcp->mb[3] | (mcp->mb[4] << 16)); 627362306a36Sopenharmony_ci if (*data == QLA8XXX_BAD_VALUE) { 627462306a36Sopenharmony_ci /* 627562306a36Sopenharmony_ci * During soft-reset CAMRAM register reads might 627662306a36Sopenharmony_ci * return 0xbad0bad0. So retry for MAX of 2 sec 627762306a36Sopenharmony_ci * while reading camram registers. 627862306a36Sopenharmony_ci */ 627962306a36Sopenharmony_ci if (time_after(jiffies, retry_max_time)) { 628062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1141, 628162306a36Sopenharmony_ci "Failure to read CAMRAM register. " 628262306a36Sopenharmony_ci "data=0x%x.\n", *data); 628362306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 628462306a36Sopenharmony_ci } 628562306a36Sopenharmony_ci msleep(100); 628662306a36Sopenharmony_ci goto retry_rd_reg; 628762306a36Sopenharmony_ci } 628862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1142, "Done %s.\n", __func__); 628962306a36Sopenharmony_ci } 629062306a36Sopenharmony_ci 629162306a36Sopenharmony_ci return rval; 629262306a36Sopenharmony_ci} 629362306a36Sopenharmony_ci 629462306a36Sopenharmony_ciint 629562306a36Sopenharmony_ciqla83xx_restart_nic_firmware(scsi_qla_host_t *vha) 629662306a36Sopenharmony_ci{ 629762306a36Sopenharmony_ci int rval; 629862306a36Sopenharmony_ci mbx_cmd_t mc; 629962306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 630062306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 630162306a36Sopenharmony_ci 630262306a36Sopenharmony_ci if (!IS_QLA83XX(ha)) 630362306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 630462306a36Sopenharmony_ci 630562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1143, "Entered %s.\n", __func__); 630662306a36Sopenharmony_ci 630762306a36Sopenharmony_ci mcp->mb[0] = MBC_RESTART_NIC_FIRMWARE; 630862306a36Sopenharmony_ci mcp->out_mb = MBX_0; 630962306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 631062306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 631162306a36Sopenharmony_ci mcp->flags = 0; 631262306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 631362306a36Sopenharmony_ci 631462306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 631562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1144, 631662306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x.\n", 631762306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1]); 631862306a36Sopenharmony_ci qla2xxx_dump_fw(vha); 631962306a36Sopenharmony_ci } else { 632062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1145, "Done %s.\n", __func__); 632162306a36Sopenharmony_ci } 632262306a36Sopenharmony_ci 632362306a36Sopenharmony_ci return rval; 632462306a36Sopenharmony_ci} 632562306a36Sopenharmony_ci 632662306a36Sopenharmony_ciint 632762306a36Sopenharmony_ciqla83xx_access_control(scsi_qla_host_t *vha, uint16_t options, 632862306a36Sopenharmony_ci uint32_t start_addr, uint32_t end_addr, uint16_t *sector_size) 632962306a36Sopenharmony_ci{ 633062306a36Sopenharmony_ci int rval; 633162306a36Sopenharmony_ci mbx_cmd_t mc; 633262306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 633362306a36Sopenharmony_ci uint8_t subcode = (uint8_t)options; 633462306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 633562306a36Sopenharmony_ci 633662306a36Sopenharmony_ci if (!IS_QLA8031(ha)) 633762306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 633862306a36Sopenharmony_ci 633962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1146, "Entered %s.\n", __func__); 634062306a36Sopenharmony_ci 634162306a36Sopenharmony_ci mcp->mb[0] = MBC_SET_ACCESS_CONTROL; 634262306a36Sopenharmony_ci mcp->mb[1] = options; 634362306a36Sopenharmony_ci mcp->out_mb = MBX_1|MBX_0; 634462306a36Sopenharmony_ci if (subcode & BIT_2) { 634562306a36Sopenharmony_ci mcp->mb[2] = LSW(start_addr); 634662306a36Sopenharmony_ci mcp->mb[3] = MSW(start_addr); 634762306a36Sopenharmony_ci mcp->mb[4] = LSW(end_addr); 634862306a36Sopenharmony_ci mcp->mb[5] = MSW(end_addr); 634962306a36Sopenharmony_ci mcp->out_mb |= MBX_5|MBX_4|MBX_3|MBX_2; 635062306a36Sopenharmony_ci } 635162306a36Sopenharmony_ci mcp->in_mb = MBX_2|MBX_1|MBX_0; 635262306a36Sopenharmony_ci if (!(subcode & (BIT_2 | BIT_5))) 635362306a36Sopenharmony_ci mcp->in_mb |= MBX_4|MBX_3; 635462306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 635562306a36Sopenharmony_ci mcp->flags = 0; 635662306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 635762306a36Sopenharmony_ci 635862306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 635962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1147, 636062306a36Sopenharmony_ci "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[3]=%x mb[4]=%x.\n", 636162306a36Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], 636262306a36Sopenharmony_ci mcp->mb[4]); 636362306a36Sopenharmony_ci qla2xxx_dump_fw(vha); 636462306a36Sopenharmony_ci } else { 636562306a36Sopenharmony_ci if (subcode & BIT_5) 636662306a36Sopenharmony_ci *sector_size = mcp->mb[1]; 636762306a36Sopenharmony_ci else if (subcode & (BIT_6 | BIT_7)) { 636862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1148, 636962306a36Sopenharmony_ci "Driver-lock id=%x%x", mcp->mb[4], mcp->mb[3]); 637062306a36Sopenharmony_ci } else if (subcode & (BIT_3 | BIT_4)) { 637162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1149, 637262306a36Sopenharmony_ci "Flash-lock id=%x%x", mcp->mb[4], mcp->mb[3]); 637362306a36Sopenharmony_ci } 637462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x114a, "Done %s.\n", __func__); 637562306a36Sopenharmony_ci } 637662306a36Sopenharmony_ci 637762306a36Sopenharmony_ci return rval; 637862306a36Sopenharmony_ci} 637962306a36Sopenharmony_ci 638062306a36Sopenharmony_ciint 638162306a36Sopenharmony_ciqla2x00_dump_mctp_data(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr, 638262306a36Sopenharmony_ci uint32_t size) 638362306a36Sopenharmony_ci{ 638462306a36Sopenharmony_ci int rval; 638562306a36Sopenharmony_ci mbx_cmd_t mc; 638662306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 638762306a36Sopenharmony_ci 638862306a36Sopenharmony_ci if (!IS_MCTP_CAPABLE(vha->hw)) 638962306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 639062306a36Sopenharmony_ci 639162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x114f, 639262306a36Sopenharmony_ci "Entered %s.\n", __func__); 639362306a36Sopenharmony_ci 639462306a36Sopenharmony_ci mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED; 639562306a36Sopenharmony_ci mcp->mb[1] = LSW(addr); 639662306a36Sopenharmony_ci mcp->mb[2] = MSW(req_dma); 639762306a36Sopenharmony_ci mcp->mb[3] = LSW(req_dma); 639862306a36Sopenharmony_ci mcp->mb[4] = MSW(size); 639962306a36Sopenharmony_ci mcp->mb[5] = LSW(size); 640062306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(req_dma)); 640162306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(req_dma)); 640262306a36Sopenharmony_ci mcp->mb[8] = MSW(addr); 640362306a36Sopenharmony_ci /* Setting RAM ID to valid */ 640462306a36Sopenharmony_ci /* For MCTP RAM ID is 0x40 */ 640562306a36Sopenharmony_ci mcp->mb[10] = BIT_7 | 0x40; 640662306a36Sopenharmony_ci 640762306a36Sopenharmony_ci mcp->out_mb |= MBX_10|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1| 640862306a36Sopenharmony_ci MBX_0; 640962306a36Sopenharmony_ci 641062306a36Sopenharmony_ci mcp->in_mb = MBX_0; 641162306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 641262306a36Sopenharmony_ci mcp->flags = 0; 641362306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 641462306a36Sopenharmony_ci 641562306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 641662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x114e, 641762306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 641862306a36Sopenharmony_ci } else { 641962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x114d, 642062306a36Sopenharmony_ci "Done %s.\n", __func__); 642162306a36Sopenharmony_ci } 642262306a36Sopenharmony_ci 642362306a36Sopenharmony_ci return rval; 642462306a36Sopenharmony_ci} 642562306a36Sopenharmony_ci 642662306a36Sopenharmony_ciint 642762306a36Sopenharmony_ciqla26xx_dport_diagnostics(scsi_qla_host_t *vha, 642862306a36Sopenharmony_ci void *dd_buf, uint size, uint options) 642962306a36Sopenharmony_ci{ 643062306a36Sopenharmony_ci int rval; 643162306a36Sopenharmony_ci mbx_cmd_t mc; 643262306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 643362306a36Sopenharmony_ci dma_addr_t dd_dma; 643462306a36Sopenharmony_ci 643562306a36Sopenharmony_ci if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) && 643662306a36Sopenharmony_ci !IS_QLA28XX(vha->hw)) 643762306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 643862306a36Sopenharmony_ci 643962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x119f, 644062306a36Sopenharmony_ci "Entered %s.\n", __func__); 644162306a36Sopenharmony_ci 644262306a36Sopenharmony_ci dd_dma = dma_map_single(&vha->hw->pdev->dev, 644362306a36Sopenharmony_ci dd_buf, size, DMA_FROM_DEVICE); 644462306a36Sopenharmony_ci if (dma_mapping_error(&vha->hw->pdev->dev, dd_dma)) { 644562306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1194, "Failed to map dma buffer.\n"); 644662306a36Sopenharmony_ci return QLA_MEMORY_ALLOC_FAILED; 644762306a36Sopenharmony_ci } 644862306a36Sopenharmony_ci 644962306a36Sopenharmony_ci memset(dd_buf, 0, size); 645062306a36Sopenharmony_ci 645162306a36Sopenharmony_ci mcp->mb[0] = MBC_DPORT_DIAGNOSTICS; 645262306a36Sopenharmony_ci mcp->mb[1] = options; 645362306a36Sopenharmony_ci mcp->mb[2] = MSW(LSD(dd_dma)); 645462306a36Sopenharmony_ci mcp->mb[3] = LSW(LSD(dd_dma)); 645562306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(dd_dma)); 645662306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(dd_dma)); 645762306a36Sopenharmony_ci mcp->mb[8] = size; 645862306a36Sopenharmony_ci mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; 645962306a36Sopenharmony_ci mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0; 646062306a36Sopenharmony_ci mcp->buf_size = size; 646162306a36Sopenharmony_ci mcp->flags = MBX_DMA_IN; 646262306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS * 4; 646362306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 646462306a36Sopenharmony_ci 646562306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 646662306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1195, "Failed=%x.\n", rval); 646762306a36Sopenharmony_ci } else { 646862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1196, 646962306a36Sopenharmony_ci "Done %s.\n", __func__); 647062306a36Sopenharmony_ci } 647162306a36Sopenharmony_ci 647262306a36Sopenharmony_ci dma_unmap_single(&vha->hw->pdev->dev, dd_dma, 647362306a36Sopenharmony_ci size, DMA_FROM_DEVICE); 647462306a36Sopenharmony_ci 647562306a36Sopenharmony_ci return rval; 647662306a36Sopenharmony_ci} 647762306a36Sopenharmony_ci 647862306a36Sopenharmony_ciint 647962306a36Sopenharmony_ciqla26xx_dport_diagnostics_v2(scsi_qla_host_t *vha, 648062306a36Sopenharmony_ci struct qla_dport_diag_v2 *dd, mbx_cmd_t *mcp) 648162306a36Sopenharmony_ci{ 648262306a36Sopenharmony_ci int rval; 648362306a36Sopenharmony_ci dma_addr_t dd_dma; 648462306a36Sopenharmony_ci uint size = sizeof(dd->buf); 648562306a36Sopenharmony_ci uint16_t options = dd->options; 648662306a36Sopenharmony_ci 648762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x119f, 648862306a36Sopenharmony_ci "Entered %s.\n", __func__); 648962306a36Sopenharmony_ci 649062306a36Sopenharmony_ci dd_dma = dma_map_single(&vha->hw->pdev->dev, 649162306a36Sopenharmony_ci dd->buf, size, DMA_FROM_DEVICE); 649262306a36Sopenharmony_ci if (dma_mapping_error(&vha->hw->pdev->dev, dd_dma)) { 649362306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1194, 649462306a36Sopenharmony_ci "Failed to map dma buffer.\n"); 649562306a36Sopenharmony_ci return QLA_MEMORY_ALLOC_FAILED; 649662306a36Sopenharmony_ci } 649762306a36Sopenharmony_ci 649862306a36Sopenharmony_ci memset(dd->buf, 0, size); 649962306a36Sopenharmony_ci 650062306a36Sopenharmony_ci mcp->mb[0] = MBC_DPORT_DIAGNOSTICS; 650162306a36Sopenharmony_ci mcp->mb[1] = options; 650262306a36Sopenharmony_ci mcp->mb[2] = MSW(LSD(dd_dma)); 650362306a36Sopenharmony_ci mcp->mb[3] = LSW(LSD(dd_dma)); 650462306a36Sopenharmony_ci mcp->mb[6] = MSW(MSD(dd_dma)); 650562306a36Sopenharmony_ci mcp->mb[7] = LSW(MSD(dd_dma)); 650662306a36Sopenharmony_ci mcp->mb[8] = size; 650762306a36Sopenharmony_ci mcp->out_mb = MBX_8 | MBX_7 | MBX_6 | MBX_3 | MBX_2 | MBX_1 | MBX_0; 650862306a36Sopenharmony_ci mcp->in_mb = MBX_3 | MBX_2 | MBX_1 | MBX_0; 650962306a36Sopenharmony_ci mcp->buf_size = size; 651062306a36Sopenharmony_ci mcp->flags = MBX_DMA_IN; 651162306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS * 4; 651262306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 651362306a36Sopenharmony_ci 651462306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 651562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1195, "Failed=%x.\n", rval); 651662306a36Sopenharmony_ci } else { 651762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1196, 651862306a36Sopenharmony_ci "Done %s.\n", __func__); 651962306a36Sopenharmony_ci } 652062306a36Sopenharmony_ci 652162306a36Sopenharmony_ci dma_unmap_single(&vha->hw->pdev->dev, dd_dma, size, DMA_FROM_DEVICE); 652262306a36Sopenharmony_ci 652362306a36Sopenharmony_ci return rval; 652462306a36Sopenharmony_ci} 652562306a36Sopenharmony_ci 652662306a36Sopenharmony_cistatic void qla2x00_async_mb_sp_done(srb_t *sp, int res) 652762306a36Sopenharmony_ci{ 652862306a36Sopenharmony_ci sp->u.iocb_cmd.u.mbx.rc = res; 652962306a36Sopenharmony_ci 653062306a36Sopenharmony_ci complete(&sp->u.iocb_cmd.u.mbx.comp); 653162306a36Sopenharmony_ci /* don't free sp here. Let the caller do the free */ 653262306a36Sopenharmony_ci} 653362306a36Sopenharmony_ci 653462306a36Sopenharmony_ci/* 653562306a36Sopenharmony_ci * This mailbox uses the iocb interface to send MB command. 653662306a36Sopenharmony_ci * This allows non-critial (non chip setup) command to go 653762306a36Sopenharmony_ci * out in parrallel. 653862306a36Sopenharmony_ci */ 653962306a36Sopenharmony_ciint qla24xx_send_mb_cmd(struct scsi_qla_host *vha, mbx_cmd_t *mcp) 654062306a36Sopenharmony_ci{ 654162306a36Sopenharmony_ci int rval = QLA_FUNCTION_FAILED; 654262306a36Sopenharmony_ci srb_t *sp; 654362306a36Sopenharmony_ci struct srb_iocb *c; 654462306a36Sopenharmony_ci 654562306a36Sopenharmony_ci if (!vha->hw->flags.fw_started) 654662306a36Sopenharmony_ci goto done; 654762306a36Sopenharmony_ci 654862306a36Sopenharmony_ci /* ref: INIT */ 654962306a36Sopenharmony_ci sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL); 655062306a36Sopenharmony_ci if (!sp) 655162306a36Sopenharmony_ci goto done; 655262306a36Sopenharmony_ci 655362306a36Sopenharmony_ci c = &sp->u.iocb_cmd; 655462306a36Sopenharmony_ci init_completion(&c->u.mbx.comp); 655562306a36Sopenharmony_ci 655662306a36Sopenharmony_ci sp->type = SRB_MB_IOCB; 655762306a36Sopenharmony_ci sp->name = mb_to_str(mcp->mb[0]); 655862306a36Sopenharmony_ci qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2, 655962306a36Sopenharmony_ci qla2x00_async_mb_sp_done); 656062306a36Sopenharmony_ci 656162306a36Sopenharmony_ci memcpy(sp->u.iocb_cmd.u.mbx.out_mb, mcp->mb, SIZEOF_IOCB_MB_REG); 656262306a36Sopenharmony_ci 656362306a36Sopenharmony_ci rval = qla2x00_start_sp(sp); 656462306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 656562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1018, 656662306a36Sopenharmony_ci "%s: %s Failed submission. %x.\n", 656762306a36Sopenharmony_ci __func__, sp->name, rval); 656862306a36Sopenharmony_ci goto done_free_sp; 656962306a36Sopenharmony_ci } 657062306a36Sopenharmony_ci 657162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x113f, "MB:%s hndl %x submitted\n", 657262306a36Sopenharmony_ci sp->name, sp->handle); 657362306a36Sopenharmony_ci 657462306a36Sopenharmony_ci wait_for_completion(&c->u.mbx.comp); 657562306a36Sopenharmony_ci memcpy(mcp->mb, sp->u.iocb_cmd.u.mbx.in_mb, SIZEOF_IOCB_MB_REG); 657662306a36Sopenharmony_ci 657762306a36Sopenharmony_ci rval = c->u.mbx.rc; 657862306a36Sopenharmony_ci switch (rval) { 657962306a36Sopenharmony_ci case QLA_FUNCTION_TIMEOUT: 658062306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1140, "%s: %s Timeout. %x.\n", 658162306a36Sopenharmony_ci __func__, sp->name, rval); 658262306a36Sopenharmony_ci break; 658362306a36Sopenharmony_ci case QLA_SUCCESS: 658462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x119d, "%s: %s done.\n", 658562306a36Sopenharmony_ci __func__, sp->name); 658662306a36Sopenharmony_ci break; 658762306a36Sopenharmony_ci default: 658862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x119e, "%s: %s Failed. %x.\n", 658962306a36Sopenharmony_ci __func__, sp->name, rval); 659062306a36Sopenharmony_ci break; 659162306a36Sopenharmony_ci } 659262306a36Sopenharmony_ci 659362306a36Sopenharmony_cidone_free_sp: 659462306a36Sopenharmony_ci /* ref: INIT */ 659562306a36Sopenharmony_ci kref_put(&sp->cmd_kref, qla2x00_sp_release); 659662306a36Sopenharmony_cidone: 659762306a36Sopenharmony_ci return rval; 659862306a36Sopenharmony_ci} 659962306a36Sopenharmony_ci 660062306a36Sopenharmony_ci/* 660162306a36Sopenharmony_ci * qla24xx_gpdb_wait 660262306a36Sopenharmony_ci * NOTE: Do not call this routine from DPC thread 660362306a36Sopenharmony_ci */ 660462306a36Sopenharmony_ciint qla24xx_gpdb_wait(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt) 660562306a36Sopenharmony_ci{ 660662306a36Sopenharmony_ci int rval = QLA_FUNCTION_FAILED; 660762306a36Sopenharmony_ci dma_addr_t pd_dma; 660862306a36Sopenharmony_ci struct port_database_24xx *pd; 660962306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 661062306a36Sopenharmony_ci mbx_cmd_t mc; 661162306a36Sopenharmony_ci 661262306a36Sopenharmony_ci if (!vha->hw->flags.fw_started) 661362306a36Sopenharmony_ci goto done; 661462306a36Sopenharmony_ci 661562306a36Sopenharmony_ci pd = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma); 661662306a36Sopenharmony_ci if (pd == NULL) { 661762306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0xd047, 661862306a36Sopenharmony_ci "Failed to allocate port database structure.\n"); 661962306a36Sopenharmony_ci goto done_free_sp; 662062306a36Sopenharmony_ci } 662162306a36Sopenharmony_ci 662262306a36Sopenharmony_ci memset(&mc, 0, sizeof(mc)); 662362306a36Sopenharmony_ci mc.mb[0] = MBC_GET_PORT_DATABASE; 662462306a36Sopenharmony_ci mc.mb[1] = fcport->loop_id; 662562306a36Sopenharmony_ci mc.mb[2] = MSW(pd_dma); 662662306a36Sopenharmony_ci mc.mb[3] = LSW(pd_dma); 662762306a36Sopenharmony_ci mc.mb[6] = MSW(MSD(pd_dma)); 662862306a36Sopenharmony_ci mc.mb[7] = LSW(MSD(pd_dma)); 662962306a36Sopenharmony_ci mc.mb[9] = vha->vp_idx; 663062306a36Sopenharmony_ci mc.mb[10] = opt; 663162306a36Sopenharmony_ci 663262306a36Sopenharmony_ci rval = qla24xx_send_mb_cmd(vha, &mc); 663362306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 663462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1193, 663562306a36Sopenharmony_ci "%s: %8phC fail\n", __func__, fcport->port_name); 663662306a36Sopenharmony_ci goto done_free_sp; 663762306a36Sopenharmony_ci } 663862306a36Sopenharmony_ci 663962306a36Sopenharmony_ci rval = __qla24xx_parse_gpdb(vha, fcport, pd); 664062306a36Sopenharmony_ci 664162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1197, "%s: %8phC done\n", 664262306a36Sopenharmony_ci __func__, fcport->port_name); 664362306a36Sopenharmony_ci 664462306a36Sopenharmony_cidone_free_sp: 664562306a36Sopenharmony_ci if (pd) 664662306a36Sopenharmony_ci dma_pool_free(ha->s_dma_pool, pd, pd_dma); 664762306a36Sopenharmony_cidone: 664862306a36Sopenharmony_ci return rval; 664962306a36Sopenharmony_ci} 665062306a36Sopenharmony_ci 665162306a36Sopenharmony_ciint __qla24xx_parse_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, 665262306a36Sopenharmony_ci struct port_database_24xx *pd) 665362306a36Sopenharmony_ci{ 665462306a36Sopenharmony_ci int rval = QLA_SUCCESS; 665562306a36Sopenharmony_ci uint64_t zero = 0; 665662306a36Sopenharmony_ci u8 current_login_state, last_login_state; 665762306a36Sopenharmony_ci 665862306a36Sopenharmony_ci if (NVME_TARGET(vha->hw, fcport)) { 665962306a36Sopenharmony_ci current_login_state = pd->current_login_state >> 4; 666062306a36Sopenharmony_ci last_login_state = pd->last_login_state >> 4; 666162306a36Sopenharmony_ci } else { 666262306a36Sopenharmony_ci current_login_state = pd->current_login_state & 0xf; 666362306a36Sopenharmony_ci last_login_state = pd->last_login_state & 0xf; 666462306a36Sopenharmony_ci } 666562306a36Sopenharmony_ci 666662306a36Sopenharmony_ci /* Check for logged in state. */ 666762306a36Sopenharmony_ci if (current_login_state != PDS_PRLI_COMPLETE) { 666862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x119a, 666962306a36Sopenharmony_ci "Unable to verify login-state (%x/%x) for loop_id %x.\n", 667062306a36Sopenharmony_ci current_login_state, last_login_state, fcport->loop_id); 667162306a36Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 667262306a36Sopenharmony_ci goto gpd_error_out; 667362306a36Sopenharmony_ci } 667462306a36Sopenharmony_ci 667562306a36Sopenharmony_ci if (fcport->loop_id == FC_NO_LOOP_ID || 667662306a36Sopenharmony_ci (memcmp(fcport->port_name, (uint8_t *)&zero, 8) && 667762306a36Sopenharmony_ci memcmp(fcport->port_name, pd->port_name, 8))) { 667862306a36Sopenharmony_ci /* We lost the device mid way. */ 667962306a36Sopenharmony_ci rval = QLA_NOT_LOGGED_IN; 668062306a36Sopenharmony_ci goto gpd_error_out; 668162306a36Sopenharmony_ci } 668262306a36Sopenharmony_ci 668362306a36Sopenharmony_ci /* Names are little-endian. */ 668462306a36Sopenharmony_ci memcpy(fcport->node_name, pd->node_name, WWN_SIZE); 668562306a36Sopenharmony_ci memcpy(fcport->port_name, pd->port_name, WWN_SIZE); 668662306a36Sopenharmony_ci 668762306a36Sopenharmony_ci /* Get port_id of device. */ 668862306a36Sopenharmony_ci fcport->d_id.b.domain = pd->port_id[0]; 668962306a36Sopenharmony_ci fcport->d_id.b.area = pd->port_id[1]; 669062306a36Sopenharmony_ci fcport->d_id.b.al_pa = pd->port_id[2]; 669162306a36Sopenharmony_ci fcport->d_id.b.rsvd_1 = 0; 669262306a36Sopenharmony_ci 669362306a36Sopenharmony_ci ql_dbg(ql_dbg_disc, vha, 0x2062, 669462306a36Sopenharmony_ci "%8phC SVC Param w3 %02x%02x", 669562306a36Sopenharmony_ci fcport->port_name, 669662306a36Sopenharmony_ci pd->prli_svc_param_word_3[1], 669762306a36Sopenharmony_ci pd->prli_svc_param_word_3[0]); 669862306a36Sopenharmony_ci 669962306a36Sopenharmony_ci if (NVME_TARGET(vha->hw, fcport)) { 670062306a36Sopenharmony_ci fcport->port_type = FCT_NVME; 670162306a36Sopenharmony_ci if ((pd->prli_svc_param_word_3[0] & BIT_5) == 0) 670262306a36Sopenharmony_ci fcport->port_type |= FCT_NVME_INITIATOR; 670362306a36Sopenharmony_ci if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0) 670462306a36Sopenharmony_ci fcport->port_type |= FCT_NVME_TARGET; 670562306a36Sopenharmony_ci if ((pd->prli_svc_param_word_3[0] & BIT_3) == 0) 670662306a36Sopenharmony_ci fcport->port_type |= FCT_NVME_DISCOVERY; 670762306a36Sopenharmony_ci } else { 670862306a36Sopenharmony_ci /* If not target must be initiator or unknown type. */ 670962306a36Sopenharmony_ci if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0) 671062306a36Sopenharmony_ci fcport->port_type = FCT_INITIATOR; 671162306a36Sopenharmony_ci else 671262306a36Sopenharmony_ci fcport->port_type = FCT_TARGET; 671362306a36Sopenharmony_ci } 671462306a36Sopenharmony_ci /* Passback COS information. */ 671562306a36Sopenharmony_ci fcport->supported_classes = (pd->flags & PDF_CLASS_2) ? 671662306a36Sopenharmony_ci FC_COS_CLASS2 : FC_COS_CLASS3; 671762306a36Sopenharmony_ci 671862306a36Sopenharmony_ci if (pd->prli_svc_param_word_3[0] & BIT_7) { 671962306a36Sopenharmony_ci fcport->flags |= FCF_CONF_COMP_SUPPORTED; 672062306a36Sopenharmony_ci fcport->conf_compl_supported = 1; 672162306a36Sopenharmony_ci } 672262306a36Sopenharmony_ci 672362306a36Sopenharmony_cigpd_error_out: 672462306a36Sopenharmony_ci return rval; 672562306a36Sopenharmony_ci} 672662306a36Sopenharmony_ci 672762306a36Sopenharmony_ci/* 672862306a36Sopenharmony_ci * qla24xx_gidlist__wait 672962306a36Sopenharmony_ci * NOTE: don't call this routine from DPC thread. 673062306a36Sopenharmony_ci */ 673162306a36Sopenharmony_ciint qla24xx_gidlist_wait(struct scsi_qla_host *vha, 673262306a36Sopenharmony_ci void *id_list, dma_addr_t id_list_dma, uint16_t *entries) 673362306a36Sopenharmony_ci{ 673462306a36Sopenharmony_ci int rval = QLA_FUNCTION_FAILED; 673562306a36Sopenharmony_ci mbx_cmd_t mc; 673662306a36Sopenharmony_ci 673762306a36Sopenharmony_ci if (!vha->hw->flags.fw_started) 673862306a36Sopenharmony_ci goto done; 673962306a36Sopenharmony_ci 674062306a36Sopenharmony_ci memset(&mc, 0, sizeof(mc)); 674162306a36Sopenharmony_ci mc.mb[0] = MBC_GET_ID_LIST; 674262306a36Sopenharmony_ci mc.mb[2] = MSW(id_list_dma); 674362306a36Sopenharmony_ci mc.mb[3] = LSW(id_list_dma); 674462306a36Sopenharmony_ci mc.mb[6] = MSW(MSD(id_list_dma)); 674562306a36Sopenharmony_ci mc.mb[7] = LSW(MSD(id_list_dma)); 674662306a36Sopenharmony_ci mc.mb[8] = 0; 674762306a36Sopenharmony_ci mc.mb[9] = vha->vp_idx; 674862306a36Sopenharmony_ci 674962306a36Sopenharmony_ci rval = qla24xx_send_mb_cmd(vha, &mc); 675062306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 675162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x119b, 675262306a36Sopenharmony_ci "%s: fail\n", __func__); 675362306a36Sopenharmony_ci } else { 675462306a36Sopenharmony_ci *entries = mc.mb[1]; 675562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x119c, 675662306a36Sopenharmony_ci "%s: done\n", __func__); 675762306a36Sopenharmony_ci } 675862306a36Sopenharmony_cidone: 675962306a36Sopenharmony_ci return rval; 676062306a36Sopenharmony_ci} 676162306a36Sopenharmony_ci 676262306a36Sopenharmony_ciint qla27xx_set_zio_threshold(scsi_qla_host_t *vha, uint16_t value) 676362306a36Sopenharmony_ci{ 676462306a36Sopenharmony_ci int rval; 676562306a36Sopenharmony_ci mbx_cmd_t mc; 676662306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 676762306a36Sopenharmony_ci 676862306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1200, 676962306a36Sopenharmony_ci "Entered %s\n", __func__); 677062306a36Sopenharmony_ci 677162306a36Sopenharmony_ci memset(mcp->mb, 0 , sizeof(mcp->mb)); 677262306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_SET_ZIO_THRESHOLD; 677362306a36Sopenharmony_ci mcp->mb[1] = 1; 677462306a36Sopenharmony_ci mcp->mb[2] = value; 677562306a36Sopenharmony_ci mcp->out_mb = MBX_2 | MBX_1 | MBX_0; 677662306a36Sopenharmony_ci mcp->in_mb = MBX_2 | MBX_0; 677762306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 677862306a36Sopenharmony_ci mcp->flags = 0; 677962306a36Sopenharmony_ci 678062306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 678162306a36Sopenharmony_ci 678262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1201, "%s %x\n", 678362306a36Sopenharmony_ci (rval != QLA_SUCCESS) ? "Failed" : "Done", rval); 678462306a36Sopenharmony_ci 678562306a36Sopenharmony_ci return rval; 678662306a36Sopenharmony_ci} 678762306a36Sopenharmony_ci 678862306a36Sopenharmony_ciint qla27xx_get_zio_threshold(scsi_qla_host_t *vha, uint16_t *value) 678962306a36Sopenharmony_ci{ 679062306a36Sopenharmony_ci int rval; 679162306a36Sopenharmony_ci mbx_cmd_t mc; 679262306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 679362306a36Sopenharmony_ci 679462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1203, 679562306a36Sopenharmony_ci "Entered %s\n", __func__); 679662306a36Sopenharmony_ci 679762306a36Sopenharmony_ci memset(mcp->mb, 0, sizeof(mcp->mb)); 679862306a36Sopenharmony_ci mcp->mb[0] = MBC_GET_SET_ZIO_THRESHOLD; 679962306a36Sopenharmony_ci mcp->mb[1] = 0; 680062306a36Sopenharmony_ci mcp->out_mb = MBX_1 | MBX_0; 680162306a36Sopenharmony_ci mcp->in_mb = MBX_2 | MBX_0; 680262306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 680362306a36Sopenharmony_ci mcp->flags = 0; 680462306a36Sopenharmony_ci 680562306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 680662306a36Sopenharmony_ci if (rval == QLA_SUCCESS) 680762306a36Sopenharmony_ci *value = mc.mb[2]; 680862306a36Sopenharmony_ci 680962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1205, "%s %x\n", 681062306a36Sopenharmony_ci (rval != QLA_SUCCESS) ? "Failed" : "Done", rval); 681162306a36Sopenharmony_ci 681262306a36Sopenharmony_ci return rval; 681362306a36Sopenharmony_ci} 681462306a36Sopenharmony_ci 681562306a36Sopenharmony_ciint 681662306a36Sopenharmony_ciqla2x00_read_sfp_dev(struct scsi_qla_host *vha, char *buf, int count) 681762306a36Sopenharmony_ci{ 681862306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 681962306a36Sopenharmony_ci uint16_t iter, addr, offset; 682062306a36Sopenharmony_ci dma_addr_t phys_addr; 682162306a36Sopenharmony_ci int rval, c; 682262306a36Sopenharmony_ci u8 *sfp_data; 682362306a36Sopenharmony_ci 682462306a36Sopenharmony_ci memset(ha->sfp_data, 0, SFP_DEV_SIZE); 682562306a36Sopenharmony_ci addr = 0xa0; 682662306a36Sopenharmony_ci phys_addr = ha->sfp_data_dma; 682762306a36Sopenharmony_ci sfp_data = ha->sfp_data; 682862306a36Sopenharmony_ci offset = c = 0; 682962306a36Sopenharmony_ci 683062306a36Sopenharmony_ci for (iter = 0; iter < SFP_DEV_SIZE / SFP_BLOCK_SIZE; iter++) { 683162306a36Sopenharmony_ci if (iter == 4) { 683262306a36Sopenharmony_ci /* Skip to next device address. */ 683362306a36Sopenharmony_ci addr = 0xa2; 683462306a36Sopenharmony_ci offset = 0; 683562306a36Sopenharmony_ci } 683662306a36Sopenharmony_ci 683762306a36Sopenharmony_ci rval = qla2x00_read_sfp(vha, phys_addr, sfp_data, 683862306a36Sopenharmony_ci addr, offset, SFP_BLOCK_SIZE, BIT_1); 683962306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 684062306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0x706d, 684162306a36Sopenharmony_ci "Unable to read SFP data (%x/%x/%x).\n", rval, 684262306a36Sopenharmony_ci addr, offset); 684362306a36Sopenharmony_ci 684462306a36Sopenharmony_ci return rval; 684562306a36Sopenharmony_ci } 684662306a36Sopenharmony_ci 684762306a36Sopenharmony_ci if (buf && (c < count)) { 684862306a36Sopenharmony_ci u16 sz; 684962306a36Sopenharmony_ci 685062306a36Sopenharmony_ci if ((count - c) >= SFP_BLOCK_SIZE) 685162306a36Sopenharmony_ci sz = SFP_BLOCK_SIZE; 685262306a36Sopenharmony_ci else 685362306a36Sopenharmony_ci sz = count - c; 685462306a36Sopenharmony_ci 685562306a36Sopenharmony_ci memcpy(buf, sfp_data, sz); 685662306a36Sopenharmony_ci buf += SFP_BLOCK_SIZE; 685762306a36Sopenharmony_ci c += sz; 685862306a36Sopenharmony_ci } 685962306a36Sopenharmony_ci phys_addr += SFP_BLOCK_SIZE; 686062306a36Sopenharmony_ci sfp_data += SFP_BLOCK_SIZE; 686162306a36Sopenharmony_ci offset += SFP_BLOCK_SIZE; 686262306a36Sopenharmony_ci } 686362306a36Sopenharmony_ci 686462306a36Sopenharmony_ci return rval; 686562306a36Sopenharmony_ci} 686662306a36Sopenharmony_ci 686762306a36Sopenharmony_ciint qla24xx_res_count_wait(struct scsi_qla_host *vha, 686862306a36Sopenharmony_ci uint16_t *out_mb, int out_mb_sz) 686962306a36Sopenharmony_ci{ 687062306a36Sopenharmony_ci int rval = QLA_FUNCTION_FAILED; 687162306a36Sopenharmony_ci mbx_cmd_t mc; 687262306a36Sopenharmony_ci 687362306a36Sopenharmony_ci if (!vha->hw->flags.fw_started) 687462306a36Sopenharmony_ci goto done; 687562306a36Sopenharmony_ci 687662306a36Sopenharmony_ci memset(&mc, 0, sizeof(mc)); 687762306a36Sopenharmony_ci mc.mb[0] = MBC_GET_RESOURCE_COUNTS; 687862306a36Sopenharmony_ci 687962306a36Sopenharmony_ci rval = qla24xx_send_mb_cmd(vha, &mc); 688062306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 688162306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0xffff, 688262306a36Sopenharmony_ci "%s: fail\n", __func__); 688362306a36Sopenharmony_ci } else { 688462306a36Sopenharmony_ci if (out_mb_sz <= SIZEOF_IOCB_MB_REG) 688562306a36Sopenharmony_ci memcpy(out_mb, mc.mb, out_mb_sz); 688662306a36Sopenharmony_ci else 688762306a36Sopenharmony_ci memcpy(out_mb, mc.mb, SIZEOF_IOCB_MB_REG); 688862306a36Sopenharmony_ci 688962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0xffff, 689062306a36Sopenharmony_ci "%s: done\n", __func__); 689162306a36Sopenharmony_ci } 689262306a36Sopenharmony_cidone: 689362306a36Sopenharmony_ci return rval; 689462306a36Sopenharmony_ci} 689562306a36Sopenharmony_ci 689662306a36Sopenharmony_ciint qla28xx_secure_flash_update(scsi_qla_host_t *vha, uint16_t opts, 689762306a36Sopenharmony_ci uint16_t region, uint32_t len, dma_addr_t sfub_dma_addr, 689862306a36Sopenharmony_ci uint32_t sfub_len) 689962306a36Sopenharmony_ci{ 690062306a36Sopenharmony_ci int rval; 690162306a36Sopenharmony_ci mbx_cmd_t mc; 690262306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 690362306a36Sopenharmony_ci 690462306a36Sopenharmony_ci mcp->mb[0] = MBC_SECURE_FLASH_UPDATE; 690562306a36Sopenharmony_ci mcp->mb[1] = opts; 690662306a36Sopenharmony_ci mcp->mb[2] = region; 690762306a36Sopenharmony_ci mcp->mb[3] = MSW(len); 690862306a36Sopenharmony_ci mcp->mb[4] = LSW(len); 690962306a36Sopenharmony_ci mcp->mb[5] = MSW(sfub_dma_addr); 691062306a36Sopenharmony_ci mcp->mb[6] = LSW(sfub_dma_addr); 691162306a36Sopenharmony_ci mcp->mb[7] = MSW(MSD(sfub_dma_addr)); 691262306a36Sopenharmony_ci mcp->mb[8] = LSW(MSD(sfub_dma_addr)); 691362306a36Sopenharmony_ci mcp->mb[9] = sfub_len; 691462306a36Sopenharmony_ci mcp->out_mb = 691562306a36Sopenharmony_ci MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 691662306a36Sopenharmony_ci mcp->in_mb = MBX_2|MBX_1|MBX_0; 691762306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 691862306a36Sopenharmony_ci mcp->flags = 0; 691962306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 692062306a36Sopenharmony_ci 692162306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 692262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0xffff, "%s(%ld): failed rval 0x%x, %x %x %x", 692362306a36Sopenharmony_ci __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1], 692462306a36Sopenharmony_ci mcp->mb[2]); 692562306a36Sopenharmony_ci } 692662306a36Sopenharmony_ci 692762306a36Sopenharmony_ci return rval; 692862306a36Sopenharmony_ci} 692962306a36Sopenharmony_ci 693062306a36Sopenharmony_ciint qla2xxx_write_remote_register(scsi_qla_host_t *vha, uint32_t addr, 693162306a36Sopenharmony_ci uint32_t data) 693262306a36Sopenharmony_ci{ 693362306a36Sopenharmony_ci int rval; 693462306a36Sopenharmony_ci mbx_cmd_t mc; 693562306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 693662306a36Sopenharmony_ci 693762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e8, 693862306a36Sopenharmony_ci "Entered %s.\n", __func__); 693962306a36Sopenharmony_ci 694062306a36Sopenharmony_ci mcp->mb[0] = MBC_WRITE_REMOTE_REG; 694162306a36Sopenharmony_ci mcp->mb[1] = LSW(addr); 694262306a36Sopenharmony_ci mcp->mb[2] = MSW(addr); 694362306a36Sopenharmony_ci mcp->mb[3] = LSW(data); 694462306a36Sopenharmony_ci mcp->mb[4] = MSW(data); 694562306a36Sopenharmony_ci mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 694662306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 694762306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 694862306a36Sopenharmony_ci mcp->flags = 0; 694962306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 695062306a36Sopenharmony_ci 695162306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 695262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10e9, 695362306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 695462306a36Sopenharmony_ci } else { 695562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea, 695662306a36Sopenharmony_ci "Done %s.\n", __func__); 695762306a36Sopenharmony_ci } 695862306a36Sopenharmony_ci 695962306a36Sopenharmony_ci return rval; 696062306a36Sopenharmony_ci} 696162306a36Sopenharmony_ci 696262306a36Sopenharmony_ciint qla2xxx_read_remote_register(scsi_qla_host_t *vha, uint32_t addr, 696362306a36Sopenharmony_ci uint32_t *data) 696462306a36Sopenharmony_ci{ 696562306a36Sopenharmony_ci int rval; 696662306a36Sopenharmony_ci mbx_cmd_t mc; 696762306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 696862306a36Sopenharmony_ci 696962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e8, 697062306a36Sopenharmony_ci "Entered %s.\n", __func__); 697162306a36Sopenharmony_ci 697262306a36Sopenharmony_ci mcp->mb[0] = MBC_READ_REMOTE_REG; 697362306a36Sopenharmony_ci mcp->mb[1] = LSW(addr); 697462306a36Sopenharmony_ci mcp->mb[2] = MSW(addr); 697562306a36Sopenharmony_ci mcp->out_mb = MBX_2|MBX_1|MBX_0; 697662306a36Sopenharmony_ci mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 697762306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 697862306a36Sopenharmony_ci mcp->flags = 0; 697962306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 698062306a36Sopenharmony_ci 698162306a36Sopenharmony_ci *data = (uint32_t)((((uint32_t)mcp->mb[4]) << 16) | mcp->mb[3]); 698262306a36Sopenharmony_ci 698362306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 698462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x10e9, 698562306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 698662306a36Sopenharmony_ci } else { 698762306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea, 698862306a36Sopenharmony_ci "Done %s.\n", __func__); 698962306a36Sopenharmony_ci } 699062306a36Sopenharmony_ci 699162306a36Sopenharmony_ci return rval; 699262306a36Sopenharmony_ci} 699362306a36Sopenharmony_ci 699462306a36Sopenharmony_ciint 699562306a36Sopenharmony_ciql26xx_led_config(scsi_qla_host_t *vha, uint16_t options, uint16_t *led) 699662306a36Sopenharmony_ci{ 699762306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 699862306a36Sopenharmony_ci mbx_cmd_t mc; 699962306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 700062306a36Sopenharmony_ci int rval; 700162306a36Sopenharmony_ci 700262306a36Sopenharmony_ci if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 700362306a36Sopenharmony_ci return QLA_FUNCTION_FAILED; 700462306a36Sopenharmony_ci 700562306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x7070, "Entered %s (options=%x).\n", 700662306a36Sopenharmony_ci __func__, options); 700762306a36Sopenharmony_ci 700862306a36Sopenharmony_ci mcp->mb[0] = MBC_SET_GET_FC_LED_CONFIG; 700962306a36Sopenharmony_ci mcp->mb[1] = options; 701062306a36Sopenharmony_ci mcp->out_mb = MBX_1|MBX_0; 701162306a36Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 701262306a36Sopenharmony_ci if (options & BIT_0) { 701362306a36Sopenharmony_ci if (options & BIT_1) { 701462306a36Sopenharmony_ci mcp->mb[2] = led[2]; 701562306a36Sopenharmony_ci mcp->out_mb |= MBX_2; 701662306a36Sopenharmony_ci } 701762306a36Sopenharmony_ci if (options & BIT_2) { 701862306a36Sopenharmony_ci mcp->mb[3] = led[0]; 701962306a36Sopenharmony_ci mcp->out_mb |= MBX_3; 702062306a36Sopenharmony_ci } 702162306a36Sopenharmony_ci if (options & BIT_3) { 702262306a36Sopenharmony_ci mcp->mb[4] = led[1]; 702362306a36Sopenharmony_ci mcp->out_mb |= MBX_4; 702462306a36Sopenharmony_ci } 702562306a36Sopenharmony_ci } else { 702662306a36Sopenharmony_ci mcp->in_mb |= MBX_4|MBX_3|MBX_2; 702762306a36Sopenharmony_ci } 702862306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 702962306a36Sopenharmony_ci mcp->flags = 0; 703062306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 703162306a36Sopenharmony_ci if (rval) { 703262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x7071, "Failed %s %x (mb=%x,%x)\n", 703362306a36Sopenharmony_ci __func__, rval, mcp->mb[0], mcp->mb[1]); 703462306a36Sopenharmony_ci return rval; 703562306a36Sopenharmony_ci } 703662306a36Sopenharmony_ci 703762306a36Sopenharmony_ci if (options & BIT_0) { 703862306a36Sopenharmony_ci ha->beacon_blink_led = 0; 703962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x7072, "Done %s\n", __func__); 704062306a36Sopenharmony_ci } else { 704162306a36Sopenharmony_ci led[2] = mcp->mb[2]; 704262306a36Sopenharmony_ci led[0] = mcp->mb[3]; 704362306a36Sopenharmony_ci led[1] = mcp->mb[4]; 704462306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x7073, "Done %s (led=%x,%x,%x)\n", 704562306a36Sopenharmony_ci __func__, led[0], led[1], led[2]); 704662306a36Sopenharmony_ci } 704762306a36Sopenharmony_ci 704862306a36Sopenharmony_ci return rval; 704962306a36Sopenharmony_ci} 705062306a36Sopenharmony_ci 705162306a36Sopenharmony_ci/** 705262306a36Sopenharmony_ci * qla_no_op_mb(): This MB is used to check if FW is still alive and 705362306a36Sopenharmony_ci * able to generate an interrupt. Otherwise, a timeout will trigger 705462306a36Sopenharmony_ci * FW dump + reset 705562306a36Sopenharmony_ci * @vha: host adapter pointer 705662306a36Sopenharmony_ci * Return: None 705762306a36Sopenharmony_ci */ 705862306a36Sopenharmony_civoid qla_no_op_mb(struct scsi_qla_host *vha) 705962306a36Sopenharmony_ci{ 706062306a36Sopenharmony_ci mbx_cmd_t mc; 706162306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 706262306a36Sopenharmony_ci int rval; 706362306a36Sopenharmony_ci 706462306a36Sopenharmony_ci memset(&mc, 0, sizeof(mc)); 706562306a36Sopenharmony_ci mcp->mb[0] = 0; // noop cmd= 0 706662306a36Sopenharmony_ci mcp->out_mb = MBX_0; 706762306a36Sopenharmony_ci mcp->in_mb = MBX_0; 706862306a36Sopenharmony_ci mcp->tov = 5; 706962306a36Sopenharmony_ci mcp->flags = 0; 707062306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 707162306a36Sopenharmony_ci 707262306a36Sopenharmony_ci if (rval) { 707362306a36Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x7071, 707462306a36Sopenharmony_ci "Failed %s %x\n", __func__, rval); 707562306a36Sopenharmony_ci } 707662306a36Sopenharmony_ci} 707762306a36Sopenharmony_ci 707862306a36Sopenharmony_ciint qla_mailbox_passthru(scsi_qla_host_t *vha, 707962306a36Sopenharmony_ci uint16_t *mbx_in, uint16_t *mbx_out) 708062306a36Sopenharmony_ci{ 708162306a36Sopenharmony_ci mbx_cmd_t mc; 708262306a36Sopenharmony_ci mbx_cmd_t *mcp = &mc; 708362306a36Sopenharmony_ci int rval = -EINVAL; 708462306a36Sopenharmony_ci 708562306a36Sopenharmony_ci memset(&mc, 0, sizeof(mc)); 708662306a36Sopenharmony_ci /* Receiving all 32 register's contents */ 708762306a36Sopenharmony_ci memcpy(&mcp->mb, (char *)mbx_in, (32 * sizeof(uint16_t))); 708862306a36Sopenharmony_ci 708962306a36Sopenharmony_ci mcp->out_mb = 0xFFFFFFFF; 709062306a36Sopenharmony_ci mcp->in_mb = 0xFFFFFFFF; 709162306a36Sopenharmony_ci 709262306a36Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 709362306a36Sopenharmony_ci mcp->flags = 0; 709462306a36Sopenharmony_ci mcp->bufp = NULL; 709562306a36Sopenharmony_ci 709662306a36Sopenharmony_ci rval = qla2x00_mailbox_command(vha, mcp); 709762306a36Sopenharmony_ci 709862306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 709962306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0xf0a2, 710062306a36Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 710162306a36Sopenharmony_ci } else { 710262306a36Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0xf0a3, "Done %s.\n", 710362306a36Sopenharmony_ci __func__); 710462306a36Sopenharmony_ci /* passing all 32 register's contents */ 710562306a36Sopenharmony_ci memcpy(mbx_out, &mcp->mb, 32 * sizeof(uint16_t)); 710662306a36Sopenharmony_ci } 710762306a36Sopenharmony_ci 710862306a36Sopenharmony_ci return rval; 710962306a36Sopenharmony_ci} 7110