162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * QLogic iSCSI HBA Driver 462306a36Sopenharmony_ci * Copyright (c) 2003-2013 QLogic Corporation 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/ctype.h> 862306a36Sopenharmony_ci#include "ql4_def.h" 962306a36Sopenharmony_ci#include "ql4_glbl.h" 1062306a36Sopenharmony_ci#include "ql4_dbg.h" 1162306a36Sopenharmony_ci#include "ql4_inline.h" 1262306a36Sopenharmony_ci#include "ql4_version.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_civoid qla4xxx_queue_mbox_cmd(struct scsi_qla_host *ha, uint32_t *mbx_cmd, 1562306a36Sopenharmony_ci int in_count) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci int i; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci /* Load all mailbox registers, except mailbox 0. */ 2062306a36Sopenharmony_ci for (i = 1; i < in_count; i++) 2162306a36Sopenharmony_ci writel(mbx_cmd[i], &ha->reg->mailbox[i]); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci /* Wakeup firmware */ 2462306a36Sopenharmony_ci writel(mbx_cmd[0], &ha->reg->mailbox[0]); 2562306a36Sopenharmony_ci readl(&ha->reg->mailbox[0]); 2662306a36Sopenharmony_ci writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status); 2762306a36Sopenharmony_ci readl(&ha->reg->ctrl_status); 2862306a36Sopenharmony_ci} 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_civoid qla4xxx_process_mbox_intr(struct scsi_qla_host *ha, int out_count) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci int intr_status; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci intr_status = readl(&ha->reg->ctrl_status); 3562306a36Sopenharmony_ci if (intr_status & INTR_PENDING) { 3662306a36Sopenharmony_ci /* 3762306a36Sopenharmony_ci * Service the interrupt. 3862306a36Sopenharmony_ci * The ISR will save the mailbox status registers 3962306a36Sopenharmony_ci * to a temporary storage location in the adapter structure. 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_ci ha->mbox_status_count = out_count; 4262306a36Sopenharmony_ci ha->isp_ops->interrupt_service_routine(ha, intr_status); 4362306a36Sopenharmony_ci } 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/** 4762306a36Sopenharmony_ci * qla4xxx_is_intr_poll_mode - Are we allowed to poll for interrupts? 4862306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 4962306a36Sopenharmony_ci * returns: 1=polling mode, 0=non-polling mode 5062306a36Sopenharmony_ci **/ 5162306a36Sopenharmony_cistatic int qla4xxx_is_intr_poll_mode(struct scsi_qla_host *ha) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci int rval = 1; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci if (is_qla8032(ha) || is_qla8042(ha)) { 5662306a36Sopenharmony_ci if (test_bit(AF_IRQ_ATTACHED, &ha->flags) && 5762306a36Sopenharmony_ci test_bit(AF_83XX_MBOX_INTR_ON, &ha->flags)) 5862306a36Sopenharmony_ci rval = 0; 5962306a36Sopenharmony_ci } else { 6062306a36Sopenharmony_ci if (test_bit(AF_IRQ_ATTACHED, &ha->flags) && 6162306a36Sopenharmony_ci test_bit(AF_INTERRUPTS_ON, &ha->flags) && 6262306a36Sopenharmony_ci test_bit(AF_ONLINE, &ha->flags) && 6362306a36Sopenharmony_ci !test_bit(AF_HA_REMOVAL, &ha->flags)) 6462306a36Sopenharmony_ci rval = 0; 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci return rval; 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/** 7162306a36Sopenharmony_ci * qla4xxx_mailbox_command - issues mailbox commands 7262306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 7362306a36Sopenharmony_ci * @inCount: number of mailbox registers to load. 7462306a36Sopenharmony_ci * @outCount: number of mailbox registers to return. 7562306a36Sopenharmony_ci * @mbx_cmd: data pointer for mailbox in registers. 7662306a36Sopenharmony_ci * @mbx_sts: data pointer for mailbox out registers. 7762306a36Sopenharmony_ci * 7862306a36Sopenharmony_ci * This routine issue mailbox commands and waits for completion. 7962306a36Sopenharmony_ci * If outCount is 0, this routine completes successfully WITHOUT waiting 8062306a36Sopenharmony_ci * for the mailbox command to complete. 8162306a36Sopenharmony_ci **/ 8262306a36Sopenharmony_ciint qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, 8362306a36Sopenharmony_ci uint8_t outCount, uint32_t *mbx_cmd, 8462306a36Sopenharmony_ci uint32_t *mbx_sts) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci int status = QLA_ERROR; 8762306a36Sopenharmony_ci uint8_t i; 8862306a36Sopenharmony_ci u_long wait_count; 8962306a36Sopenharmony_ci unsigned long flags = 0; 9062306a36Sopenharmony_ci uint32_t dev_state; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci /* Make sure that pointers are valid */ 9362306a36Sopenharmony_ci if (!mbx_cmd || !mbx_sts) { 9462306a36Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts " 9562306a36Sopenharmony_ci "pointer\n", ha->host_no, __func__)); 9662306a36Sopenharmony_ci return status; 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci if (is_qla40XX(ha)) { 10062306a36Sopenharmony_ci if (test_bit(AF_HA_REMOVAL, &ha->flags)) { 10162306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: " 10262306a36Sopenharmony_ci "prematurely completing mbx cmd as " 10362306a36Sopenharmony_ci "adapter removal detected\n", 10462306a36Sopenharmony_ci ha->host_no, __func__)); 10562306a36Sopenharmony_ci return status; 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci if ((is_aer_supported(ha)) && 11062306a36Sopenharmony_ci (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) { 11162306a36Sopenharmony_ci DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, " 11262306a36Sopenharmony_ci "timeout MBX Exiting.\n", ha->host_no, __func__)); 11362306a36Sopenharmony_ci return status; 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci /* Mailbox code active */ 11762306a36Sopenharmony_ci wait_count = MBOX_TOV * 100; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci while (wait_count--) { 12062306a36Sopenharmony_ci mutex_lock(&ha->mbox_sem); 12162306a36Sopenharmony_ci if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) { 12262306a36Sopenharmony_ci set_bit(AF_MBOX_COMMAND, &ha->flags); 12362306a36Sopenharmony_ci mutex_unlock(&ha->mbox_sem); 12462306a36Sopenharmony_ci break; 12562306a36Sopenharmony_ci } 12662306a36Sopenharmony_ci mutex_unlock(&ha->mbox_sem); 12762306a36Sopenharmony_ci if (!wait_count) { 12862306a36Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n", 12962306a36Sopenharmony_ci ha->host_no, __func__)); 13062306a36Sopenharmony_ci return status; 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci msleep(10); 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci if (is_qla80XX(ha)) { 13662306a36Sopenharmony_ci if (test_bit(AF_FW_RECOVERY, &ha->flags)) { 13762306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, 13862306a36Sopenharmony_ci "scsi%ld: %s: prematurely completing mbx cmd as firmware recovery detected\n", 13962306a36Sopenharmony_ci ha->host_no, __func__)); 14062306a36Sopenharmony_ci goto mbox_exit; 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci /* Do not send any mbx cmd if h/w is in failed state*/ 14362306a36Sopenharmony_ci ha->isp_ops->idc_lock(ha); 14462306a36Sopenharmony_ci dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE); 14562306a36Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 14662306a36Sopenharmony_ci if (dev_state == QLA8XXX_DEV_FAILED) { 14762306a36Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 14862306a36Sopenharmony_ci "scsi%ld: %s: H/W is in failed state, do not send any mailbox commands\n", 14962306a36Sopenharmony_ci ha->host_no, __func__); 15062306a36Sopenharmony_ci goto mbox_exit; 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci } 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci ha->mbox_status_count = outCount; 15762306a36Sopenharmony_ci for (i = 0; i < outCount; i++) 15862306a36Sopenharmony_ci ha->mbox_status[i] = 0; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci /* Queue the mailbox command to the firmware */ 16162306a36Sopenharmony_ci ha->isp_ops->queue_mailbox_command(ha, mbx_cmd, inCount); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci /* Wait for completion */ 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci /* 16862306a36Sopenharmony_ci * If we don't want status, don't wait for the mailbox command to 16962306a36Sopenharmony_ci * complete. For example, MBOX_CMD_RESET_FW doesn't return status, 17062306a36Sopenharmony_ci * you must poll the inbound Interrupt Mask for completion. 17162306a36Sopenharmony_ci */ 17262306a36Sopenharmony_ci if (outCount == 0) { 17362306a36Sopenharmony_ci status = QLA_SUCCESS; 17462306a36Sopenharmony_ci goto mbox_exit; 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci /* 17862306a36Sopenharmony_ci * Wait for completion: Poll or completion queue 17962306a36Sopenharmony_ci */ 18062306a36Sopenharmony_ci if (qla4xxx_is_intr_poll_mode(ha)) { 18162306a36Sopenharmony_ci /* Poll for command to complete */ 18262306a36Sopenharmony_ci wait_count = jiffies + MBOX_TOV * HZ; 18362306a36Sopenharmony_ci while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) { 18462306a36Sopenharmony_ci if (time_after_eq(jiffies, wait_count)) 18562306a36Sopenharmony_ci break; 18662306a36Sopenharmony_ci /* 18762306a36Sopenharmony_ci * Service the interrupt. 18862306a36Sopenharmony_ci * The ISR will save the mailbox status registers 18962306a36Sopenharmony_ci * to a temporary storage location in the adapter 19062306a36Sopenharmony_ci * structure. 19162306a36Sopenharmony_ci */ 19262306a36Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 19362306a36Sopenharmony_ci ha->isp_ops->process_mailbox_interrupt(ha, outCount); 19462306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 19562306a36Sopenharmony_ci msleep(10); 19662306a36Sopenharmony_ci } 19762306a36Sopenharmony_ci } else { 19862306a36Sopenharmony_ci /* Do not poll for completion. Use completion queue */ 19962306a36Sopenharmony_ci set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags); 20062306a36Sopenharmony_ci wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ); 20162306a36Sopenharmony_ci clear_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags); 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci /* Check for mailbox timeout. */ 20562306a36Sopenharmony_ci if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) { 20662306a36Sopenharmony_ci if (is_qla80XX(ha) && 20762306a36Sopenharmony_ci test_bit(AF_FW_RECOVERY, &ha->flags)) { 20862306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 20962306a36Sopenharmony_ci "scsi%ld: %s: prematurely completing mbx cmd as " 21062306a36Sopenharmony_ci "firmware recovery detected\n", 21162306a36Sopenharmony_ci ha->host_no, __func__)); 21262306a36Sopenharmony_ci goto mbox_exit; 21362306a36Sopenharmony_ci } 21462306a36Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "scsi%ld: Mailbox Cmd 0x%08X timed out, Scheduling Adapter Reset\n", 21562306a36Sopenharmony_ci ha->host_no, mbx_cmd[0]); 21662306a36Sopenharmony_ci ha->mailbox_timeout_count++; 21762306a36Sopenharmony_ci mbx_sts[0] = (-1); 21862306a36Sopenharmony_ci set_bit(DPC_RESET_HA, &ha->dpc_flags); 21962306a36Sopenharmony_ci if (is_qla8022(ha)) { 22062306a36Sopenharmony_ci ql4_printk(KERN_INFO, ha, 22162306a36Sopenharmony_ci "disabling pause transmit on port 0 & 1.\n"); 22262306a36Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98, 22362306a36Sopenharmony_ci CRB_NIU_XG_PAUSE_CTL_P0 | 22462306a36Sopenharmony_ci CRB_NIU_XG_PAUSE_CTL_P1); 22562306a36Sopenharmony_ci } else if (is_qla8032(ha) || is_qla8042(ha)) { 22662306a36Sopenharmony_ci ql4_printk(KERN_INFO, ha, " %s: disabling pause transmit on port 0 & 1.\n", 22762306a36Sopenharmony_ci __func__); 22862306a36Sopenharmony_ci qla4_83xx_disable_pause(ha); 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci goto mbox_exit; 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci /* 23462306a36Sopenharmony_ci * Copy the mailbox out registers to the caller's mailbox in/out 23562306a36Sopenharmony_ci * structure. 23662306a36Sopenharmony_ci */ 23762306a36Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 23862306a36Sopenharmony_ci for (i = 0; i < outCount; i++) 23962306a36Sopenharmony_ci mbx_sts[i] = ha->mbox_status[i]; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci /* Set return status and error flags (if applicable). */ 24262306a36Sopenharmony_ci switch (ha->mbox_status[0]) { 24362306a36Sopenharmony_ci case MBOX_STS_COMMAND_COMPLETE: 24462306a36Sopenharmony_ci status = QLA_SUCCESS; 24562306a36Sopenharmony_ci break; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci case MBOX_STS_INTERMEDIATE_COMPLETION: 24862306a36Sopenharmony_ci status = QLA_SUCCESS; 24962306a36Sopenharmony_ci break; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci case MBOX_STS_BUSY: 25262306a36Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Cmd = %08X, ISP BUSY\n", 25362306a36Sopenharmony_ci ha->host_no, __func__, mbx_cmd[0]); 25462306a36Sopenharmony_ci ha->mailbox_timeout_count++; 25562306a36Sopenharmony_ci break; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci default: 25862306a36Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: FAILED, MBOX CMD = %08X, MBOX STS = %08X %08X %08X %08X %08X %08X %08X %08X\n", 25962306a36Sopenharmony_ci ha->host_no, __func__, mbx_cmd[0], mbx_sts[0], 26062306a36Sopenharmony_ci mbx_sts[1], mbx_sts[2], mbx_sts[3], mbx_sts[4], 26162306a36Sopenharmony_ci mbx_sts[5], mbx_sts[6], mbx_sts[7]); 26262306a36Sopenharmony_ci break; 26362306a36Sopenharmony_ci } 26462306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cimbox_exit: 26762306a36Sopenharmony_ci mutex_lock(&ha->mbox_sem); 26862306a36Sopenharmony_ci clear_bit(AF_MBOX_COMMAND, &ha->flags); 26962306a36Sopenharmony_ci mutex_unlock(&ha->mbox_sem); 27062306a36Sopenharmony_ci clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci return status; 27362306a36Sopenharmony_ci} 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci/** 27662306a36Sopenharmony_ci * qla4xxx_get_minidump_template - Get the firmware template 27762306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 27862306a36Sopenharmony_ci * @phys_addr: dma address for template 27962306a36Sopenharmony_ci * 28062306a36Sopenharmony_ci * Obtain the minidump template from firmware during initialization 28162306a36Sopenharmony_ci * as it may not be available when minidump is desired. 28262306a36Sopenharmony_ci **/ 28362306a36Sopenharmony_ciint qla4xxx_get_minidump_template(struct scsi_qla_host *ha, 28462306a36Sopenharmony_ci dma_addr_t phys_addr) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 28762306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 28862306a36Sopenharmony_ci int status; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 29162306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_MINIDUMP; 29462306a36Sopenharmony_ci mbox_cmd[1] = MINIDUMP_GET_TMPLT_SUBCOMMAND; 29562306a36Sopenharmony_ci mbox_cmd[2] = LSDW(phys_addr); 29662306a36Sopenharmony_ci mbox_cmd[3] = MSDW(phys_addr); 29762306a36Sopenharmony_ci mbox_cmd[4] = ha->fw_dump_tmplt_size; 29862306a36Sopenharmony_ci mbox_cmd[5] = 0; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], 30162306a36Sopenharmony_ci &mbox_sts[0]); 30262306a36Sopenharmony_ci if (status != QLA_SUCCESS) { 30362306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 30462306a36Sopenharmony_ci "scsi%ld: %s: Cmd = %08X, mbx[0] = 0x%04x, mbx[1] = 0x%04x\n", 30562306a36Sopenharmony_ci ha->host_no, __func__, mbox_cmd[0], 30662306a36Sopenharmony_ci mbox_sts[0], mbox_sts[1])); 30762306a36Sopenharmony_ci } 30862306a36Sopenharmony_ci return status; 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci/** 31262306a36Sopenharmony_ci * qla4xxx_req_template_size - Get minidump template size from firmware. 31362306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 31462306a36Sopenharmony_ci **/ 31562306a36Sopenharmony_ciint qla4xxx_req_template_size(struct scsi_qla_host *ha) 31662306a36Sopenharmony_ci{ 31762306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 31862306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 31962306a36Sopenharmony_ci int status; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 32262306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_MINIDUMP; 32562306a36Sopenharmony_ci mbox_cmd[1] = MINIDUMP_GET_SIZE_SUBCOMMAND; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0], 32862306a36Sopenharmony_ci &mbox_sts[0]); 32962306a36Sopenharmony_ci if (status == QLA_SUCCESS) { 33062306a36Sopenharmony_ci ha->fw_dump_tmplt_size = mbox_sts[1]; 33162306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 33262306a36Sopenharmony_ci "%s: sts[0]=0x%04x, template size=0x%04x, size_cm_02=0x%04x, size_cm_04=0x%04x, size_cm_08=0x%04x, size_cm_10=0x%04x, size_cm_FF=0x%04x, version=0x%04x\n", 33362306a36Sopenharmony_ci __func__, mbox_sts[0], mbox_sts[1], 33462306a36Sopenharmony_ci mbox_sts[2], mbox_sts[3], mbox_sts[4], 33562306a36Sopenharmony_ci mbox_sts[5], mbox_sts[6], mbox_sts[7])); 33662306a36Sopenharmony_ci if (ha->fw_dump_tmplt_size == 0) 33762306a36Sopenharmony_ci status = QLA_ERROR; 33862306a36Sopenharmony_ci } else { 33962306a36Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 34062306a36Sopenharmony_ci "%s: Error sts[0]=0x%04x, mbx[1]=0x%04x\n", 34162306a36Sopenharmony_ci __func__, mbox_sts[0], mbox_sts[1]); 34262306a36Sopenharmony_ci status = QLA_ERROR; 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci return status; 34662306a36Sopenharmony_ci} 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_civoid qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha) 34962306a36Sopenharmony_ci{ 35062306a36Sopenharmony_ci set_bit(AF_FW_RECOVERY, &ha->flags); 35162306a36Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: set FW RECOVERY!\n", 35262306a36Sopenharmony_ci ha->host_no, __func__); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci if (test_bit(AF_MBOX_COMMAND, &ha->flags)) { 35562306a36Sopenharmony_ci if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags)) { 35662306a36Sopenharmony_ci complete(&ha->mbx_intr_comp); 35762306a36Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw " 35862306a36Sopenharmony_ci "recovery, doing premature completion of " 35962306a36Sopenharmony_ci "mbx cmd\n", ha->host_no, __func__); 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci } else { 36262306a36Sopenharmony_ci set_bit(AF_MBOX_COMMAND_DONE, &ha->flags); 36362306a36Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw " 36462306a36Sopenharmony_ci "recovery, doing premature completion of " 36562306a36Sopenharmony_ci "polling mbx cmd\n", ha->host_no, __func__); 36662306a36Sopenharmony_ci } 36762306a36Sopenharmony_ci } 36862306a36Sopenharmony_ci} 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_cistatic uint8_t 37162306a36Sopenharmony_ciqla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, 37262306a36Sopenharmony_ci uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) 37362306a36Sopenharmony_ci{ 37462306a36Sopenharmony_ci memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT); 37562306a36Sopenharmony_ci memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT); 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci if (is_qla8022(ha)) 37862306a36Sopenharmony_ci qla4_82xx_wr_32(ha, ha->nx_db_wr_ptr, 0); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE; 38162306a36Sopenharmony_ci mbox_cmd[1] = 0; 38262306a36Sopenharmony_ci mbox_cmd[2] = LSDW(init_fw_cb_dma); 38362306a36Sopenharmony_ci mbox_cmd[3] = MSDW(init_fw_cb_dma); 38462306a36Sopenharmony_ci mbox_cmd[4] = sizeof(struct addr_ctrl_blk); 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci if (qla4xxx_mailbox_command(ha, 6, 6, mbox_cmd, mbox_sts) != 38762306a36Sopenharmony_ci QLA_SUCCESS) { 38862306a36Sopenharmony_ci DEBUG2(printk(KERN_WARNING "scsi%ld: %s: " 38962306a36Sopenharmony_ci "MBOX_CMD_INITIALIZE_FIRMWARE" 39062306a36Sopenharmony_ci " failed w/ status %04X\n", 39162306a36Sopenharmony_ci ha->host_no, __func__, mbox_sts[0])); 39262306a36Sopenharmony_ci return QLA_ERROR; 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci return QLA_SUCCESS; 39562306a36Sopenharmony_ci} 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ciuint8_t 39862306a36Sopenharmony_ciqla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, 39962306a36Sopenharmony_ci uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT); 40262306a36Sopenharmony_ci memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT); 40362306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK; 40462306a36Sopenharmony_ci mbox_cmd[2] = LSDW(init_fw_cb_dma); 40562306a36Sopenharmony_ci mbox_cmd[3] = MSDW(init_fw_cb_dma); 40662306a36Sopenharmony_ci mbox_cmd[4] = sizeof(struct addr_ctrl_blk); 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci if (qla4xxx_mailbox_command(ha, 5, 5, mbox_cmd, mbox_sts) != 40962306a36Sopenharmony_ci QLA_SUCCESS) { 41062306a36Sopenharmony_ci DEBUG2(printk(KERN_WARNING "scsi%ld: %s: " 41162306a36Sopenharmony_ci "MBOX_CMD_GET_INIT_FW_CTRL_BLOCK" 41262306a36Sopenharmony_ci " failed w/ status %04X\n", 41362306a36Sopenharmony_ci ha->host_no, __func__, mbox_sts[0])); 41462306a36Sopenharmony_ci return QLA_ERROR; 41562306a36Sopenharmony_ci } 41662306a36Sopenharmony_ci return QLA_SUCCESS; 41762306a36Sopenharmony_ci} 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ciuint8_t qla4xxx_set_ipaddr_state(uint8_t fw_ipaddr_state) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci uint8_t ipaddr_state; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci switch (fw_ipaddr_state) { 42462306a36Sopenharmony_ci case IP_ADDRSTATE_UNCONFIGURED: 42562306a36Sopenharmony_ci ipaddr_state = ISCSI_IPDDRESS_STATE_UNCONFIGURED; 42662306a36Sopenharmony_ci break; 42762306a36Sopenharmony_ci case IP_ADDRSTATE_INVALID: 42862306a36Sopenharmony_ci ipaddr_state = ISCSI_IPDDRESS_STATE_INVALID; 42962306a36Sopenharmony_ci break; 43062306a36Sopenharmony_ci case IP_ADDRSTATE_ACQUIRING: 43162306a36Sopenharmony_ci ipaddr_state = ISCSI_IPDDRESS_STATE_ACQUIRING; 43262306a36Sopenharmony_ci break; 43362306a36Sopenharmony_ci case IP_ADDRSTATE_TENTATIVE: 43462306a36Sopenharmony_ci ipaddr_state = ISCSI_IPDDRESS_STATE_TENTATIVE; 43562306a36Sopenharmony_ci break; 43662306a36Sopenharmony_ci case IP_ADDRSTATE_DEPRICATED: 43762306a36Sopenharmony_ci ipaddr_state = ISCSI_IPDDRESS_STATE_DEPRECATED; 43862306a36Sopenharmony_ci break; 43962306a36Sopenharmony_ci case IP_ADDRSTATE_PREFERRED: 44062306a36Sopenharmony_ci ipaddr_state = ISCSI_IPDDRESS_STATE_VALID; 44162306a36Sopenharmony_ci break; 44262306a36Sopenharmony_ci case IP_ADDRSTATE_DISABLING: 44362306a36Sopenharmony_ci ipaddr_state = ISCSI_IPDDRESS_STATE_DISABLING; 44462306a36Sopenharmony_ci break; 44562306a36Sopenharmony_ci default: 44662306a36Sopenharmony_ci ipaddr_state = ISCSI_IPDDRESS_STATE_UNCONFIGURED; 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci return ipaddr_state; 44962306a36Sopenharmony_ci} 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_cistatic void 45262306a36Sopenharmony_ciqla4xxx_update_local_ip(struct scsi_qla_host *ha, 45362306a36Sopenharmony_ci struct addr_ctrl_blk *init_fw_cb) 45462306a36Sopenharmony_ci{ 45562306a36Sopenharmony_ci ha->ip_config.tcp_options = le16_to_cpu(init_fw_cb->ipv4_tcp_opts); 45662306a36Sopenharmony_ci ha->ip_config.ipv4_options = le16_to_cpu(init_fw_cb->ipv4_ip_opts); 45762306a36Sopenharmony_ci ha->ip_config.ipv4_addr_state = 45862306a36Sopenharmony_ci qla4xxx_set_ipaddr_state(init_fw_cb->ipv4_addr_state); 45962306a36Sopenharmony_ci ha->ip_config.eth_mtu_size = 46062306a36Sopenharmony_ci le16_to_cpu(init_fw_cb->eth_mtu_size); 46162306a36Sopenharmony_ci ha->ip_config.ipv4_port = le16_to_cpu(init_fw_cb->ipv4_port); 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci if (ha->acb_version == ACB_SUPPORTED) { 46462306a36Sopenharmony_ci ha->ip_config.ipv6_options = le16_to_cpu(init_fw_cb->ipv6_opts); 46562306a36Sopenharmony_ci ha->ip_config.ipv6_addl_options = 46662306a36Sopenharmony_ci le16_to_cpu(init_fw_cb->ipv6_addtl_opts); 46762306a36Sopenharmony_ci ha->ip_config.ipv6_tcp_options = 46862306a36Sopenharmony_ci le16_to_cpu(init_fw_cb->ipv6_tcp_opts); 46962306a36Sopenharmony_ci } 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci /* Save IPv4 Address Info */ 47262306a36Sopenharmony_ci memcpy(ha->ip_config.ip_address, init_fw_cb->ipv4_addr, 47362306a36Sopenharmony_ci min(sizeof(ha->ip_config.ip_address), 47462306a36Sopenharmony_ci sizeof(init_fw_cb->ipv4_addr))); 47562306a36Sopenharmony_ci memcpy(ha->ip_config.subnet_mask, init_fw_cb->ipv4_subnet, 47662306a36Sopenharmony_ci min(sizeof(ha->ip_config.subnet_mask), 47762306a36Sopenharmony_ci sizeof(init_fw_cb->ipv4_subnet))); 47862306a36Sopenharmony_ci memcpy(ha->ip_config.gateway, init_fw_cb->ipv4_gw_addr, 47962306a36Sopenharmony_ci min(sizeof(ha->ip_config.gateway), 48062306a36Sopenharmony_ci sizeof(init_fw_cb->ipv4_gw_addr))); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci ha->ip_config.ipv4_vlan_tag = be16_to_cpu(init_fw_cb->ipv4_vlan_tag); 48362306a36Sopenharmony_ci ha->ip_config.control = init_fw_cb->control; 48462306a36Sopenharmony_ci ha->ip_config.tcp_wsf = init_fw_cb->ipv4_tcp_wsf; 48562306a36Sopenharmony_ci ha->ip_config.ipv4_tos = init_fw_cb->ipv4_tos; 48662306a36Sopenharmony_ci ha->ip_config.ipv4_cache_id = init_fw_cb->ipv4_cacheid; 48762306a36Sopenharmony_ci ha->ip_config.ipv4_alt_cid_len = init_fw_cb->ipv4_dhcp_alt_cid_len; 48862306a36Sopenharmony_ci memcpy(ha->ip_config.ipv4_alt_cid, init_fw_cb->ipv4_dhcp_alt_cid, 48962306a36Sopenharmony_ci min(sizeof(ha->ip_config.ipv4_alt_cid), 49062306a36Sopenharmony_ci sizeof(init_fw_cb->ipv4_dhcp_alt_cid))); 49162306a36Sopenharmony_ci ha->ip_config.ipv4_vid_len = init_fw_cb->ipv4_dhcp_vid_len; 49262306a36Sopenharmony_ci memcpy(ha->ip_config.ipv4_vid, init_fw_cb->ipv4_dhcp_vid, 49362306a36Sopenharmony_ci min(sizeof(ha->ip_config.ipv4_vid), 49462306a36Sopenharmony_ci sizeof(init_fw_cb->ipv4_dhcp_vid))); 49562306a36Sopenharmony_ci ha->ip_config.ipv4_ttl = init_fw_cb->ipv4_ttl; 49662306a36Sopenharmony_ci ha->ip_config.def_timeout = le16_to_cpu(init_fw_cb->def_timeout); 49762306a36Sopenharmony_ci ha->ip_config.abort_timer = init_fw_cb->abort_timer; 49862306a36Sopenharmony_ci ha->ip_config.iscsi_options = le16_to_cpu(init_fw_cb->iscsi_opts); 49962306a36Sopenharmony_ci ha->ip_config.iscsi_max_pdu_size = 50062306a36Sopenharmony_ci le16_to_cpu(init_fw_cb->iscsi_max_pdu_size); 50162306a36Sopenharmony_ci ha->ip_config.iscsi_first_burst_len = 50262306a36Sopenharmony_ci le16_to_cpu(init_fw_cb->iscsi_fburst_len); 50362306a36Sopenharmony_ci ha->ip_config.iscsi_max_outstnd_r2t = 50462306a36Sopenharmony_ci le16_to_cpu(init_fw_cb->iscsi_max_outstnd_r2t); 50562306a36Sopenharmony_ci ha->ip_config.iscsi_max_burst_len = 50662306a36Sopenharmony_ci le16_to_cpu(init_fw_cb->iscsi_max_burst_len); 50762306a36Sopenharmony_ci memcpy(ha->ip_config.iscsi_name, init_fw_cb->iscsi_name, 50862306a36Sopenharmony_ci min(sizeof(ha->ip_config.iscsi_name), 50962306a36Sopenharmony_ci sizeof(init_fw_cb->iscsi_name))); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci if (is_ipv6_enabled(ha)) { 51262306a36Sopenharmony_ci /* Save IPv6 Address */ 51362306a36Sopenharmony_ci ha->ip_config.ipv6_link_local_state = 51462306a36Sopenharmony_ci qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_lnk_lcl_addr_state); 51562306a36Sopenharmony_ci ha->ip_config.ipv6_addr0_state = 51662306a36Sopenharmony_ci qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_addr0_state); 51762306a36Sopenharmony_ci ha->ip_config.ipv6_addr1_state = 51862306a36Sopenharmony_ci qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_addr1_state); 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci switch (le16_to_cpu(init_fw_cb->ipv6_dflt_rtr_state)) { 52162306a36Sopenharmony_ci case IPV6_RTRSTATE_UNKNOWN: 52262306a36Sopenharmony_ci ha->ip_config.ipv6_default_router_state = 52362306a36Sopenharmony_ci ISCSI_ROUTER_STATE_UNKNOWN; 52462306a36Sopenharmony_ci break; 52562306a36Sopenharmony_ci case IPV6_RTRSTATE_MANUAL: 52662306a36Sopenharmony_ci ha->ip_config.ipv6_default_router_state = 52762306a36Sopenharmony_ci ISCSI_ROUTER_STATE_MANUAL; 52862306a36Sopenharmony_ci break; 52962306a36Sopenharmony_ci case IPV6_RTRSTATE_ADVERTISED: 53062306a36Sopenharmony_ci ha->ip_config.ipv6_default_router_state = 53162306a36Sopenharmony_ci ISCSI_ROUTER_STATE_ADVERTISED; 53262306a36Sopenharmony_ci break; 53362306a36Sopenharmony_ci case IPV6_RTRSTATE_STALE: 53462306a36Sopenharmony_ci ha->ip_config.ipv6_default_router_state = 53562306a36Sopenharmony_ci ISCSI_ROUTER_STATE_STALE; 53662306a36Sopenharmony_ci break; 53762306a36Sopenharmony_ci default: 53862306a36Sopenharmony_ci ha->ip_config.ipv6_default_router_state = 53962306a36Sopenharmony_ci ISCSI_ROUTER_STATE_UNKNOWN; 54062306a36Sopenharmony_ci } 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[0] = 0xFE; 54362306a36Sopenharmony_ci ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[1] = 0x80; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci memcpy(&ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[8], 54662306a36Sopenharmony_ci init_fw_cb->ipv6_if_id, 54762306a36Sopenharmony_ci min(sizeof(ha->ip_config.ipv6_link_local_addr)/2, 54862306a36Sopenharmony_ci sizeof(init_fw_cb->ipv6_if_id))); 54962306a36Sopenharmony_ci memcpy(&ha->ip_config.ipv6_addr0, init_fw_cb->ipv6_addr0, 55062306a36Sopenharmony_ci min(sizeof(ha->ip_config.ipv6_addr0), 55162306a36Sopenharmony_ci sizeof(init_fw_cb->ipv6_addr0))); 55262306a36Sopenharmony_ci memcpy(&ha->ip_config.ipv6_addr1, init_fw_cb->ipv6_addr1, 55362306a36Sopenharmony_ci min(sizeof(ha->ip_config.ipv6_addr1), 55462306a36Sopenharmony_ci sizeof(init_fw_cb->ipv6_addr1))); 55562306a36Sopenharmony_ci memcpy(&ha->ip_config.ipv6_default_router_addr, 55662306a36Sopenharmony_ci init_fw_cb->ipv6_dflt_rtr_addr, 55762306a36Sopenharmony_ci min(sizeof(ha->ip_config.ipv6_default_router_addr), 55862306a36Sopenharmony_ci sizeof(init_fw_cb->ipv6_dflt_rtr_addr))); 55962306a36Sopenharmony_ci ha->ip_config.ipv6_vlan_tag = 56062306a36Sopenharmony_ci be16_to_cpu(init_fw_cb->ipv6_vlan_tag); 56162306a36Sopenharmony_ci ha->ip_config.ipv6_port = le16_to_cpu(init_fw_cb->ipv6_port); 56262306a36Sopenharmony_ci ha->ip_config.ipv6_cache_id = init_fw_cb->ipv6_cache_id; 56362306a36Sopenharmony_ci ha->ip_config.ipv6_flow_lbl = 56462306a36Sopenharmony_ci le16_to_cpu(init_fw_cb->ipv6_flow_lbl); 56562306a36Sopenharmony_ci ha->ip_config.ipv6_traffic_class = 56662306a36Sopenharmony_ci init_fw_cb->ipv6_traffic_class; 56762306a36Sopenharmony_ci ha->ip_config.ipv6_hop_limit = init_fw_cb->ipv6_hop_limit; 56862306a36Sopenharmony_ci ha->ip_config.ipv6_nd_reach_time = 56962306a36Sopenharmony_ci le32_to_cpu(init_fw_cb->ipv6_nd_reach_time); 57062306a36Sopenharmony_ci ha->ip_config.ipv6_nd_rexmit_timer = 57162306a36Sopenharmony_ci le32_to_cpu(init_fw_cb->ipv6_nd_rexmit_timer); 57262306a36Sopenharmony_ci ha->ip_config.ipv6_nd_stale_timeout = 57362306a36Sopenharmony_ci le32_to_cpu(init_fw_cb->ipv6_nd_stale_timeout); 57462306a36Sopenharmony_ci ha->ip_config.ipv6_dup_addr_detect_count = 57562306a36Sopenharmony_ci init_fw_cb->ipv6_dup_addr_detect_count; 57662306a36Sopenharmony_ci ha->ip_config.ipv6_gw_advrt_mtu = 57762306a36Sopenharmony_ci le32_to_cpu(init_fw_cb->ipv6_gw_advrt_mtu); 57862306a36Sopenharmony_ci ha->ip_config.ipv6_tcp_wsf = init_fw_cb->ipv6_tcp_wsf; 57962306a36Sopenharmony_ci } 58062306a36Sopenharmony_ci} 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ciuint8_t 58362306a36Sopenharmony_ciqla4xxx_update_local_ifcb(struct scsi_qla_host *ha, 58462306a36Sopenharmony_ci uint32_t *mbox_cmd, 58562306a36Sopenharmony_ci uint32_t *mbox_sts, 58662306a36Sopenharmony_ci struct addr_ctrl_blk *init_fw_cb, 58762306a36Sopenharmony_ci dma_addr_t init_fw_cb_dma) 58862306a36Sopenharmony_ci{ 58962306a36Sopenharmony_ci if (qla4xxx_get_ifcb(ha, mbox_cmd, mbox_sts, init_fw_cb_dma) 59062306a36Sopenharmony_ci != QLA_SUCCESS) { 59162306a36Sopenharmony_ci DEBUG2(printk(KERN_WARNING 59262306a36Sopenharmony_ci "scsi%ld: %s: Failed to get init_fw_ctrl_blk\n", 59362306a36Sopenharmony_ci ha->host_no, __func__)); 59462306a36Sopenharmony_ci return QLA_ERROR; 59562306a36Sopenharmony_ci } 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci DEBUG2(qla4xxx_dump_buffer(init_fw_cb, sizeof(struct addr_ctrl_blk))); 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci /* Save some info in adapter structure. */ 60062306a36Sopenharmony_ci ha->acb_version = init_fw_cb->acb_version; 60162306a36Sopenharmony_ci ha->firmware_options = le16_to_cpu(init_fw_cb->fw_options); 60262306a36Sopenharmony_ci ha->heartbeat_interval = init_fw_cb->hb_interval; 60362306a36Sopenharmony_ci memcpy(ha->name_string, init_fw_cb->iscsi_name, 60462306a36Sopenharmony_ci min(sizeof(ha->name_string), 60562306a36Sopenharmony_ci sizeof(init_fw_cb->iscsi_name))); 60662306a36Sopenharmony_ci ha->def_timeout = le16_to_cpu(init_fw_cb->def_timeout); 60762306a36Sopenharmony_ci /*memcpy(ha->alias, init_fw_cb->Alias, 60862306a36Sopenharmony_ci min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/ 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci qla4xxx_update_local_ip(ha, init_fw_cb); 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci return QLA_SUCCESS; 61362306a36Sopenharmony_ci} 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci/** 61662306a36Sopenharmony_ci * qla4xxx_initialize_fw_cb - initializes firmware control block. 61762306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 61862306a36Sopenharmony_ci **/ 61962306a36Sopenharmony_ciint qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha) 62062306a36Sopenharmony_ci{ 62162306a36Sopenharmony_ci struct addr_ctrl_blk *init_fw_cb; 62262306a36Sopenharmony_ci dma_addr_t init_fw_cb_dma; 62362306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 62462306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 62562306a36Sopenharmony_ci int status = QLA_ERROR; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci init_fw_cb = dma_alloc_coherent(&ha->pdev->dev, 62862306a36Sopenharmony_ci sizeof(struct addr_ctrl_blk), 62962306a36Sopenharmony_ci &init_fw_cb_dma, GFP_KERNEL); 63062306a36Sopenharmony_ci if (init_fw_cb == NULL) { 63162306a36Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n", 63262306a36Sopenharmony_ci ha->host_no, __func__)); 63362306a36Sopenharmony_ci goto exit_init_fw_cb_no_free; 63462306a36Sopenharmony_ci } 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci /* Get Initialize Firmware Control Block. */ 63762306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 63862306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) != 64162306a36Sopenharmony_ci QLA_SUCCESS) { 64262306a36Sopenharmony_ci goto exit_init_fw_cb; 64362306a36Sopenharmony_ci } 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci /* Fill in the request and response queue information. */ 64662306a36Sopenharmony_ci init_fw_cb->rqq_consumer_idx = cpu_to_le16(ha->request_out); 64762306a36Sopenharmony_ci init_fw_cb->compq_producer_idx = cpu_to_le16(ha->response_in); 64862306a36Sopenharmony_ci init_fw_cb->rqq_len = cpu_to_le16(REQUEST_QUEUE_DEPTH); 64962306a36Sopenharmony_ci init_fw_cb->compq_len = cpu_to_le16(RESPONSE_QUEUE_DEPTH); 65062306a36Sopenharmony_ci init_fw_cb->rqq_addr_lo = cpu_to_le32(LSDW(ha->request_dma)); 65162306a36Sopenharmony_ci init_fw_cb->rqq_addr_hi = cpu_to_le32(MSDW(ha->request_dma)); 65262306a36Sopenharmony_ci init_fw_cb->compq_addr_lo = cpu_to_le32(LSDW(ha->response_dma)); 65362306a36Sopenharmony_ci init_fw_cb->compq_addr_hi = cpu_to_le32(MSDW(ha->response_dma)); 65462306a36Sopenharmony_ci init_fw_cb->shdwreg_addr_lo = cpu_to_le32(LSDW(ha->shadow_regs_dma)); 65562306a36Sopenharmony_ci init_fw_cb->shdwreg_addr_hi = cpu_to_le32(MSDW(ha->shadow_regs_dma)); 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci /* Set up required options. */ 65862306a36Sopenharmony_ci init_fw_cb->fw_options |= 65962306a36Sopenharmony_ci cpu_to_le16(FWOPT_SESSION_MODE | 66062306a36Sopenharmony_ci FWOPT_INITIATOR_MODE); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci if (is_qla80XX(ha)) 66362306a36Sopenharmony_ci init_fw_cb->fw_options |= 66462306a36Sopenharmony_ci cpu_to_le16(FWOPT_ENABLE_CRBDB); 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci init_fw_cb->fw_options &= cpu_to_le16(~FWOPT_TARGET_MODE); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci init_fw_cb->add_fw_options = 0; 66962306a36Sopenharmony_ci init_fw_cb->add_fw_options |= 67062306a36Sopenharmony_ci cpu_to_le16(ADFWOPT_SERIALIZE_TASK_MGMT); 67162306a36Sopenharmony_ci init_fw_cb->add_fw_options |= 67262306a36Sopenharmony_ci cpu_to_le16(ADFWOPT_AUTOCONN_DISABLE); 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci if (qla4xxx_set_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) 67562306a36Sopenharmony_ci != QLA_SUCCESS) { 67662306a36Sopenharmony_ci DEBUG2(printk(KERN_WARNING 67762306a36Sopenharmony_ci "scsi%ld: %s: Failed to set init_fw_ctrl_blk\n", 67862306a36Sopenharmony_ci ha->host_no, __func__)); 67962306a36Sopenharmony_ci goto exit_init_fw_cb; 68062306a36Sopenharmony_ci } 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci if (qla4xxx_update_local_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], 68362306a36Sopenharmony_ci init_fw_cb, init_fw_cb_dma) != QLA_SUCCESS) { 68462306a36Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: Failed to update local ifcb\n", 68562306a36Sopenharmony_ci ha->host_no, __func__)); 68662306a36Sopenharmony_ci goto exit_init_fw_cb; 68762306a36Sopenharmony_ci } 68862306a36Sopenharmony_ci status = QLA_SUCCESS; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ciexit_init_fw_cb: 69162306a36Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk), 69262306a36Sopenharmony_ci init_fw_cb, init_fw_cb_dma); 69362306a36Sopenharmony_ciexit_init_fw_cb_no_free: 69462306a36Sopenharmony_ci return status; 69562306a36Sopenharmony_ci} 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci/** 69862306a36Sopenharmony_ci * qla4xxx_get_dhcp_ip_address - gets HBA ip address via DHCP 69962306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 70062306a36Sopenharmony_ci **/ 70162306a36Sopenharmony_ciint qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha) 70262306a36Sopenharmony_ci{ 70362306a36Sopenharmony_ci struct addr_ctrl_blk *init_fw_cb; 70462306a36Sopenharmony_ci dma_addr_t init_fw_cb_dma; 70562306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 70662306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci init_fw_cb = dma_alloc_coherent(&ha->pdev->dev, 70962306a36Sopenharmony_ci sizeof(struct addr_ctrl_blk), 71062306a36Sopenharmony_ci &init_fw_cb_dma, GFP_KERNEL); 71162306a36Sopenharmony_ci if (init_fw_cb == NULL) { 71262306a36Sopenharmony_ci printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no, 71362306a36Sopenharmony_ci __func__); 71462306a36Sopenharmony_ci return QLA_ERROR; 71562306a36Sopenharmony_ci } 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci /* Get Initialize Firmware Control Block. */ 71862306a36Sopenharmony_ci if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) != 71962306a36Sopenharmony_ci QLA_SUCCESS) { 72062306a36Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n", 72162306a36Sopenharmony_ci ha->host_no, __func__)); 72262306a36Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, 72362306a36Sopenharmony_ci sizeof(struct addr_ctrl_blk), 72462306a36Sopenharmony_ci init_fw_cb, init_fw_cb_dma); 72562306a36Sopenharmony_ci return QLA_ERROR; 72662306a36Sopenharmony_ci } 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci /* Save IP Address. */ 72962306a36Sopenharmony_ci qla4xxx_update_local_ip(ha, init_fw_cb); 73062306a36Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk), 73162306a36Sopenharmony_ci init_fw_cb, init_fw_cb_dma); 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci return QLA_SUCCESS; 73462306a36Sopenharmony_ci} 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci/** 73762306a36Sopenharmony_ci * qla4xxx_get_firmware_state - gets firmware state of HBA 73862306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 73962306a36Sopenharmony_ci **/ 74062306a36Sopenharmony_ciint qla4xxx_get_firmware_state(struct scsi_qla_host * ha) 74162306a36Sopenharmony_ci{ 74262306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 74362306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci /* Get firmware version */ 74662306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 74762306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_FW_STATE; 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 4, &mbox_cmd[0], &mbox_sts[0]) != 75262306a36Sopenharmony_ci QLA_SUCCESS) { 75362306a36Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ " 75462306a36Sopenharmony_ci "status %04X\n", ha->host_no, __func__, 75562306a36Sopenharmony_ci mbox_sts[0])); 75662306a36Sopenharmony_ci return QLA_ERROR; 75762306a36Sopenharmony_ci } 75862306a36Sopenharmony_ci ha->firmware_state = mbox_sts[1]; 75962306a36Sopenharmony_ci ha->board_id = mbox_sts[2]; 76062306a36Sopenharmony_ci ha->addl_fw_state = mbox_sts[3]; 76162306a36Sopenharmony_ci DEBUG2(printk("scsi%ld: %s firmware_state=0x%x\n", 76262306a36Sopenharmony_ci ha->host_no, __func__, ha->firmware_state);) 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci return QLA_SUCCESS; 76562306a36Sopenharmony_ci} 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci/** 76862306a36Sopenharmony_ci * qla4xxx_get_firmware_status - retrieves firmware status 76962306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 77062306a36Sopenharmony_ci **/ 77162306a36Sopenharmony_ciint qla4xxx_get_firmware_status(struct scsi_qla_host * ha) 77262306a36Sopenharmony_ci{ 77362306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 77462306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci /* Get firmware version */ 77762306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 77862306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) != 78362306a36Sopenharmony_ci QLA_SUCCESS) { 78462306a36Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ " 78562306a36Sopenharmony_ci "status %04X\n", ha->host_no, __func__, 78662306a36Sopenharmony_ci mbox_sts[0])); 78762306a36Sopenharmony_ci return QLA_ERROR; 78862306a36Sopenharmony_ci } 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci /* High-water mark of IOCBs */ 79162306a36Sopenharmony_ci ha->iocb_hiwat = mbox_sts[2]; 79262306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 79362306a36Sopenharmony_ci "%s: firmware IOCBs available = %d\n", __func__, 79462306a36Sopenharmony_ci ha->iocb_hiwat)); 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci if (ha->iocb_hiwat > IOCB_HIWAT_CUSHION) 79762306a36Sopenharmony_ci ha->iocb_hiwat -= IOCB_HIWAT_CUSHION; 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci /* Ideally, we should not enter this code, as the # of firmware 80062306a36Sopenharmony_ci * IOCBs is hard-coded in the firmware. We set a default 80162306a36Sopenharmony_ci * iocb_hiwat here just in case */ 80262306a36Sopenharmony_ci if (ha->iocb_hiwat == 0) { 80362306a36Sopenharmony_ci ha->iocb_hiwat = REQUEST_QUEUE_DEPTH / 4; 80462306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, 80562306a36Sopenharmony_ci "%s: Setting IOCB's to = %d\n", __func__, 80662306a36Sopenharmony_ci ha->iocb_hiwat)); 80762306a36Sopenharmony_ci } 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci return QLA_SUCCESS; 81062306a36Sopenharmony_ci} 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci/* 81362306a36Sopenharmony_ci * qla4xxx_get_fwddb_entry - retrieves firmware ddb entry 81462306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 81562306a36Sopenharmony_ci * @fw_ddb_index: Firmware's device database index 81662306a36Sopenharmony_ci * @fw_ddb_entry: Pointer to firmware's device database entry structure 81762306a36Sopenharmony_ci * @num_valid_ddb_entries: Pointer to number of valid ddb entries 81862306a36Sopenharmony_ci * @next_ddb_index: Pointer to next valid device database index 81962306a36Sopenharmony_ci * @fw_ddb_device_state: Pointer to device state 82062306a36Sopenharmony_ci **/ 82162306a36Sopenharmony_ciint qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha, 82262306a36Sopenharmony_ci uint16_t fw_ddb_index, 82362306a36Sopenharmony_ci struct dev_db_entry *fw_ddb_entry, 82462306a36Sopenharmony_ci dma_addr_t fw_ddb_entry_dma, 82562306a36Sopenharmony_ci uint32_t *num_valid_ddb_entries, 82662306a36Sopenharmony_ci uint32_t *next_ddb_index, 82762306a36Sopenharmony_ci uint32_t *fw_ddb_device_state, 82862306a36Sopenharmony_ci uint32_t *conn_err_detail, 82962306a36Sopenharmony_ci uint16_t *tcp_source_port_num, 83062306a36Sopenharmony_ci uint16_t *connection_id) 83162306a36Sopenharmony_ci{ 83262306a36Sopenharmony_ci int status = QLA_ERROR; 83362306a36Sopenharmony_ci uint16_t options; 83462306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 83562306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci /* Make sure the device index is valid */ 83862306a36Sopenharmony_ci if (fw_ddb_index >= MAX_DDB_ENTRIES) { 83962306a36Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: ddb [%d] out of range.\n", 84062306a36Sopenharmony_ci ha->host_no, __func__, fw_ddb_index)); 84162306a36Sopenharmony_ci goto exit_get_fwddb; 84262306a36Sopenharmony_ci } 84362306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 84462306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 84562306a36Sopenharmony_ci if (fw_ddb_entry) 84662306a36Sopenharmony_ci memset(fw_ddb_entry, 0, sizeof(struct dev_db_entry)); 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY; 84962306a36Sopenharmony_ci mbox_cmd[1] = (uint32_t) fw_ddb_index; 85062306a36Sopenharmony_ci mbox_cmd[2] = LSDW(fw_ddb_entry_dma); 85162306a36Sopenharmony_ci mbox_cmd[3] = MSDW(fw_ddb_entry_dma); 85262306a36Sopenharmony_ci mbox_cmd[4] = sizeof(struct dev_db_entry); 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 7, &mbox_cmd[0], &mbox_sts[0]) == 85562306a36Sopenharmony_ci QLA_ERROR) { 85662306a36Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed" 85762306a36Sopenharmony_ci " with status 0x%04X\n", ha->host_no, __func__, 85862306a36Sopenharmony_ci mbox_sts[0])); 85962306a36Sopenharmony_ci goto exit_get_fwddb; 86062306a36Sopenharmony_ci } 86162306a36Sopenharmony_ci if (fw_ddb_index != mbox_sts[1]) { 86262306a36Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: ddb mismatch [%d] != [%d].\n", 86362306a36Sopenharmony_ci ha->host_no, __func__, fw_ddb_index, 86462306a36Sopenharmony_ci mbox_sts[1])); 86562306a36Sopenharmony_ci goto exit_get_fwddb; 86662306a36Sopenharmony_ci } 86762306a36Sopenharmony_ci if (fw_ddb_entry) { 86862306a36Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->options); 86962306a36Sopenharmony_ci if (options & DDB_OPT_IPV6_DEVICE) { 87062306a36Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d " 87162306a36Sopenharmony_ci "Next %d State %04x ConnErr %08x %pI6 " 87262306a36Sopenharmony_ci ":%04d \"%s\"\n", __func__, fw_ddb_index, 87362306a36Sopenharmony_ci mbox_sts[0], mbox_sts[2], mbox_sts[3], 87462306a36Sopenharmony_ci mbox_sts[4], mbox_sts[5], 87562306a36Sopenharmony_ci fw_ddb_entry->ip_addr, 87662306a36Sopenharmony_ci le16_to_cpu(fw_ddb_entry->port), 87762306a36Sopenharmony_ci fw_ddb_entry->iscsi_name); 87862306a36Sopenharmony_ci } else { 87962306a36Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d " 88062306a36Sopenharmony_ci "Next %d State %04x ConnErr %08x %pI4 " 88162306a36Sopenharmony_ci ":%04d \"%s\"\n", __func__, fw_ddb_index, 88262306a36Sopenharmony_ci mbox_sts[0], mbox_sts[2], mbox_sts[3], 88362306a36Sopenharmony_ci mbox_sts[4], mbox_sts[5], 88462306a36Sopenharmony_ci fw_ddb_entry->ip_addr, 88562306a36Sopenharmony_ci le16_to_cpu(fw_ddb_entry->port), 88662306a36Sopenharmony_ci fw_ddb_entry->iscsi_name); 88762306a36Sopenharmony_ci } 88862306a36Sopenharmony_ci } 88962306a36Sopenharmony_ci if (num_valid_ddb_entries) 89062306a36Sopenharmony_ci *num_valid_ddb_entries = mbox_sts[2]; 89162306a36Sopenharmony_ci if (next_ddb_index) 89262306a36Sopenharmony_ci *next_ddb_index = mbox_sts[3]; 89362306a36Sopenharmony_ci if (fw_ddb_device_state) 89462306a36Sopenharmony_ci *fw_ddb_device_state = mbox_sts[4]; 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci /* 89762306a36Sopenharmony_ci * RA: This mailbox has been changed to pass connection error and 89862306a36Sopenharmony_ci * details. Its true for ISP4010 as per Version E - Not sure when it 89962306a36Sopenharmony_ci * was changed. Get the time2wait from the fw_dd_entry field : 90062306a36Sopenharmony_ci * default_time2wait which we call it as minTime2Wait DEV_DB_ENTRY 90162306a36Sopenharmony_ci * struct. 90262306a36Sopenharmony_ci */ 90362306a36Sopenharmony_ci if (conn_err_detail) 90462306a36Sopenharmony_ci *conn_err_detail = mbox_sts[5]; 90562306a36Sopenharmony_ci if (tcp_source_port_num) 90662306a36Sopenharmony_ci *tcp_source_port_num = (uint16_t) (mbox_sts[6] >> 16); 90762306a36Sopenharmony_ci if (connection_id) 90862306a36Sopenharmony_ci *connection_id = (uint16_t) mbox_sts[6] & 0x00FF; 90962306a36Sopenharmony_ci status = QLA_SUCCESS; 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ciexit_get_fwddb: 91262306a36Sopenharmony_ci return status; 91362306a36Sopenharmony_ci} 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ciint qla4xxx_conn_open(struct scsi_qla_host *ha, uint16_t fw_ddb_index) 91662306a36Sopenharmony_ci{ 91762306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 91862306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 91962306a36Sopenharmony_ci int status; 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 92262306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_CONN_OPEN; 92562306a36Sopenharmony_ci mbox_cmd[1] = fw_ddb_index; 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], 92862306a36Sopenharmony_ci &mbox_sts[0]); 92962306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 93062306a36Sopenharmony_ci "%s: status = %d mbx0 = 0x%x mbx1 = 0x%x\n", 93162306a36Sopenharmony_ci __func__, status, mbox_sts[0], mbox_sts[1])); 93262306a36Sopenharmony_ci return status; 93362306a36Sopenharmony_ci} 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci/** 93662306a36Sopenharmony_ci * qla4xxx_set_ddb_entry - sets a ddb entry. 93762306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 93862306a36Sopenharmony_ci * @fw_ddb_index: Firmware's device database index 93962306a36Sopenharmony_ci * @fw_ddb_entry_dma: dma address of ddb entry 94062306a36Sopenharmony_ci * @mbx_sts: mailbox 0 to be returned or NULL 94162306a36Sopenharmony_ci * 94262306a36Sopenharmony_ci * This routine initializes or updates the adapter's device database 94362306a36Sopenharmony_ci * entry for the specified device. 94462306a36Sopenharmony_ci **/ 94562306a36Sopenharmony_ciint qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index, 94662306a36Sopenharmony_ci dma_addr_t fw_ddb_entry_dma, uint32_t *mbx_sts) 94762306a36Sopenharmony_ci{ 94862306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 94962306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 95062306a36Sopenharmony_ci int status; 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci /* Do not wait for completion. The firmware will send us an 95362306a36Sopenharmony_ci * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status. 95462306a36Sopenharmony_ci */ 95562306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 95662306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_SET_DATABASE_ENTRY; 95962306a36Sopenharmony_ci mbox_cmd[1] = (uint32_t) fw_ddb_index; 96062306a36Sopenharmony_ci mbox_cmd[2] = LSDW(fw_ddb_entry_dma); 96162306a36Sopenharmony_ci mbox_cmd[3] = MSDW(fw_ddb_entry_dma); 96262306a36Sopenharmony_ci mbox_cmd[4] = sizeof(struct dev_db_entry); 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], 96562306a36Sopenharmony_ci &mbox_sts[0]); 96662306a36Sopenharmony_ci if (mbx_sts) 96762306a36Sopenharmony_ci *mbx_sts = mbox_sts[0]; 96862306a36Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: status=%d mbx0=0x%x mbx4=0x%x\n", 96962306a36Sopenharmony_ci ha->host_no, __func__, status, mbox_sts[0], mbox_sts[4]);) 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci return status; 97262306a36Sopenharmony_ci} 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ciint qla4xxx_session_logout_ddb(struct scsi_qla_host *ha, 97562306a36Sopenharmony_ci struct ddb_entry *ddb_entry, int options) 97662306a36Sopenharmony_ci{ 97762306a36Sopenharmony_ci int status; 97862306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 97962306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 98262306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT; 98562306a36Sopenharmony_ci mbox_cmd[1] = ddb_entry->fw_ddb_index; 98662306a36Sopenharmony_ci mbox_cmd[3] = options; 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], 98962306a36Sopenharmony_ci &mbox_sts[0]); 99062306a36Sopenharmony_ci if (status != QLA_SUCCESS) { 99162306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 99262306a36Sopenharmony_ci "%s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT " 99362306a36Sopenharmony_ci "failed sts %04X %04X", __func__, 99462306a36Sopenharmony_ci mbox_sts[0], mbox_sts[1])); 99562306a36Sopenharmony_ci if ((mbox_sts[0] == MBOX_STS_COMMAND_ERROR) && 99662306a36Sopenharmony_ci (mbox_sts[1] == DDB_NOT_LOGGED_IN)) { 99762306a36Sopenharmony_ci set_bit(DDB_CONN_CLOSE_FAILURE, &ddb_entry->flags); 99862306a36Sopenharmony_ci } 99962306a36Sopenharmony_ci } 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci return status; 100262306a36Sopenharmony_ci} 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci/** 100562306a36Sopenharmony_ci * qla4xxx_get_crash_record - retrieves crash record. 100662306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 100762306a36Sopenharmony_ci * 100862306a36Sopenharmony_ci * This routine retrieves a crash record from the QLA4010 after an 8002h aen. 100962306a36Sopenharmony_ci **/ 101062306a36Sopenharmony_civoid qla4xxx_get_crash_record(struct scsi_qla_host * ha) 101162306a36Sopenharmony_ci{ 101262306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 101362306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 101462306a36Sopenharmony_ci struct crash_record *crash_record = NULL; 101562306a36Sopenharmony_ci dma_addr_t crash_record_dma = 0; 101662306a36Sopenharmony_ci uint32_t crash_record_size = 0; 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 101962306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_cmd)); 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci /* Get size of crash record. */ 102262306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD; 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != 102562306a36Sopenharmony_ci QLA_SUCCESS) { 102662306a36Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n", 102762306a36Sopenharmony_ci ha->host_no, __func__)); 102862306a36Sopenharmony_ci goto exit_get_crash_record; 102962306a36Sopenharmony_ci } 103062306a36Sopenharmony_ci crash_record_size = mbox_sts[4]; 103162306a36Sopenharmony_ci if (crash_record_size == 0) { 103262306a36Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: ERROR: Crash record size is 0!\n", 103362306a36Sopenharmony_ci ha->host_no, __func__)); 103462306a36Sopenharmony_ci goto exit_get_crash_record; 103562306a36Sopenharmony_ci } 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci /* Alloc Memory for Crash Record. */ 103862306a36Sopenharmony_ci crash_record = dma_alloc_coherent(&ha->pdev->dev, crash_record_size, 103962306a36Sopenharmony_ci &crash_record_dma, GFP_KERNEL); 104062306a36Sopenharmony_ci if (crash_record == NULL) 104162306a36Sopenharmony_ci goto exit_get_crash_record; 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci /* Get Crash Record. */ 104462306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 104562306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_cmd)); 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD; 104862306a36Sopenharmony_ci mbox_cmd[2] = LSDW(crash_record_dma); 104962306a36Sopenharmony_ci mbox_cmd[3] = MSDW(crash_record_dma); 105062306a36Sopenharmony_ci mbox_cmd[4] = crash_record_size; 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != 105362306a36Sopenharmony_ci QLA_SUCCESS) 105462306a36Sopenharmony_ci goto exit_get_crash_record; 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_ci /* Dump Crash Record. */ 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ciexit_get_crash_record: 105962306a36Sopenharmony_ci if (crash_record) 106062306a36Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, crash_record_size, 106162306a36Sopenharmony_ci crash_record, crash_record_dma); 106262306a36Sopenharmony_ci} 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci/** 106562306a36Sopenharmony_ci * qla4xxx_get_conn_event_log - retrieves connection event log 106662306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 106762306a36Sopenharmony_ci **/ 106862306a36Sopenharmony_civoid qla4xxx_get_conn_event_log(struct scsi_qla_host * ha) 106962306a36Sopenharmony_ci{ 107062306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 107162306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 107262306a36Sopenharmony_ci struct conn_event_log_entry *event_log = NULL; 107362306a36Sopenharmony_ci dma_addr_t event_log_dma = 0; 107462306a36Sopenharmony_ci uint32_t event_log_size = 0; 107562306a36Sopenharmony_ci uint32_t num_valid_entries; 107662306a36Sopenharmony_ci uint32_t oldest_entry = 0; 107762306a36Sopenharmony_ci uint32_t max_event_log_entries; 107862306a36Sopenharmony_ci uint8_t i; 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 108162306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_cmd)); 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci /* Get size of crash record. */ 108462306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG; 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != 108762306a36Sopenharmony_ci QLA_SUCCESS) 108862306a36Sopenharmony_ci goto exit_get_event_log; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci event_log_size = mbox_sts[4]; 109162306a36Sopenharmony_ci if (event_log_size == 0) 109262306a36Sopenharmony_ci goto exit_get_event_log; 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci /* Alloc Memory for Crash Record. */ 109562306a36Sopenharmony_ci event_log = dma_alloc_coherent(&ha->pdev->dev, event_log_size, 109662306a36Sopenharmony_ci &event_log_dma, GFP_KERNEL); 109762306a36Sopenharmony_ci if (event_log == NULL) 109862306a36Sopenharmony_ci goto exit_get_event_log; 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci /* Get Crash Record. */ 110162306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 110262306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_cmd)); 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG; 110562306a36Sopenharmony_ci mbox_cmd[2] = LSDW(event_log_dma); 110662306a36Sopenharmony_ci mbox_cmd[3] = MSDW(event_log_dma); 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != 110962306a36Sopenharmony_ci QLA_SUCCESS) { 111062306a36Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event " 111162306a36Sopenharmony_ci "log!\n", ha->host_no, __func__)); 111262306a36Sopenharmony_ci goto exit_get_event_log; 111362306a36Sopenharmony_ci } 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci /* Dump Event Log. */ 111662306a36Sopenharmony_ci num_valid_entries = mbox_sts[1]; 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_ci max_event_log_entries = event_log_size / 111962306a36Sopenharmony_ci sizeof(struct conn_event_log_entry); 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci if (num_valid_entries > max_event_log_entries) 112262306a36Sopenharmony_ci oldest_entry = num_valid_entries % max_event_log_entries; 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci DEBUG3(printk("scsi%ld: Connection Event Log Dump (%d entries):\n", 112562306a36Sopenharmony_ci ha->host_no, num_valid_entries)); 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci if (ql4xextended_error_logging == 3) { 112862306a36Sopenharmony_ci if (oldest_entry == 0) { 112962306a36Sopenharmony_ci /* Circular Buffer has not wrapped around */ 113062306a36Sopenharmony_ci for (i=0; i < num_valid_entries; i++) { 113162306a36Sopenharmony_ci qla4xxx_dump_buffer((uint8_t *)event_log+ 113262306a36Sopenharmony_ci (i*sizeof(*event_log)), 113362306a36Sopenharmony_ci sizeof(*event_log)); 113462306a36Sopenharmony_ci } 113562306a36Sopenharmony_ci } 113662306a36Sopenharmony_ci else { 113762306a36Sopenharmony_ci /* Circular Buffer has wrapped around - 113862306a36Sopenharmony_ci * display accordingly*/ 113962306a36Sopenharmony_ci for (i=oldest_entry; i < max_event_log_entries; i++) { 114062306a36Sopenharmony_ci qla4xxx_dump_buffer((uint8_t *)event_log+ 114162306a36Sopenharmony_ci (i*sizeof(*event_log)), 114262306a36Sopenharmony_ci sizeof(*event_log)); 114362306a36Sopenharmony_ci } 114462306a36Sopenharmony_ci for (i=0; i < oldest_entry; i++) { 114562306a36Sopenharmony_ci qla4xxx_dump_buffer((uint8_t *)event_log+ 114662306a36Sopenharmony_ci (i*sizeof(*event_log)), 114762306a36Sopenharmony_ci sizeof(*event_log)); 114862306a36Sopenharmony_ci } 114962306a36Sopenharmony_ci } 115062306a36Sopenharmony_ci } 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ciexit_get_event_log: 115362306a36Sopenharmony_ci if (event_log) 115462306a36Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, event_log_size, event_log, 115562306a36Sopenharmony_ci event_log_dma); 115662306a36Sopenharmony_ci} 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci/** 115962306a36Sopenharmony_ci * qla4xxx_abort_task - issues Abort Task 116062306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 116162306a36Sopenharmony_ci * @srb: Pointer to srb entry 116262306a36Sopenharmony_ci * 116362306a36Sopenharmony_ci * This routine performs a LUN RESET on the specified target/lun. 116462306a36Sopenharmony_ci * The caller must ensure that the ddb_entry and lun_entry pointers 116562306a36Sopenharmony_ci * are valid before calling this routine. 116662306a36Sopenharmony_ci **/ 116762306a36Sopenharmony_ciint qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb) 116862306a36Sopenharmony_ci{ 116962306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 117062306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 117162306a36Sopenharmony_ci struct scsi_cmnd *cmd = srb->cmd; 117262306a36Sopenharmony_ci int status = QLA_SUCCESS; 117362306a36Sopenharmony_ci unsigned long flags = 0; 117462306a36Sopenharmony_ci uint32_t index; 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ci /* 117762306a36Sopenharmony_ci * Send abort task command to ISP, so that the ISP will return 117862306a36Sopenharmony_ci * request with ABORT status 117962306a36Sopenharmony_ci */ 118062306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 118162306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 118462306a36Sopenharmony_ci index = (unsigned long)(unsigned char *)cmd->host_scribble; 118562306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci /* Firmware already posted completion on response queue */ 118862306a36Sopenharmony_ci if (index == MAX_SRBS) 118962306a36Sopenharmony_ci return status; 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_ABORT_TASK; 119262306a36Sopenharmony_ci mbox_cmd[1] = srb->ddb->fw_ddb_index; 119362306a36Sopenharmony_ci mbox_cmd[2] = index; 119462306a36Sopenharmony_ci /* Immediate Command Enable */ 119562306a36Sopenharmony_ci mbox_cmd[5] = 0x01; 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], 119862306a36Sopenharmony_ci &mbox_sts[0]); 119962306a36Sopenharmony_ci if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE) { 120062306a36Sopenharmony_ci status = QLA_ERROR; 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci DEBUG2(printk(KERN_WARNING "scsi%ld:%d:%llu: abort task FAILED: " 120362306a36Sopenharmony_ci "mbx0=%04X, mb1=%04X, mb2=%04X, mb3=%04X, mb4=%04X\n", 120462306a36Sopenharmony_ci ha->host_no, cmd->device->id, cmd->device->lun, mbox_sts[0], 120562306a36Sopenharmony_ci mbox_sts[1], mbox_sts[2], mbox_sts[3], mbox_sts[4])); 120662306a36Sopenharmony_ci } 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_ci return status; 120962306a36Sopenharmony_ci} 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci/** 121262306a36Sopenharmony_ci * qla4xxx_reset_lun - issues LUN Reset 121362306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 121462306a36Sopenharmony_ci * @ddb_entry: Pointer to device database entry 121562306a36Sopenharmony_ci * @lun: lun number 121662306a36Sopenharmony_ci * 121762306a36Sopenharmony_ci * This routine performs a LUN RESET on the specified target/lun. 121862306a36Sopenharmony_ci * The caller must ensure that the ddb_entry and lun_entry pointers 121962306a36Sopenharmony_ci * are valid before calling this routine. 122062306a36Sopenharmony_ci **/ 122162306a36Sopenharmony_ciint qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry, 122262306a36Sopenharmony_ci uint64_t lun) 122362306a36Sopenharmony_ci{ 122462306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 122562306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 122662306a36Sopenharmony_ci uint32_t scsi_lun[2]; 122762306a36Sopenharmony_ci int status = QLA_SUCCESS; 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci DEBUG2(printk("scsi%ld:%d:%llu: lun reset issued\n", ha->host_no, 123062306a36Sopenharmony_ci ddb_entry->fw_ddb_index, lun)); 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci /* 123362306a36Sopenharmony_ci * Send lun reset command to ISP, so that the ISP will return all 123462306a36Sopenharmony_ci * outstanding requests with RESET status 123562306a36Sopenharmony_ci */ 123662306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 123762306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 123862306a36Sopenharmony_ci int_to_scsilun(lun, (struct scsi_lun *) scsi_lun); 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_LUN_RESET; 124162306a36Sopenharmony_ci mbox_cmd[1] = ddb_entry->fw_ddb_index; 124262306a36Sopenharmony_ci /* FW expects LUN bytes 0-3 in Incoming Mailbox 2 124362306a36Sopenharmony_ci * (LUN byte 0 is LSByte, byte 3 is MSByte) */ 124462306a36Sopenharmony_ci mbox_cmd[2] = cpu_to_le32(scsi_lun[0]); 124562306a36Sopenharmony_ci /* FW expects LUN bytes 4-7 in Incoming Mailbox 3 124662306a36Sopenharmony_ci * (LUN byte 4 is LSByte, byte 7 is MSByte) */ 124762306a36Sopenharmony_ci mbox_cmd[3] = cpu_to_le32(scsi_lun[1]); 124862306a36Sopenharmony_ci mbox_cmd[5] = 0x01; /* Immediate Command Enable */ 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]); 125162306a36Sopenharmony_ci if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE && 125262306a36Sopenharmony_ci mbox_sts[0] != MBOX_STS_COMMAND_ERROR) 125362306a36Sopenharmony_ci status = QLA_ERROR; 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci return status; 125662306a36Sopenharmony_ci} 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci/** 125962306a36Sopenharmony_ci * qla4xxx_reset_target - issues target Reset 126062306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 126162306a36Sopenharmony_ci * @ddb_entry: Pointer to device database entry 126262306a36Sopenharmony_ci * 126362306a36Sopenharmony_ci * This routine performs a TARGET RESET on the specified target. 126462306a36Sopenharmony_ci * The caller must ensure that the ddb_entry pointers 126562306a36Sopenharmony_ci * are valid before calling this routine. 126662306a36Sopenharmony_ci **/ 126762306a36Sopenharmony_ciint qla4xxx_reset_target(struct scsi_qla_host *ha, 126862306a36Sopenharmony_ci struct ddb_entry *ddb_entry) 126962306a36Sopenharmony_ci{ 127062306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 127162306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 127262306a36Sopenharmony_ci int status = QLA_SUCCESS; 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no, 127562306a36Sopenharmony_ci ddb_entry->fw_ddb_index)); 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ci /* 127862306a36Sopenharmony_ci * Send target reset command to ISP, so that the ISP will return all 127962306a36Sopenharmony_ci * outstanding requests with RESET status 128062306a36Sopenharmony_ci */ 128162306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 128262306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_TARGET_WARM_RESET; 128562306a36Sopenharmony_ci mbox_cmd[1] = ddb_entry->fw_ddb_index; 128662306a36Sopenharmony_ci mbox_cmd[5] = 0x01; /* Immediate Command Enable */ 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], 128962306a36Sopenharmony_ci &mbox_sts[0]); 129062306a36Sopenharmony_ci if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE && 129162306a36Sopenharmony_ci mbox_sts[0] != MBOX_STS_COMMAND_ERROR) 129262306a36Sopenharmony_ci status = QLA_ERROR; 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_ci return status; 129562306a36Sopenharmony_ci} 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ciint qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr, 129862306a36Sopenharmony_ci uint32_t offset, uint32_t len) 129962306a36Sopenharmony_ci{ 130062306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 130162306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 130462306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_READ_FLASH; 130762306a36Sopenharmony_ci mbox_cmd[1] = LSDW(dma_addr); 130862306a36Sopenharmony_ci mbox_cmd[2] = MSDW(dma_addr); 130962306a36Sopenharmony_ci mbox_cmd[3] = offset; 131062306a36Sopenharmony_ci mbox_cmd[4] = len; 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], &mbox_sts[0]) != 131362306a36Sopenharmony_ci QLA_SUCCESS) { 131462306a36Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ " 131562306a36Sopenharmony_ci "status %04X %04X, offset %08x, len %08x\n", ha->host_no, 131662306a36Sopenharmony_ci __func__, mbox_sts[0], mbox_sts[1], offset, len)); 131762306a36Sopenharmony_ci return QLA_ERROR; 131862306a36Sopenharmony_ci } 131962306a36Sopenharmony_ci return QLA_SUCCESS; 132062306a36Sopenharmony_ci} 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci/** 132362306a36Sopenharmony_ci * qla4xxx_about_firmware - gets FW, iscsi draft and boot loader version 132462306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 132562306a36Sopenharmony_ci * 132662306a36Sopenharmony_ci * Retrieves the FW version, iSCSI draft version & bootloader version of HBA. 132762306a36Sopenharmony_ci * Mailboxes 2 & 3 may hold an address for data. Make sure that we write 0 to 132862306a36Sopenharmony_ci * those mailboxes, if unused. 132962306a36Sopenharmony_ci **/ 133062306a36Sopenharmony_ciint qla4xxx_about_firmware(struct scsi_qla_host *ha) 133162306a36Sopenharmony_ci{ 133262306a36Sopenharmony_ci struct about_fw_info *about_fw = NULL; 133362306a36Sopenharmony_ci dma_addr_t about_fw_dma; 133462306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 133562306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 133662306a36Sopenharmony_ci int status = QLA_ERROR; 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_ci about_fw = dma_alloc_coherent(&ha->pdev->dev, 133962306a36Sopenharmony_ci sizeof(struct about_fw_info), 134062306a36Sopenharmony_ci &about_fw_dma, GFP_KERNEL); 134162306a36Sopenharmony_ci if (!about_fw) { 134262306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Unable to alloc memory " 134362306a36Sopenharmony_ci "for about_fw\n", __func__)); 134462306a36Sopenharmony_ci return status; 134562306a36Sopenharmony_ci } 134662306a36Sopenharmony_ci 134762306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 134862306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_ABOUT_FW; 135162306a36Sopenharmony_ci mbox_cmd[2] = LSDW(about_fw_dma); 135262306a36Sopenharmony_ci mbox_cmd[3] = MSDW(about_fw_dma); 135362306a36Sopenharmony_ci mbox_cmd[4] = sizeof(struct about_fw_info); 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT, 135662306a36Sopenharmony_ci &mbox_cmd[0], &mbox_sts[0]); 135762306a36Sopenharmony_ci if (status != QLA_SUCCESS) { 135862306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_ABOUT_FW " 135962306a36Sopenharmony_ci "failed w/ status %04X\n", __func__, 136062306a36Sopenharmony_ci mbox_sts[0])); 136162306a36Sopenharmony_ci goto exit_about_fw; 136262306a36Sopenharmony_ci } 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci /* Save version information. */ 136562306a36Sopenharmony_ci ha->fw_info.fw_major = le16_to_cpu(about_fw->fw_major); 136662306a36Sopenharmony_ci ha->fw_info.fw_minor = le16_to_cpu(about_fw->fw_minor); 136762306a36Sopenharmony_ci ha->fw_info.fw_patch = le16_to_cpu(about_fw->fw_patch); 136862306a36Sopenharmony_ci ha->fw_info.fw_build = le16_to_cpu(about_fw->fw_build); 136962306a36Sopenharmony_ci memcpy(ha->fw_info.fw_build_date, about_fw->fw_build_date, 137062306a36Sopenharmony_ci sizeof(about_fw->fw_build_date)); 137162306a36Sopenharmony_ci memcpy(ha->fw_info.fw_build_time, about_fw->fw_build_time, 137262306a36Sopenharmony_ci sizeof(about_fw->fw_build_time)); 137362306a36Sopenharmony_ci strcpy((char *)ha->fw_info.fw_build_user, 137462306a36Sopenharmony_ci skip_spaces((char *)about_fw->fw_build_user)); 137562306a36Sopenharmony_ci ha->fw_info.fw_load_source = le16_to_cpu(about_fw->fw_load_source); 137662306a36Sopenharmony_ci ha->fw_info.iscsi_major = le16_to_cpu(about_fw->iscsi_major); 137762306a36Sopenharmony_ci ha->fw_info.iscsi_minor = le16_to_cpu(about_fw->iscsi_minor); 137862306a36Sopenharmony_ci ha->fw_info.bootload_major = le16_to_cpu(about_fw->bootload_major); 137962306a36Sopenharmony_ci ha->fw_info.bootload_minor = le16_to_cpu(about_fw->bootload_minor); 138062306a36Sopenharmony_ci ha->fw_info.bootload_patch = le16_to_cpu(about_fw->bootload_patch); 138162306a36Sopenharmony_ci ha->fw_info.bootload_build = le16_to_cpu(about_fw->bootload_build); 138262306a36Sopenharmony_ci strcpy((char *)ha->fw_info.extended_timestamp, 138362306a36Sopenharmony_ci skip_spaces((char *)about_fw->extended_timestamp)); 138462306a36Sopenharmony_ci 138562306a36Sopenharmony_ci ha->fw_uptime_secs = le32_to_cpu(mbox_sts[5]); 138662306a36Sopenharmony_ci ha->fw_uptime_msecs = le32_to_cpu(mbox_sts[6]); 138762306a36Sopenharmony_ci status = QLA_SUCCESS; 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ciexit_about_fw: 139062306a36Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(struct about_fw_info), 139162306a36Sopenharmony_ci about_fw, about_fw_dma); 139262306a36Sopenharmony_ci return status; 139362306a36Sopenharmony_ci} 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ciint qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options, 139662306a36Sopenharmony_ci dma_addr_t dma_addr) 139762306a36Sopenharmony_ci{ 139862306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 139962306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 140262306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 140362306a36Sopenharmony_ci 140462306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS; 140562306a36Sopenharmony_ci mbox_cmd[1] = options; 140662306a36Sopenharmony_ci mbox_cmd[2] = LSDW(dma_addr); 140762306a36Sopenharmony_ci mbox_cmd[3] = MSDW(dma_addr); 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) != 141062306a36Sopenharmony_ci QLA_SUCCESS) { 141162306a36Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: failed status %04X\n", 141262306a36Sopenharmony_ci ha->host_no, __func__, mbox_sts[0])); 141362306a36Sopenharmony_ci return QLA_ERROR; 141462306a36Sopenharmony_ci } 141562306a36Sopenharmony_ci return QLA_SUCCESS; 141662306a36Sopenharmony_ci} 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ciint qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index, 141962306a36Sopenharmony_ci uint32_t *mbx_sts) 142062306a36Sopenharmony_ci{ 142162306a36Sopenharmony_ci int status; 142262306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 142362306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 142662306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY; 142962306a36Sopenharmony_ci mbox_cmd[1] = ddb_index; 143062306a36Sopenharmony_ci 143162306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], 143262306a36Sopenharmony_ci &mbox_sts[0]); 143362306a36Sopenharmony_ci if (status != QLA_SUCCESS) { 143462306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", 143562306a36Sopenharmony_ci __func__, mbox_sts[0])); 143662306a36Sopenharmony_ci } 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_ci *mbx_sts = mbox_sts[0]; 143962306a36Sopenharmony_ci return status; 144062306a36Sopenharmony_ci} 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_ciint qla4xxx_clear_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index) 144362306a36Sopenharmony_ci{ 144462306a36Sopenharmony_ci int status; 144562306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 144662306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 144762306a36Sopenharmony_ci 144862306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 144962306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY; 145262306a36Sopenharmony_ci mbox_cmd[1] = ddb_index; 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, 2, 1, &mbox_cmd[0], 145562306a36Sopenharmony_ci &mbox_sts[0]); 145662306a36Sopenharmony_ci if (status != QLA_SUCCESS) { 145762306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", 145862306a36Sopenharmony_ci __func__, mbox_sts[0])); 145962306a36Sopenharmony_ci } 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci return status; 146262306a36Sopenharmony_ci} 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ciint qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr, 146562306a36Sopenharmony_ci uint32_t offset, uint32_t length, uint32_t options) 146662306a36Sopenharmony_ci{ 146762306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 146862306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 146962306a36Sopenharmony_ci int status = QLA_SUCCESS; 147062306a36Sopenharmony_ci 147162306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 147262306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_WRITE_FLASH; 147562306a36Sopenharmony_ci mbox_cmd[1] = LSDW(dma_addr); 147662306a36Sopenharmony_ci mbox_cmd[2] = MSDW(dma_addr); 147762306a36Sopenharmony_ci mbox_cmd[3] = offset; 147862306a36Sopenharmony_ci mbox_cmd[4] = length; 147962306a36Sopenharmony_ci mbox_cmd[5] = options; 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, 6, 2, &mbox_cmd[0], &mbox_sts[0]); 148262306a36Sopenharmony_ci if (status != QLA_SUCCESS) { 148362306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_WRITE_FLASH " 148462306a36Sopenharmony_ci "failed w/ status %04X, mbx1 %04X\n", 148562306a36Sopenharmony_ci __func__, mbox_sts[0], mbox_sts[1])); 148662306a36Sopenharmony_ci } 148762306a36Sopenharmony_ci return status; 148862306a36Sopenharmony_ci} 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_ciint qla4xxx_bootdb_by_index(struct scsi_qla_host *ha, 149162306a36Sopenharmony_ci struct dev_db_entry *fw_ddb_entry, 149262306a36Sopenharmony_ci dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index) 149362306a36Sopenharmony_ci{ 149462306a36Sopenharmony_ci uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO; 149562306a36Sopenharmony_ci uint32_t dev_db_end_offset; 149662306a36Sopenharmony_ci int status = QLA_ERROR; 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_ci memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry)); 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry)); 150162306a36Sopenharmony_ci dev_db_end_offset = FLASH_OFFSET_DB_END; 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci if (dev_db_start_offset > dev_db_end_offset) { 150462306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, 150562306a36Sopenharmony_ci "%s:Invalid DDB index %d", __func__, 150662306a36Sopenharmony_ci ddb_index)); 150762306a36Sopenharmony_ci goto exit_bootdb_failed; 150862306a36Sopenharmony_ci } 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_ci if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset, 151162306a36Sopenharmony_ci sizeof(*fw_ddb_entry)) != QLA_SUCCESS) { 151262306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash" 151362306a36Sopenharmony_ci "failed\n", ha->host_no, __func__); 151462306a36Sopenharmony_ci goto exit_bootdb_failed; 151562306a36Sopenharmony_ci } 151662306a36Sopenharmony_ci 151762306a36Sopenharmony_ci if (fw_ddb_entry->cookie == DDB_VALID_COOKIE) 151862306a36Sopenharmony_ci status = QLA_SUCCESS; 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_ciexit_bootdb_failed: 152162306a36Sopenharmony_ci return status; 152262306a36Sopenharmony_ci} 152362306a36Sopenharmony_ci 152462306a36Sopenharmony_ciint qla4xxx_flashdb_by_index(struct scsi_qla_host *ha, 152562306a36Sopenharmony_ci struct dev_db_entry *fw_ddb_entry, 152662306a36Sopenharmony_ci dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index) 152762306a36Sopenharmony_ci{ 152862306a36Sopenharmony_ci uint32_t dev_db_start_offset; 152962306a36Sopenharmony_ci uint32_t dev_db_end_offset; 153062306a36Sopenharmony_ci int status = QLA_ERROR; 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_ci memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry)); 153362306a36Sopenharmony_ci 153462306a36Sopenharmony_ci if (is_qla40XX(ha)) { 153562306a36Sopenharmony_ci dev_db_start_offset = FLASH_OFFSET_DB_INFO; 153662306a36Sopenharmony_ci dev_db_end_offset = FLASH_OFFSET_DB_END; 153762306a36Sopenharmony_ci } else { 153862306a36Sopenharmony_ci dev_db_start_offset = FLASH_RAW_ACCESS_ADDR + 153962306a36Sopenharmony_ci (ha->hw.flt_region_ddb << 2); 154062306a36Sopenharmony_ci /* flt_ddb_size is DDB table size for both ports 154162306a36Sopenharmony_ci * so divide it by 2 to calculate the offset for second port 154262306a36Sopenharmony_ci */ 154362306a36Sopenharmony_ci if (ha->port_num == 1) 154462306a36Sopenharmony_ci dev_db_start_offset += (ha->hw.flt_ddb_size / 2); 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci dev_db_end_offset = dev_db_start_offset + 154762306a36Sopenharmony_ci (ha->hw.flt_ddb_size / 2); 154862306a36Sopenharmony_ci } 154962306a36Sopenharmony_ci 155062306a36Sopenharmony_ci dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry)); 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ci if (dev_db_start_offset > dev_db_end_offset) { 155362306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, 155462306a36Sopenharmony_ci "%s:Invalid DDB index %d", __func__, 155562306a36Sopenharmony_ci ddb_index)); 155662306a36Sopenharmony_ci goto exit_fdb_failed; 155762306a36Sopenharmony_ci } 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset, 156062306a36Sopenharmony_ci sizeof(*fw_ddb_entry)) != QLA_SUCCESS) { 156162306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash failed\n", 156262306a36Sopenharmony_ci ha->host_no, __func__); 156362306a36Sopenharmony_ci goto exit_fdb_failed; 156462306a36Sopenharmony_ci } 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ci if (fw_ddb_entry->cookie == DDB_VALID_COOKIE) 156762306a36Sopenharmony_ci status = QLA_SUCCESS; 156862306a36Sopenharmony_ci 156962306a36Sopenharmony_ciexit_fdb_failed: 157062306a36Sopenharmony_ci return status; 157162306a36Sopenharmony_ci} 157262306a36Sopenharmony_ci 157362306a36Sopenharmony_ciint qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password, 157462306a36Sopenharmony_ci uint16_t idx) 157562306a36Sopenharmony_ci{ 157662306a36Sopenharmony_ci int ret = 0; 157762306a36Sopenharmony_ci int rval = QLA_ERROR; 157862306a36Sopenharmony_ci uint32_t offset = 0, chap_size; 157962306a36Sopenharmony_ci struct ql4_chap_table *chap_table; 158062306a36Sopenharmony_ci dma_addr_t chap_dma; 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci chap_table = dma_pool_zalloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma); 158362306a36Sopenharmony_ci if (chap_table == NULL) 158462306a36Sopenharmony_ci return -ENOMEM; 158562306a36Sopenharmony_ci 158662306a36Sopenharmony_ci chap_size = sizeof(struct ql4_chap_table); 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_ci if (is_qla40XX(ha)) 158962306a36Sopenharmony_ci offset = FLASH_CHAP_OFFSET | (idx * chap_size); 159062306a36Sopenharmony_ci else { 159162306a36Sopenharmony_ci offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2); 159262306a36Sopenharmony_ci /* flt_chap_size is CHAP table size for both ports 159362306a36Sopenharmony_ci * so divide it by 2 to calculate the offset for second port 159462306a36Sopenharmony_ci */ 159562306a36Sopenharmony_ci if (ha->port_num == 1) 159662306a36Sopenharmony_ci offset += (ha->hw.flt_chap_size / 2); 159762306a36Sopenharmony_ci offset += (idx * chap_size); 159862306a36Sopenharmony_ci } 159962306a36Sopenharmony_ci 160062306a36Sopenharmony_ci rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size); 160162306a36Sopenharmony_ci if (rval != QLA_SUCCESS) { 160262306a36Sopenharmony_ci ret = -EINVAL; 160362306a36Sopenharmony_ci goto exit_get_chap; 160462306a36Sopenharmony_ci } 160562306a36Sopenharmony_ci 160662306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Chap Cookie: x%x\n", 160762306a36Sopenharmony_ci __le16_to_cpu(chap_table->cookie))); 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci if (__le16_to_cpu(chap_table->cookie) != CHAP_VALID_COOKIE) { 161062306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "No valid chap entry found\n"); 161162306a36Sopenharmony_ci goto exit_get_chap; 161262306a36Sopenharmony_ci } 161362306a36Sopenharmony_ci 161462306a36Sopenharmony_ci strscpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); 161562306a36Sopenharmony_ci strscpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); 161662306a36Sopenharmony_ci chap_table->cookie = cpu_to_le16(CHAP_VALID_COOKIE); 161762306a36Sopenharmony_ci 161862306a36Sopenharmony_ciexit_get_chap: 161962306a36Sopenharmony_ci dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma); 162062306a36Sopenharmony_ci return ret; 162162306a36Sopenharmony_ci} 162262306a36Sopenharmony_ci 162362306a36Sopenharmony_ci/** 162462306a36Sopenharmony_ci * qla4xxx_set_chap - Make a chap entry at the given index 162562306a36Sopenharmony_ci * @ha: pointer to adapter structure 162662306a36Sopenharmony_ci * @username: CHAP username to set 162762306a36Sopenharmony_ci * @password: CHAP password to set 162862306a36Sopenharmony_ci * @idx: CHAP index at which to make the entry 162962306a36Sopenharmony_ci * @bidi: type of chap entry (chap_in or chap_out) 163062306a36Sopenharmony_ci * 163162306a36Sopenharmony_ci * Create chap entry at the given index with the information provided. 163262306a36Sopenharmony_ci * 163362306a36Sopenharmony_ci * Note: Caller should acquire the chap lock before getting here. 163462306a36Sopenharmony_ci **/ 163562306a36Sopenharmony_ciint qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, char *password, 163662306a36Sopenharmony_ci uint16_t idx, int bidi) 163762306a36Sopenharmony_ci{ 163862306a36Sopenharmony_ci int ret = 0; 163962306a36Sopenharmony_ci int rval = QLA_ERROR; 164062306a36Sopenharmony_ci uint32_t offset = 0; 164162306a36Sopenharmony_ci struct ql4_chap_table *chap_table; 164262306a36Sopenharmony_ci uint32_t chap_size = 0; 164362306a36Sopenharmony_ci dma_addr_t chap_dma; 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci chap_table = dma_pool_zalloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma); 164662306a36Sopenharmony_ci if (chap_table == NULL) { 164762306a36Sopenharmony_ci ret = -ENOMEM; 164862306a36Sopenharmony_ci goto exit_set_chap; 164962306a36Sopenharmony_ci } 165062306a36Sopenharmony_ci 165162306a36Sopenharmony_ci if (bidi) 165262306a36Sopenharmony_ci chap_table->flags |= BIT_6; /* peer */ 165362306a36Sopenharmony_ci else 165462306a36Sopenharmony_ci chap_table->flags |= BIT_7; /* local */ 165562306a36Sopenharmony_ci chap_table->secret_len = strlen(password); 165662306a36Sopenharmony_ci strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN - 1); 165762306a36Sopenharmony_ci strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN - 1); 165862306a36Sopenharmony_ci chap_table->cookie = cpu_to_le16(CHAP_VALID_COOKIE); 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_ci if (is_qla40XX(ha)) { 166162306a36Sopenharmony_ci chap_size = MAX_CHAP_ENTRIES_40XX * sizeof(*chap_table); 166262306a36Sopenharmony_ci offset = FLASH_CHAP_OFFSET; 166362306a36Sopenharmony_ci } else { /* Single region contains CHAP info for both ports which is 166462306a36Sopenharmony_ci * divided into half for each port. 166562306a36Sopenharmony_ci */ 166662306a36Sopenharmony_ci chap_size = ha->hw.flt_chap_size / 2; 166762306a36Sopenharmony_ci offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2); 166862306a36Sopenharmony_ci if (ha->port_num == 1) 166962306a36Sopenharmony_ci offset += chap_size; 167062306a36Sopenharmony_ci } 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci offset += (idx * sizeof(struct ql4_chap_table)); 167362306a36Sopenharmony_ci rval = qla4xxx_set_flash(ha, chap_dma, offset, 167462306a36Sopenharmony_ci sizeof(struct ql4_chap_table), 167562306a36Sopenharmony_ci FLASH_OPT_RMW_COMMIT); 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_ci if (rval == QLA_SUCCESS && ha->chap_list) { 167862306a36Sopenharmony_ci /* Update ha chap_list cache */ 167962306a36Sopenharmony_ci memcpy((struct ql4_chap_table *)ha->chap_list + idx, 168062306a36Sopenharmony_ci chap_table, sizeof(struct ql4_chap_table)); 168162306a36Sopenharmony_ci } 168262306a36Sopenharmony_ci dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma); 168362306a36Sopenharmony_ci if (rval != QLA_SUCCESS) 168462306a36Sopenharmony_ci ret = -EINVAL; 168562306a36Sopenharmony_ci 168662306a36Sopenharmony_ciexit_set_chap: 168762306a36Sopenharmony_ci return ret; 168862306a36Sopenharmony_ci} 168962306a36Sopenharmony_ci 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ciint qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username, 169262306a36Sopenharmony_ci char *password, uint16_t chap_index) 169362306a36Sopenharmony_ci{ 169462306a36Sopenharmony_ci int rval = QLA_ERROR; 169562306a36Sopenharmony_ci struct ql4_chap_table *chap_table = NULL; 169662306a36Sopenharmony_ci int max_chap_entries; 169762306a36Sopenharmony_ci 169862306a36Sopenharmony_ci if (!ha->chap_list) { 169962306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n"); 170062306a36Sopenharmony_ci rval = QLA_ERROR; 170162306a36Sopenharmony_ci goto exit_uni_chap; 170262306a36Sopenharmony_ci } 170362306a36Sopenharmony_ci 170462306a36Sopenharmony_ci if (!username || !password) { 170562306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "No memory for username & secret\n"); 170662306a36Sopenharmony_ci rval = QLA_ERROR; 170762306a36Sopenharmony_ci goto exit_uni_chap; 170862306a36Sopenharmony_ci } 170962306a36Sopenharmony_ci 171062306a36Sopenharmony_ci if (is_qla80XX(ha)) 171162306a36Sopenharmony_ci max_chap_entries = (ha->hw.flt_chap_size / 2) / 171262306a36Sopenharmony_ci sizeof(struct ql4_chap_table); 171362306a36Sopenharmony_ci else 171462306a36Sopenharmony_ci max_chap_entries = MAX_CHAP_ENTRIES_40XX; 171562306a36Sopenharmony_ci 171662306a36Sopenharmony_ci if (chap_index > max_chap_entries) { 171762306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Invalid Chap index\n"); 171862306a36Sopenharmony_ci rval = QLA_ERROR; 171962306a36Sopenharmony_ci goto exit_uni_chap; 172062306a36Sopenharmony_ci } 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_ci mutex_lock(&ha->chap_sem); 172362306a36Sopenharmony_ci chap_table = (struct ql4_chap_table *)ha->chap_list + chap_index; 172462306a36Sopenharmony_ci if (chap_table->cookie != cpu_to_le16(CHAP_VALID_COOKIE)) { 172562306a36Sopenharmony_ci rval = QLA_ERROR; 172662306a36Sopenharmony_ci goto exit_unlock_uni_chap; 172762306a36Sopenharmony_ci } 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_ci if (!(chap_table->flags & BIT_7)) { 173062306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Unidirectional entry not set\n"); 173162306a36Sopenharmony_ci rval = QLA_ERROR; 173262306a36Sopenharmony_ci goto exit_unlock_uni_chap; 173362306a36Sopenharmony_ci } 173462306a36Sopenharmony_ci 173562306a36Sopenharmony_ci strscpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN); 173662306a36Sopenharmony_ci strscpy(username, chap_table->name, MAX_CHAP_NAME_LEN); 173762306a36Sopenharmony_ci 173862306a36Sopenharmony_ci rval = QLA_SUCCESS; 173962306a36Sopenharmony_ci 174062306a36Sopenharmony_ciexit_unlock_uni_chap: 174162306a36Sopenharmony_ci mutex_unlock(&ha->chap_sem); 174262306a36Sopenharmony_ciexit_uni_chap: 174362306a36Sopenharmony_ci return rval; 174462306a36Sopenharmony_ci} 174562306a36Sopenharmony_ci 174662306a36Sopenharmony_ci/** 174762306a36Sopenharmony_ci * qla4xxx_get_chap_index - Get chap index given username and secret 174862306a36Sopenharmony_ci * @ha: pointer to adapter structure 174962306a36Sopenharmony_ci * @username: CHAP username to be searched 175062306a36Sopenharmony_ci * @password: CHAP password to be searched 175162306a36Sopenharmony_ci * @bidi: Is this a BIDI CHAP 175262306a36Sopenharmony_ci * @chap_index: CHAP index to be returned 175362306a36Sopenharmony_ci * 175462306a36Sopenharmony_ci * Match the username and password in the chap_list, return the index if a 175562306a36Sopenharmony_ci * match is found. If a match is not found then add the entry in FLASH and 175662306a36Sopenharmony_ci * return the index at which entry is written in the FLASH. 175762306a36Sopenharmony_ci **/ 175862306a36Sopenharmony_ciint qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username, 175962306a36Sopenharmony_ci char *password, int bidi, uint16_t *chap_index) 176062306a36Sopenharmony_ci{ 176162306a36Sopenharmony_ci int i, rval; 176262306a36Sopenharmony_ci int free_index = -1; 176362306a36Sopenharmony_ci int found_index = 0; 176462306a36Sopenharmony_ci int max_chap_entries = 0; 176562306a36Sopenharmony_ci struct ql4_chap_table *chap_table; 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_ci if (is_qla80XX(ha)) 176862306a36Sopenharmony_ci max_chap_entries = (ha->hw.flt_chap_size / 2) / 176962306a36Sopenharmony_ci sizeof(struct ql4_chap_table); 177062306a36Sopenharmony_ci else 177162306a36Sopenharmony_ci max_chap_entries = MAX_CHAP_ENTRIES_40XX; 177262306a36Sopenharmony_ci 177362306a36Sopenharmony_ci if (!ha->chap_list) { 177462306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n"); 177562306a36Sopenharmony_ci return QLA_ERROR; 177662306a36Sopenharmony_ci } 177762306a36Sopenharmony_ci 177862306a36Sopenharmony_ci if (!username || !password) { 177962306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Do not have username and psw\n"); 178062306a36Sopenharmony_ci return QLA_ERROR; 178162306a36Sopenharmony_ci } 178262306a36Sopenharmony_ci 178362306a36Sopenharmony_ci mutex_lock(&ha->chap_sem); 178462306a36Sopenharmony_ci for (i = 0; i < max_chap_entries; i++) { 178562306a36Sopenharmony_ci chap_table = (struct ql4_chap_table *)ha->chap_list + i; 178662306a36Sopenharmony_ci if (chap_table->cookie != 178762306a36Sopenharmony_ci cpu_to_le16(CHAP_VALID_COOKIE)) { 178862306a36Sopenharmony_ci if (i > MAX_RESRV_CHAP_IDX && free_index == -1) 178962306a36Sopenharmony_ci free_index = i; 179062306a36Sopenharmony_ci continue; 179162306a36Sopenharmony_ci } 179262306a36Sopenharmony_ci if (bidi) { 179362306a36Sopenharmony_ci if (chap_table->flags & BIT_7) 179462306a36Sopenharmony_ci continue; 179562306a36Sopenharmony_ci } else { 179662306a36Sopenharmony_ci if (chap_table->flags & BIT_6) 179762306a36Sopenharmony_ci continue; 179862306a36Sopenharmony_ci } 179962306a36Sopenharmony_ci if (!strncmp(chap_table->secret, password, 180062306a36Sopenharmony_ci MAX_CHAP_SECRET_LEN) && 180162306a36Sopenharmony_ci !strncmp(chap_table->name, username, 180262306a36Sopenharmony_ci MAX_CHAP_NAME_LEN)) { 180362306a36Sopenharmony_ci *chap_index = i; 180462306a36Sopenharmony_ci found_index = 1; 180562306a36Sopenharmony_ci break; 180662306a36Sopenharmony_ci } 180762306a36Sopenharmony_ci } 180862306a36Sopenharmony_ci 180962306a36Sopenharmony_ci /* If chap entry is not present and a free index is available then 181062306a36Sopenharmony_ci * write the entry in flash 181162306a36Sopenharmony_ci */ 181262306a36Sopenharmony_ci if (!found_index && free_index != -1) { 181362306a36Sopenharmony_ci rval = qla4xxx_set_chap(ha, username, password, 181462306a36Sopenharmony_ci free_index, bidi); 181562306a36Sopenharmony_ci if (!rval) { 181662306a36Sopenharmony_ci *chap_index = free_index; 181762306a36Sopenharmony_ci found_index = 1; 181862306a36Sopenharmony_ci } 181962306a36Sopenharmony_ci } 182062306a36Sopenharmony_ci 182162306a36Sopenharmony_ci mutex_unlock(&ha->chap_sem); 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci if (found_index) 182462306a36Sopenharmony_ci return QLA_SUCCESS; 182562306a36Sopenharmony_ci return QLA_ERROR; 182662306a36Sopenharmony_ci} 182762306a36Sopenharmony_ci 182862306a36Sopenharmony_ciint qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha, 182962306a36Sopenharmony_ci uint16_t fw_ddb_index, 183062306a36Sopenharmony_ci uint16_t connection_id, 183162306a36Sopenharmony_ci uint16_t option) 183262306a36Sopenharmony_ci{ 183362306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 183462306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 183562306a36Sopenharmony_ci int status = QLA_SUCCESS; 183662306a36Sopenharmony_ci 183762306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 183862306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 183962306a36Sopenharmony_ci 184062306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT; 184162306a36Sopenharmony_ci mbox_cmd[1] = fw_ddb_index; 184262306a36Sopenharmony_ci mbox_cmd[2] = connection_id; 184362306a36Sopenharmony_ci mbox_cmd[3] = option; 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]); 184662306a36Sopenharmony_ci if (status != QLA_SUCCESS) { 184762306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_CONN_CLOSE " 184862306a36Sopenharmony_ci "option %04x failed w/ status %04X %04X\n", 184962306a36Sopenharmony_ci __func__, option, mbox_sts[0], mbox_sts[1])); 185062306a36Sopenharmony_ci } 185162306a36Sopenharmony_ci return status; 185262306a36Sopenharmony_ci} 185362306a36Sopenharmony_ci 185462306a36Sopenharmony_ci/** 185562306a36Sopenharmony_ci * qla4_84xx_extend_idc_tmo - Extend IDC Timeout. 185662306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 185762306a36Sopenharmony_ci * @ext_tmo: idc timeout value 185862306a36Sopenharmony_ci * 185962306a36Sopenharmony_ci * Requests firmware to extend the idc timeout value. 186062306a36Sopenharmony_ci **/ 186162306a36Sopenharmony_cistatic int qla4_84xx_extend_idc_tmo(struct scsi_qla_host *ha, uint32_t ext_tmo) 186262306a36Sopenharmony_ci{ 186362306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 186462306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 186562306a36Sopenharmony_ci int status; 186662306a36Sopenharmony_ci 186762306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 186862306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 186962306a36Sopenharmony_ci ext_tmo &= 0xf; 187062306a36Sopenharmony_ci 187162306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_IDC_TIME_EXTEND; 187262306a36Sopenharmony_ci mbox_cmd[1] = ((ha->idc_info.request_desc & 0xfffff0ff) | 187362306a36Sopenharmony_ci (ext_tmo << 8)); /* new timeout */ 187462306a36Sopenharmony_ci mbox_cmd[2] = ha->idc_info.info1; 187562306a36Sopenharmony_ci mbox_cmd[3] = ha->idc_info.info2; 187662306a36Sopenharmony_ci mbox_cmd[4] = ha->idc_info.info3; 187762306a36Sopenharmony_ci 187862306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT, 187962306a36Sopenharmony_ci mbox_cmd, mbox_sts); 188062306a36Sopenharmony_ci if (status != QLA_SUCCESS) { 188162306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 188262306a36Sopenharmony_ci "scsi%ld: %s: failed status %04X\n", 188362306a36Sopenharmony_ci ha->host_no, __func__, mbox_sts[0])); 188462306a36Sopenharmony_ci return QLA_ERROR; 188562306a36Sopenharmony_ci } else { 188662306a36Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: IDC timeout extended by %d secs\n", 188762306a36Sopenharmony_ci __func__, ext_tmo); 188862306a36Sopenharmony_ci } 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_ci return QLA_SUCCESS; 189162306a36Sopenharmony_ci} 189262306a36Sopenharmony_ci 189362306a36Sopenharmony_ciint qla4xxx_disable_acb(struct scsi_qla_host *ha) 189462306a36Sopenharmony_ci{ 189562306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 189662306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 189762306a36Sopenharmony_ci int status = QLA_SUCCESS; 189862306a36Sopenharmony_ci 189962306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 190062306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 190162306a36Sopenharmony_ci 190262306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_DISABLE_ACB; 190362306a36Sopenharmony_ci 190462306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, 8, 5, &mbox_cmd[0], &mbox_sts[0]); 190562306a36Sopenharmony_ci if (status != QLA_SUCCESS) { 190662306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_DISABLE_ACB " 190762306a36Sopenharmony_ci "failed w/ status %04X %04X %04X", __func__, 190862306a36Sopenharmony_ci mbox_sts[0], mbox_sts[1], mbox_sts[2])); 190962306a36Sopenharmony_ci } else { 191062306a36Sopenharmony_ci if (is_qla8042(ha) && 191162306a36Sopenharmony_ci test_bit(DPC_POST_IDC_ACK, &ha->dpc_flags) && 191262306a36Sopenharmony_ci (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE)) { 191362306a36Sopenharmony_ci /* 191462306a36Sopenharmony_ci * Disable ACB mailbox command takes time to complete 191562306a36Sopenharmony_ci * based on the total number of targets connected. 191662306a36Sopenharmony_ci * For 512 targets, it took approximately 5 secs to 191762306a36Sopenharmony_ci * complete. Setting the timeout value to 8, with the 3 191862306a36Sopenharmony_ci * secs buffer. 191962306a36Sopenharmony_ci */ 192062306a36Sopenharmony_ci qla4_84xx_extend_idc_tmo(ha, IDC_EXTEND_TOV); 192162306a36Sopenharmony_ci if (!wait_for_completion_timeout(&ha->disable_acb_comp, 192262306a36Sopenharmony_ci IDC_EXTEND_TOV * HZ)) { 192362306a36Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "%s: Disable ACB Completion not received\n", 192462306a36Sopenharmony_ci __func__); 192562306a36Sopenharmony_ci } 192662306a36Sopenharmony_ci } 192762306a36Sopenharmony_ci } 192862306a36Sopenharmony_ci return status; 192962306a36Sopenharmony_ci} 193062306a36Sopenharmony_ci 193162306a36Sopenharmony_ciint qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma, 193262306a36Sopenharmony_ci uint32_t acb_type, uint32_t len) 193362306a36Sopenharmony_ci{ 193462306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 193562306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 193662306a36Sopenharmony_ci int status = QLA_SUCCESS; 193762306a36Sopenharmony_ci 193862306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 193962306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 194062306a36Sopenharmony_ci 194162306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_ACB; 194262306a36Sopenharmony_ci mbox_cmd[1] = acb_type; 194362306a36Sopenharmony_ci mbox_cmd[2] = LSDW(acb_dma); 194462306a36Sopenharmony_ci mbox_cmd[3] = MSDW(acb_dma); 194562306a36Sopenharmony_ci mbox_cmd[4] = len; 194662306a36Sopenharmony_ci 194762306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]); 194862306a36Sopenharmony_ci if (status != QLA_SUCCESS) { 194962306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_GET_ACB " 195062306a36Sopenharmony_ci "failed w/ status %04X\n", __func__, 195162306a36Sopenharmony_ci mbox_sts[0])); 195262306a36Sopenharmony_ci } 195362306a36Sopenharmony_ci return status; 195462306a36Sopenharmony_ci} 195562306a36Sopenharmony_ci 195662306a36Sopenharmony_ciint qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, 195762306a36Sopenharmony_ci uint32_t *mbox_sts, dma_addr_t acb_dma) 195862306a36Sopenharmony_ci{ 195962306a36Sopenharmony_ci int status = QLA_SUCCESS; 196062306a36Sopenharmony_ci 196162306a36Sopenharmony_ci memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT); 196262306a36Sopenharmony_ci memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT); 196362306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_SET_ACB; 196462306a36Sopenharmony_ci mbox_cmd[1] = 0; /* Primary ACB */ 196562306a36Sopenharmony_ci mbox_cmd[2] = LSDW(acb_dma); 196662306a36Sopenharmony_ci mbox_cmd[3] = MSDW(acb_dma); 196762306a36Sopenharmony_ci mbox_cmd[4] = sizeof(struct addr_ctrl_blk); 196862306a36Sopenharmony_ci 196962306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]); 197062306a36Sopenharmony_ci if (status != QLA_SUCCESS) { 197162306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_SET_ACB " 197262306a36Sopenharmony_ci "failed w/ status %04X\n", __func__, 197362306a36Sopenharmony_ci mbox_sts[0])); 197462306a36Sopenharmony_ci } 197562306a36Sopenharmony_ci return status; 197662306a36Sopenharmony_ci} 197762306a36Sopenharmony_ci 197862306a36Sopenharmony_ciint qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha, 197962306a36Sopenharmony_ci struct ddb_entry *ddb_entry, 198062306a36Sopenharmony_ci struct iscsi_cls_conn *cls_conn, 198162306a36Sopenharmony_ci uint32_t *mbx_sts) 198262306a36Sopenharmony_ci{ 198362306a36Sopenharmony_ci struct dev_db_entry *fw_ddb_entry; 198462306a36Sopenharmony_ci struct iscsi_conn *conn; 198562306a36Sopenharmony_ci struct iscsi_session *sess; 198662306a36Sopenharmony_ci struct qla_conn *qla_conn; 198762306a36Sopenharmony_ci struct sockaddr *dst_addr; 198862306a36Sopenharmony_ci dma_addr_t fw_ddb_entry_dma; 198962306a36Sopenharmony_ci int status = QLA_SUCCESS; 199062306a36Sopenharmony_ci int rval = 0; 199162306a36Sopenharmony_ci struct sockaddr_in *addr; 199262306a36Sopenharmony_ci struct sockaddr_in6 *addr6; 199362306a36Sopenharmony_ci char *ip; 199462306a36Sopenharmony_ci uint16_t iscsi_opts = 0; 199562306a36Sopenharmony_ci uint32_t options = 0; 199662306a36Sopenharmony_ci uint16_t idx, *ptid; 199762306a36Sopenharmony_ci 199862306a36Sopenharmony_ci fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 199962306a36Sopenharmony_ci &fw_ddb_entry_dma, GFP_KERNEL); 200062306a36Sopenharmony_ci if (!fw_ddb_entry) { 200162306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, 200262306a36Sopenharmony_ci "%s: Unable to allocate dma buffer.\n", 200362306a36Sopenharmony_ci __func__)); 200462306a36Sopenharmony_ci rval = -ENOMEM; 200562306a36Sopenharmony_ci goto exit_set_param_no_free; 200662306a36Sopenharmony_ci } 200762306a36Sopenharmony_ci 200862306a36Sopenharmony_ci conn = cls_conn->dd_data; 200962306a36Sopenharmony_ci qla_conn = conn->dd_data; 201062306a36Sopenharmony_ci sess = conn->session; 201162306a36Sopenharmony_ci dst_addr = (struct sockaddr *)&qla_conn->qla_ep->dst_addr; 201262306a36Sopenharmony_ci 201362306a36Sopenharmony_ci if (dst_addr->sa_family == AF_INET6) 201462306a36Sopenharmony_ci options |= IPV6_DEFAULT_DDB_ENTRY; 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_ci status = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma); 201762306a36Sopenharmony_ci if (status == QLA_ERROR) { 201862306a36Sopenharmony_ci rval = -EINVAL; 201962306a36Sopenharmony_ci goto exit_set_param; 202062306a36Sopenharmony_ci } 202162306a36Sopenharmony_ci 202262306a36Sopenharmony_ci ptid = (uint16_t *)&fw_ddb_entry->isid[1]; 202362306a36Sopenharmony_ci *ptid = cpu_to_le16((uint16_t)ddb_entry->sess->target_id); 202462306a36Sopenharmony_ci 202562306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "ISID [%pmR]\n", fw_ddb_entry->isid)); 202662306a36Sopenharmony_ci 202762306a36Sopenharmony_ci iscsi_opts = le16_to_cpu(fw_ddb_entry->iscsi_options); 202862306a36Sopenharmony_ci memset(fw_ddb_entry->iscsi_alias, 0, sizeof(fw_ddb_entry->iscsi_alias)); 202962306a36Sopenharmony_ci 203062306a36Sopenharmony_ci memset(fw_ddb_entry->iscsi_name, 0, sizeof(fw_ddb_entry->iscsi_name)); 203162306a36Sopenharmony_ci 203262306a36Sopenharmony_ci if (sess->targetname != NULL) { 203362306a36Sopenharmony_ci memcpy(fw_ddb_entry->iscsi_name, sess->targetname, 203462306a36Sopenharmony_ci min(strlen(sess->targetname), 203562306a36Sopenharmony_ci sizeof(fw_ddb_entry->iscsi_name))); 203662306a36Sopenharmony_ci } 203762306a36Sopenharmony_ci 203862306a36Sopenharmony_ci memset(fw_ddb_entry->ip_addr, 0, sizeof(fw_ddb_entry->ip_addr)); 203962306a36Sopenharmony_ci memset(fw_ddb_entry->tgt_addr, 0, sizeof(fw_ddb_entry->tgt_addr)); 204062306a36Sopenharmony_ci 204162306a36Sopenharmony_ci fw_ddb_entry->options = DDB_OPT_TARGET | DDB_OPT_AUTO_SENDTGTS_DISABLE; 204262306a36Sopenharmony_ci 204362306a36Sopenharmony_ci if (dst_addr->sa_family == AF_INET) { 204462306a36Sopenharmony_ci addr = (struct sockaddr_in *)dst_addr; 204562306a36Sopenharmony_ci ip = (char *)&addr->sin_addr; 204662306a36Sopenharmony_ci memcpy(fw_ddb_entry->ip_addr, ip, IP_ADDR_LEN); 204762306a36Sopenharmony_ci fw_ddb_entry->port = cpu_to_le16(ntohs(addr->sin_port)); 204862306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 204962306a36Sopenharmony_ci "%s: Destination Address [%pI4]: index [%d]\n", 205062306a36Sopenharmony_ci __func__, fw_ddb_entry->ip_addr, 205162306a36Sopenharmony_ci ddb_entry->fw_ddb_index)); 205262306a36Sopenharmony_ci } else if (dst_addr->sa_family == AF_INET6) { 205362306a36Sopenharmony_ci addr6 = (struct sockaddr_in6 *)dst_addr; 205462306a36Sopenharmony_ci ip = (char *)&addr6->sin6_addr; 205562306a36Sopenharmony_ci memcpy(fw_ddb_entry->ip_addr, ip, IPv6_ADDR_LEN); 205662306a36Sopenharmony_ci fw_ddb_entry->port = cpu_to_le16(ntohs(addr6->sin6_port)); 205762306a36Sopenharmony_ci fw_ddb_entry->options |= DDB_OPT_IPV6_DEVICE; 205862306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 205962306a36Sopenharmony_ci "%s: Destination Address [%pI6]: index [%d]\n", 206062306a36Sopenharmony_ci __func__, fw_ddb_entry->ip_addr, 206162306a36Sopenharmony_ci ddb_entry->fw_ddb_index)); 206262306a36Sopenharmony_ci } else { 206362306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, 206462306a36Sopenharmony_ci "%s: Failed to get IP Address\n", 206562306a36Sopenharmony_ci __func__); 206662306a36Sopenharmony_ci rval = -EINVAL; 206762306a36Sopenharmony_ci goto exit_set_param; 206862306a36Sopenharmony_ci } 206962306a36Sopenharmony_ci 207062306a36Sopenharmony_ci /* CHAP */ 207162306a36Sopenharmony_ci if (sess->username != NULL && sess->password != NULL) { 207262306a36Sopenharmony_ci if (strlen(sess->username) && strlen(sess->password)) { 207362306a36Sopenharmony_ci iscsi_opts |= BIT_7; 207462306a36Sopenharmony_ci 207562306a36Sopenharmony_ci rval = qla4xxx_get_chap_index(ha, sess->username, 207662306a36Sopenharmony_ci sess->password, 207762306a36Sopenharmony_ci LOCAL_CHAP, &idx); 207862306a36Sopenharmony_ci if (rval) 207962306a36Sopenharmony_ci goto exit_set_param; 208062306a36Sopenharmony_ci 208162306a36Sopenharmony_ci fw_ddb_entry->chap_tbl_idx = cpu_to_le16(idx); 208262306a36Sopenharmony_ci } 208362306a36Sopenharmony_ci } 208462306a36Sopenharmony_ci 208562306a36Sopenharmony_ci if (sess->username_in != NULL && sess->password_in != NULL) { 208662306a36Sopenharmony_ci /* Check if BIDI CHAP */ 208762306a36Sopenharmony_ci if (strlen(sess->username_in) && strlen(sess->password_in)) { 208862306a36Sopenharmony_ci iscsi_opts |= BIT_4; 208962306a36Sopenharmony_ci 209062306a36Sopenharmony_ci rval = qla4xxx_get_chap_index(ha, sess->username_in, 209162306a36Sopenharmony_ci sess->password_in, 209262306a36Sopenharmony_ci BIDI_CHAP, &idx); 209362306a36Sopenharmony_ci if (rval) 209462306a36Sopenharmony_ci goto exit_set_param; 209562306a36Sopenharmony_ci } 209662306a36Sopenharmony_ci } 209762306a36Sopenharmony_ci 209862306a36Sopenharmony_ci if (sess->initial_r2t_en) 209962306a36Sopenharmony_ci iscsi_opts |= BIT_10; 210062306a36Sopenharmony_ci 210162306a36Sopenharmony_ci if (sess->imm_data_en) 210262306a36Sopenharmony_ci iscsi_opts |= BIT_11; 210362306a36Sopenharmony_ci 210462306a36Sopenharmony_ci fw_ddb_entry->iscsi_options = cpu_to_le16(iscsi_opts); 210562306a36Sopenharmony_ci 210662306a36Sopenharmony_ci if (conn->max_recv_dlength) 210762306a36Sopenharmony_ci fw_ddb_entry->iscsi_max_rcv_data_seg_len = 210862306a36Sopenharmony_ci cpu_to_le16((conn->max_recv_dlength / BYTE_UNITS)); 210962306a36Sopenharmony_ci 211062306a36Sopenharmony_ci if (sess->max_r2t) 211162306a36Sopenharmony_ci fw_ddb_entry->iscsi_max_outsnd_r2t = cpu_to_le16(sess->max_r2t); 211262306a36Sopenharmony_ci 211362306a36Sopenharmony_ci if (sess->first_burst) 211462306a36Sopenharmony_ci fw_ddb_entry->iscsi_first_burst_len = 211562306a36Sopenharmony_ci cpu_to_le16((sess->first_burst / BYTE_UNITS)); 211662306a36Sopenharmony_ci 211762306a36Sopenharmony_ci if (sess->max_burst) 211862306a36Sopenharmony_ci fw_ddb_entry->iscsi_max_burst_len = 211962306a36Sopenharmony_ci cpu_to_le16((sess->max_burst / BYTE_UNITS)); 212062306a36Sopenharmony_ci 212162306a36Sopenharmony_ci if (sess->time2wait) 212262306a36Sopenharmony_ci fw_ddb_entry->iscsi_def_time2wait = 212362306a36Sopenharmony_ci cpu_to_le16(sess->time2wait); 212462306a36Sopenharmony_ci 212562306a36Sopenharmony_ci if (sess->time2retain) 212662306a36Sopenharmony_ci fw_ddb_entry->iscsi_def_time2retain = 212762306a36Sopenharmony_ci cpu_to_le16(sess->time2retain); 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci status = qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index, 213062306a36Sopenharmony_ci fw_ddb_entry_dma, mbx_sts); 213162306a36Sopenharmony_ci 213262306a36Sopenharmony_ci if (status != QLA_SUCCESS) 213362306a36Sopenharmony_ci rval = -EINVAL; 213462306a36Sopenharmony_ciexit_set_param: 213562306a36Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 213662306a36Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma); 213762306a36Sopenharmony_ciexit_set_param_no_free: 213862306a36Sopenharmony_ci return rval; 213962306a36Sopenharmony_ci} 214062306a36Sopenharmony_ci 214162306a36Sopenharmony_ciint qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index, 214262306a36Sopenharmony_ci uint16_t stats_size, dma_addr_t stats_dma) 214362306a36Sopenharmony_ci{ 214462306a36Sopenharmony_ci int status = QLA_SUCCESS; 214562306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 214662306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 214762306a36Sopenharmony_ci 214862306a36Sopenharmony_ci memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT); 214962306a36Sopenharmony_ci memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT); 215062306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_MANAGEMENT_DATA; 215162306a36Sopenharmony_ci mbox_cmd[1] = fw_ddb_index; 215262306a36Sopenharmony_ci mbox_cmd[2] = LSDW(stats_dma); 215362306a36Sopenharmony_ci mbox_cmd[3] = MSDW(stats_dma); 215462306a36Sopenharmony_ci mbox_cmd[4] = stats_size; 215562306a36Sopenharmony_ci 215662306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, 5, 1, &mbox_cmd[0], &mbox_sts[0]); 215762306a36Sopenharmony_ci if (status != QLA_SUCCESS) { 215862306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, 215962306a36Sopenharmony_ci "%s: MBOX_CMD_GET_MANAGEMENT_DATA " 216062306a36Sopenharmony_ci "failed w/ status %04X\n", __func__, 216162306a36Sopenharmony_ci mbox_sts[0])); 216262306a36Sopenharmony_ci } 216362306a36Sopenharmony_ci return status; 216462306a36Sopenharmony_ci} 216562306a36Sopenharmony_ci 216662306a36Sopenharmony_ciint qla4xxx_get_ip_state(struct scsi_qla_host *ha, uint32_t acb_idx, 216762306a36Sopenharmony_ci uint32_t ip_idx, uint32_t *sts) 216862306a36Sopenharmony_ci{ 216962306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 217062306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 217162306a36Sopenharmony_ci int status = QLA_SUCCESS; 217262306a36Sopenharmony_ci 217362306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 217462306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 217562306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_IP_ADDR_STATE; 217662306a36Sopenharmony_ci mbox_cmd[1] = acb_idx; 217762306a36Sopenharmony_ci mbox_cmd[2] = ip_idx; 217862306a36Sopenharmony_ci 217962306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, 3, 8, &mbox_cmd[0], &mbox_sts[0]); 218062306a36Sopenharmony_ci if (status != QLA_SUCCESS) { 218162306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: " 218262306a36Sopenharmony_ci "MBOX_CMD_GET_IP_ADDR_STATE failed w/ " 218362306a36Sopenharmony_ci "status %04X\n", __func__, mbox_sts[0])); 218462306a36Sopenharmony_ci } 218562306a36Sopenharmony_ci memcpy(sts, mbox_sts, sizeof(mbox_sts)); 218662306a36Sopenharmony_ci return status; 218762306a36Sopenharmony_ci} 218862306a36Sopenharmony_ci 218962306a36Sopenharmony_ciint qla4xxx_get_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma, 219062306a36Sopenharmony_ci uint32_t offset, uint32_t size) 219162306a36Sopenharmony_ci{ 219262306a36Sopenharmony_ci int status = QLA_SUCCESS; 219362306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 219462306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 219562306a36Sopenharmony_ci 219662306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 219762306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 219862306a36Sopenharmony_ci 219962306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_NVRAM; 220062306a36Sopenharmony_ci mbox_cmd[1] = LSDW(nvram_dma); 220162306a36Sopenharmony_ci mbox_cmd[2] = MSDW(nvram_dma); 220262306a36Sopenharmony_ci mbox_cmd[3] = offset; 220362306a36Sopenharmony_ci mbox_cmd[4] = size; 220462306a36Sopenharmony_ci 220562306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], 220662306a36Sopenharmony_ci &mbox_sts[0]); 220762306a36Sopenharmony_ci if (status != QLA_SUCCESS) { 220862306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed " 220962306a36Sopenharmony_ci "status %04X\n", ha->host_no, __func__, 221062306a36Sopenharmony_ci mbox_sts[0])); 221162306a36Sopenharmony_ci } 221262306a36Sopenharmony_ci return status; 221362306a36Sopenharmony_ci} 221462306a36Sopenharmony_ci 221562306a36Sopenharmony_ciint qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma, 221662306a36Sopenharmony_ci uint32_t offset, uint32_t size) 221762306a36Sopenharmony_ci{ 221862306a36Sopenharmony_ci int status = QLA_SUCCESS; 221962306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 222062306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 222162306a36Sopenharmony_ci 222262306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 222362306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 222462306a36Sopenharmony_ci 222562306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_SET_NVRAM; 222662306a36Sopenharmony_ci mbox_cmd[1] = LSDW(nvram_dma); 222762306a36Sopenharmony_ci mbox_cmd[2] = MSDW(nvram_dma); 222862306a36Sopenharmony_ci mbox_cmd[3] = offset; 222962306a36Sopenharmony_ci mbox_cmd[4] = size; 223062306a36Sopenharmony_ci 223162306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], 223262306a36Sopenharmony_ci &mbox_sts[0]); 223362306a36Sopenharmony_ci if (status != QLA_SUCCESS) { 223462306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed " 223562306a36Sopenharmony_ci "status %04X\n", ha->host_no, __func__, 223662306a36Sopenharmony_ci mbox_sts[0])); 223762306a36Sopenharmony_ci } 223862306a36Sopenharmony_ci return status; 223962306a36Sopenharmony_ci} 224062306a36Sopenharmony_ci 224162306a36Sopenharmony_ciint qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha, 224262306a36Sopenharmony_ci uint32_t region, uint32_t field0, 224362306a36Sopenharmony_ci uint32_t field1) 224462306a36Sopenharmony_ci{ 224562306a36Sopenharmony_ci int status = QLA_SUCCESS; 224662306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 224762306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 224862306a36Sopenharmony_ci 224962306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 225062306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 225162306a36Sopenharmony_ci 225262306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_RESTORE_FACTORY_DEFAULTS; 225362306a36Sopenharmony_ci mbox_cmd[3] = region; 225462306a36Sopenharmony_ci mbox_cmd[4] = field0; 225562306a36Sopenharmony_ci mbox_cmd[5] = field1; 225662306a36Sopenharmony_ci 225762306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], 225862306a36Sopenharmony_ci &mbox_sts[0]); 225962306a36Sopenharmony_ci if (status != QLA_SUCCESS) { 226062306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed " 226162306a36Sopenharmony_ci "status %04X\n", ha->host_no, __func__, 226262306a36Sopenharmony_ci mbox_sts[0])); 226362306a36Sopenharmony_ci } 226462306a36Sopenharmony_ci return status; 226562306a36Sopenharmony_ci} 226662306a36Sopenharmony_ci 226762306a36Sopenharmony_ci/** 226862306a36Sopenharmony_ci * qla4_8xxx_set_param - set driver version in firmware. 226962306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 227062306a36Sopenharmony_ci * @param: Parameter to set i.e driver version 227162306a36Sopenharmony_ci **/ 227262306a36Sopenharmony_ciint qla4_8xxx_set_param(struct scsi_qla_host *ha, int param) 227362306a36Sopenharmony_ci{ 227462306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 227562306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 227662306a36Sopenharmony_ci uint32_t status; 227762306a36Sopenharmony_ci 227862306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 227962306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 228062306a36Sopenharmony_ci 228162306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_SET_PARAM; 228262306a36Sopenharmony_ci if (param == SET_DRVR_VERSION) { 228362306a36Sopenharmony_ci mbox_cmd[1] = SET_DRVR_VERSION; 228462306a36Sopenharmony_ci strncpy((char *)&mbox_cmd[2], QLA4XXX_DRIVER_VERSION, 228562306a36Sopenharmony_ci MAX_DRVR_VER_LEN - 1); 228662306a36Sopenharmony_ci } else { 228762306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: invalid parameter 0x%x\n", 228862306a36Sopenharmony_ci __func__, param); 228962306a36Sopenharmony_ci status = QLA_ERROR; 229062306a36Sopenharmony_ci goto exit_set_param; 229162306a36Sopenharmony_ci } 229262306a36Sopenharmony_ci 229362306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, mbox_cmd, 229462306a36Sopenharmony_ci mbox_sts); 229562306a36Sopenharmony_ci if (status == QLA_ERROR) 229662306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", 229762306a36Sopenharmony_ci __func__, mbox_sts[0]); 229862306a36Sopenharmony_ci 229962306a36Sopenharmony_ciexit_set_param: 230062306a36Sopenharmony_ci return status; 230162306a36Sopenharmony_ci} 230262306a36Sopenharmony_ci 230362306a36Sopenharmony_ci/** 230462306a36Sopenharmony_ci * qla4_83xx_post_idc_ack - post IDC ACK 230562306a36Sopenharmony_ci * @ha: Pointer to host adapter structure. 230662306a36Sopenharmony_ci * 230762306a36Sopenharmony_ci * Posts IDC ACK for IDC Request Notification AEN. 230862306a36Sopenharmony_ci **/ 230962306a36Sopenharmony_ciint qla4_83xx_post_idc_ack(struct scsi_qla_host *ha) 231062306a36Sopenharmony_ci{ 231162306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 231262306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 231362306a36Sopenharmony_ci int status; 231462306a36Sopenharmony_ci 231562306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 231662306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 231762306a36Sopenharmony_ci 231862306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_IDC_ACK; 231962306a36Sopenharmony_ci mbox_cmd[1] = ha->idc_info.request_desc; 232062306a36Sopenharmony_ci mbox_cmd[2] = ha->idc_info.info1; 232162306a36Sopenharmony_ci mbox_cmd[3] = ha->idc_info.info2; 232262306a36Sopenharmony_ci mbox_cmd[4] = ha->idc_info.info3; 232362306a36Sopenharmony_ci 232462306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT, 232562306a36Sopenharmony_ci mbox_cmd, mbox_sts); 232662306a36Sopenharmony_ci if (status == QLA_ERROR) 232762306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__, 232862306a36Sopenharmony_ci mbox_sts[0]); 232962306a36Sopenharmony_ci else 233062306a36Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: IDC ACK posted\n", __func__); 233162306a36Sopenharmony_ci 233262306a36Sopenharmony_ci return status; 233362306a36Sopenharmony_ci} 233462306a36Sopenharmony_ci 233562306a36Sopenharmony_ciint qla4_84xx_config_acb(struct scsi_qla_host *ha, int acb_config) 233662306a36Sopenharmony_ci{ 233762306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 233862306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 233962306a36Sopenharmony_ci struct addr_ctrl_blk *acb = NULL; 234062306a36Sopenharmony_ci uint32_t acb_len = sizeof(struct addr_ctrl_blk); 234162306a36Sopenharmony_ci int rval = QLA_SUCCESS; 234262306a36Sopenharmony_ci dma_addr_t acb_dma; 234362306a36Sopenharmony_ci 234462306a36Sopenharmony_ci acb = dma_alloc_coherent(&ha->pdev->dev, 234562306a36Sopenharmony_ci sizeof(struct addr_ctrl_blk), 234662306a36Sopenharmony_ci &acb_dma, GFP_KERNEL); 234762306a36Sopenharmony_ci if (!acb) { 234862306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Unable to alloc acb\n", __func__); 234962306a36Sopenharmony_ci rval = QLA_ERROR; 235062306a36Sopenharmony_ci goto exit_config_acb; 235162306a36Sopenharmony_ci } 235262306a36Sopenharmony_ci memset(acb, 0, acb_len); 235362306a36Sopenharmony_ci 235462306a36Sopenharmony_ci switch (acb_config) { 235562306a36Sopenharmony_ci case ACB_CONFIG_DISABLE: 235662306a36Sopenharmony_ci rval = qla4xxx_get_acb(ha, acb_dma, 0, acb_len); 235762306a36Sopenharmony_ci if (rval != QLA_SUCCESS) 235862306a36Sopenharmony_ci goto exit_free_acb; 235962306a36Sopenharmony_ci 236062306a36Sopenharmony_ci rval = qla4xxx_disable_acb(ha); 236162306a36Sopenharmony_ci if (rval != QLA_SUCCESS) 236262306a36Sopenharmony_ci goto exit_free_acb; 236362306a36Sopenharmony_ci 236462306a36Sopenharmony_ci if (!ha->saved_acb) 236562306a36Sopenharmony_ci ha->saved_acb = kzalloc(acb_len, GFP_KERNEL); 236662306a36Sopenharmony_ci 236762306a36Sopenharmony_ci if (!ha->saved_acb) { 236862306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Unable to alloc acb\n", 236962306a36Sopenharmony_ci __func__); 237062306a36Sopenharmony_ci rval = QLA_ERROR; 237162306a36Sopenharmony_ci goto exit_free_acb; 237262306a36Sopenharmony_ci } 237362306a36Sopenharmony_ci memcpy(ha->saved_acb, acb, acb_len); 237462306a36Sopenharmony_ci break; 237562306a36Sopenharmony_ci case ACB_CONFIG_SET: 237662306a36Sopenharmony_ci 237762306a36Sopenharmony_ci if (!ha->saved_acb) { 237862306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Can't set ACB, Saved ACB not available\n", 237962306a36Sopenharmony_ci __func__); 238062306a36Sopenharmony_ci rval = QLA_ERROR; 238162306a36Sopenharmony_ci goto exit_free_acb; 238262306a36Sopenharmony_ci } 238362306a36Sopenharmony_ci 238462306a36Sopenharmony_ci memcpy(acb, ha->saved_acb, acb_len); 238562306a36Sopenharmony_ci 238662306a36Sopenharmony_ci rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], acb_dma); 238762306a36Sopenharmony_ci if (rval != QLA_SUCCESS) 238862306a36Sopenharmony_ci goto exit_free_acb; 238962306a36Sopenharmony_ci 239062306a36Sopenharmony_ci break; 239162306a36Sopenharmony_ci default: 239262306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Invalid ACB Configuration\n", 239362306a36Sopenharmony_ci __func__); 239462306a36Sopenharmony_ci } 239562306a36Sopenharmony_ci 239662306a36Sopenharmony_ciexit_free_acb: 239762306a36Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk), acb, 239862306a36Sopenharmony_ci acb_dma); 239962306a36Sopenharmony_ciexit_config_acb: 240062306a36Sopenharmony_ci if ((acb_config == ACB_CONFIG_SET) && ha->saved_acb) { 240162306a36Sopenharmony_ci kfree(ha->saved_acb); 240262306a36Sopenharmony_ci ha->saved_acb = NULL; 240362306a36Sopenharmony_ci } 240462306a36Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 240562306a36Sopenharmony_ci "%s %s\n", __func__, 240662306a36Sopenharmony_ci rval == QLA_SUCCESS ? "SUCCEEDED" : "FAILED")); 240762306a36Sopenharmony_ci return rval; 240862306a36Sopenharmony_ci} 240962306a36Sopenharmony_ci 241062306a36Sopenharmony_ciint qla4_83xx_get_port_config(struct scsi_qla_host *ha, uint32_t *config) 241162306a36Sopenharmony_ci{ 241262306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 241362306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 241462306a36Sopenharmony_ci int status; 241562306a36Sopenharmony_ci 241662306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 241762306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 241862306a36Sopenharmony_ci 241962306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_PORT_CONFIG; 242062306a36Sopenharmony_ci 242162306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT, 242262306a36Sopenharmony_ci mbox_cmd, mbox_sts); 242362306a36Sopenharmony_ci if (status == QLA_SUCCESS) 242462306a36Sopenharmony_ci *config = mbox_sts[1]; 242562306a36Sopenharmony_ci else 242662306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__, 242762306a36Sopenharmony_ci mbox_sts[0]); 242862306a36Sopenharmony_ci 242962306a36Sopenharmony_ci return status; 243062306a36Sopenharmony_ci} 243162306a36Sopenharmony_ci 243262306a36Sopenharmony_ciint qla4_83xx_set_port_config(struct scsi_qla_host *ha, uint32_t *config) 243362306a36Sopenharmony_ci{ 243462306a36Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 243562306a36Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 243662306a36Sopenharmony_ci int status; 243762306a36Sopenharmony_ci 243862306a36Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 243962306a36Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 244062306a36Sopenharmony_ci 244162306a36Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_SET_PORT_CONFIG; 244262306a36Sopenharmony_ci mbox_cmd[1] = *config; 244362306a36Sopenharmony_ci 244462306a36Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT, 244562306a36Sopenharmony_ci mbox_cmd, mbox_sts); 244662306a36Sopenharmony_ci if (status != QLA_SUCCESS) 244762306a36Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__, 244862306a36Sopenharmony_ci mbox_sts[0]); 244962306a36Sopenharmony_ci 245062306a36Sopenharmony_ci return status; 245162306a36Sopenharmony_ci} 2452