18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * QLogic iSCSI HBA Driver 48c2ecf20Sopenharmony_ci * Copyright (c) 2003-2013 QLogic Corporation 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/ctype.h> 88c2ecf20Sopenharmony_ci#include "ql4_def.h" 98c2ecf20Sopenharmony_ci#include "ql4_glbl.h" 108c2ecf20Sopenharmony_ci#include "ql4_dbg.h" 118c2ecf20Sopenharmony_ci#include "ql4_inline.h" 128c2ecf20Sopenharmony_ci#include "ql4_version.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_civoid qla4xxx_queue_mbox_cmd(struct scsi_qla_host *ha, uint32_t *mbx_cmd, 158c2ecf20Sopenharmony_ci int in_count) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci int i; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci /* Load all mailbox registers, except mailbox 0. */ 208c2ecf20Sopenharmony_ci for (i = 1; i < in_count; i++) 218c2ecf20Sopenharmony_ci writel(mbx_cmd[i], &ha->reg->mailbox[i]); 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci /* Wakeup firmware */ 248c2ecf20Sopenharmony_ci writel(mbx_cmd[0], &ha->reg->mailbox[0]); 258c2ecf20Sopenharmony_ci readl(&ha->reg->mailbox[0]); 268c2ecf20Sopenharmony_ci writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status); 278c2ecf20Sopenharmony_ci readl(&ha->reg->ctrl_status); 288c2ecf20Sopenharmony_ci} 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_civoid qla4xxx_process_mbox_intr(struct scsi_qla_host *ha, int out_count) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci int intr_status; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci intr_status = readl(&ha->reg->ctrl_status); 358c2ecf20Sopenharmony_ci if (intr_status & INTR_PENDING) { 368c2ecf20Sopenharmony_ci /* 378c2ecf20Sopenharmony_ci * Service the interrupt. 388c2ecf20Sopenharmony_ci * The ISR will save the mailbox status registers 398c2ecf20Sopenharmony_ci * to a temporary storage location in the adapter structure. 408c2ecf20Sopenharmony_ci */ 418c2ecf20Sopenharmony_ci ha->mbox_status_count = out_count; 428c2ecf20Sopenharmony_ci ha->isp_ops->interrupt_service_routine(ha, intr_status); 438c2ecf20Sopenharmony_ci } 448c2ecf20Sopenharmony_ci} 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/** 478c2ecf20Sopenharmony_ci * qla4xxx_is_intr_poll_mode – Are we allowed to poll for interrupts? 488c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 498c2ecf20Sopenharmony_ci * returns: 1=polling mode, 0=non-polling mode 508c2ecf20Sopenharmony_ci **/ 518c2ecf20Sopenharmony_cistatic int qla4xxx_is_intr_poll_mode(struct scsi_qla_host *ha) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci int rval = 1; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (is_qla8032(ha) || is_qla8042(ha)) { 568c2ecf20Sopenharmony_ci if (test_bit(AF_IRQ_ATTACHED, &ha->flags) && 578c2ecf20Sopenharmony_ci test_bit(AF_83XX_MBOX_INTR_ON, &ha->flags)) 588c2ecf20Sopenharmony_ci rval = 0; 598c2ecf20Sopenharmony_ci } else { 608c2ecf20Sopenharmony_ci if (test_bit(AF_IRQ_ATTACHED, &ha->flags) && 618c2ecf20Sopenharmony_ci test_bit(AF_INTERRUPTS_ON, &ha->flags) && 628c2ecf20Sopenharmony_ci test_bit(AF_ONLINE, &ha->flags) && 638c2ecf20Sopenharmony_ci !test_bit(AF_HA_REMOVAL, &ha->flags)) 648c2ecf20Sopenharmony_ci rval = 0; 658c2ecf20Sopenharmony_ci } 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci return rval; 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci/** 718c2ecf20Sopenharmony_ci * qla4xxx_mailbox_command - issues mailbox commands 728c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 738c2ecf20Sopenharmony_ci * @inCount: number of mailbox registers to load. 748c2ecf20Sopenharmony_ci * @outCount: number of mailbox registers to return. 758c2ecf20Sopenharmony_ci * @mbx_cmd: data pointer for mailbox in registers. 768c2ecf20Sopenharmony_ci * @mbx_sts: data pointer for mailbox out registers. 778c2ecf20Sopenharmony_ci * 788c2ecf20Sopenharmony_ci * This routine issue mailbox commands and waits for completion. 798c2ecf20Sopenharmony_ci * If outCount is 0, this routine completes successfully WITHOUT waiting 808c2ecf20Sopenharmony_ci * for the mailbox command to complete. 818c2ecf20Sopenharmony_ci **/ 828c2ecf20Sopenharmony_ciint qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, 838c2ecf20Sopenharmony_ci uint8_t outCount, uint32_t *mbx_cmd, 848c2ecf20Sopenharmony_ci uint32_t *mbx_sts) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci int status = QLA_ERROR; 878c2ecf20Sopenharmony_ci uint8_t i; 888c2ecf20Sopenharmony_ci u_long wait_count; 898c2ecf20Sopenharmony_ci unsigned long flags = 0; 908c2ecf20Sopenharmony_ci uint32_t dev_state; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci /* Make sure that pointers are valid */ 938c2ecf20Sopenharmony_ci if (!mbx_cmd || !mbx_sts) { 948c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts " 958c2ecf20Sopenharmony_ci "pointer\n", ha->host_no, __func__)); 968c2ecf20Sopenharmony_ci return status; 978c2ecf20Sopenharmony_ci } 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci if (is_qla40XX(ha)) { 1008c2ecf20Sopenharmony_ci if (test_bit(AF_HA_REMOVAL, &ha->flags)) { 1018c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: " 1028c2ecf20Sopenharmony_ci "prematurely completing mbx cmd as " 1038c2ecf20Sopenharmony_ci "adapter removal detected\n", 1048c2ecf20Sopenharmony_ci ha->host_no, __func__)); 1058c2ecf20Sopenharmony_ci return status; 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci if ((is_aer_supported(ha)) && 1108c2ecf20Sopenharmony_ci (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) { 1118c2ecf20Sopenharmony_ci DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, " 1128c2ecf20Sopenharmony_ci "timeout MBX Exiting.\n", ha->host_no, __func__)); 1138c2ecf20Sopenharmony_ci return status; 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci /* Mailbox code active */ 1178c2ecf20Sopenharmony_ci wait_count = MBOX_TOV * 100; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci while (wait_count--) { 1208c2ecf20Sopenharmony_ci mutex_lock(&ha->mbox_sem); 1218c2ecf20Sopenharmony_ci if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) { 1228c2ecf20Sopenharmony_ci set_bit(AF_MBOX_COMMAND, &ha->flags); 1238c2ecf20Sopenharmony_ci mutex_unlock(&ha->mbox_sem); 1248c2ecf20Sopenharmony_ci break; 1258c2ecf20Sopenharmony_ci } 1268c2ecf20Sopenharmony_ci mutex_unlock(&ha->mbox_sem); 1278c2ecf20Sopenharmony_ci if (!wait_count) { 1288c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n", 1298c2ecf20Sopenharmony_ci ha->host_no, __func__)); 1308c2ecf20Sopenharmony_ci return status; 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci msleep(10); 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) { 1368c2ecf20Sopenharmony_ci if (test_bit(AF_FW_RECOVERY, &ha->flags)) { 1378c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, 1388c2ecf20Sopenharmony_ci "scsi%ld: %s: prematurely completing mbx cmd as firmware recovery detected\n", 1398c2ecf20Sopenharmony_ci ha->host_no, __func__)); 1408c2ecf20Sopenharmony_ci goto mbox_exit; 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci /* Do not send any mbx cmd if h/w is in failed state*/ 1438c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 1448c2ecf20Sopenharmony_ci dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE); 1458c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 1468c2ecf20Sopenharmony_ci if (dev_state == QLA8XXX_DEV_FAILED) { 1478c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 1488c2ecf20Sopenharmony_ci "scsi%ld: %s: H/W is in failed state, do not send any mailbox commands\n", 1498c2ecf20Sopenharmony_ci ha->host_no, __func__); 1508c2ecf20Sopenharmony_ci goto mbox_exit; 1518c2ecf20Sopenharmony_ci } 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci ha->mbox_status_count = outCount; 1578c2ecf20Sopenharmony_ci for (i = 0; i < outCount; i++) 1588c2ecf20Sopenharmony_ci ha->mbox_status[i] = 0; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /* Queue the mailbox command to the firmware */ 1618c2ecf20Sopenharmony_ci ha->isp_ops->queue_mailbox_command(ha, mbx_cmd, inCount); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci /* Wait for completion */ 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci /* 1688c2ecf20Sopenharmony_ci * If we don't want status, don't wait for the mailbox command to 1698c2ecf20Sopenharmony_ci * complete. For example, MBOX_CMD_RESET_FW doesn't return status, 1708c2ecf20Sopenharmony_ci * you must poll the inbound Interrupt Mask for completion. 1718c2ecf20Sopenharmony_ci */ 1728c2ecf20Sopenharmony_ci if (outCount == 0) { 1738c2ecf20Sopenharmony_ci status = QLA_SUCCESS; 1748c2ecf20Sopenharmony_ci goto mbox_exit; 1758c2ecf20Sopenharmony_ci } 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci /* 1788c2ecf20Sopenharmony_ci * Wait for completion: Poll or completion queue 1798c2ecf20Sopenharmony_ci */ 1808c2ecf20Sopenharmony_ci if (qla4xxx_is_intr_poll_mode(ha)) { 1818c2ecf20Sopenharmony_ci /* Poll for command to complete */ 1828c2ecf20Sopenharmony_ci wait_count = jiffies + MBOX_TOV * HZ; 1838c2ecf20Sopenharmony_ci while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) { 1848c2ecf20Sopenharmony_ci if (time_after_eq(jiffies, wait_count)) 1858c2ecf20Sopenharmony_ci break; 1868c2ecf20Sopenharmony_ci /* 1878c2ecf20Sopenharmony_ci * Service the interrupt. 1888c2ecf20Sopenharmony_ci * The ISR will save the mailbox status registers 1898c2ecf20Sopenharmony_ci * to a temporary storage location in the adapter 1908c2ecf20Sopenharmony_ci * structure. 1918c2ecf20Sopenharmony_ci */ 1928c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 1938c2ecf20Sopenharmony_ci ha->isp_ops->process_mailbox_interrupt(ha, outCount); 1948c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 1958c2ecf20Sopenharmony_ci msleep(10); 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci } else { 1988c2ecf20Sopenharmony_ci /* Do not poll for completion. Use completion queue */ 1998c2ecf20Sopenharmony_ci set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags); 2008c2ecf20Sopenharmony_ci wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ); 2018c2ecf20Sopenharmony_ci clear_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags); 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci /* Check for mailbox timeout. */ 2058c2ecf20Sopenharmony_ci if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) { 2068c2ecf20Sopenharmony_ci if (is_qla80XX(ha) && 2078c2ecf20Sopenharmony_ci test_bit(AF_FW_RECOVERY, &ha->flags)) { 2088c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 2098c2ecf20Sopenharmony_ci "scsi%ld: %s: prematurely completing mbx cmd as " 2108c2ecf20Sopenharmony_ci "firmware recovery detected\n", 2118c2ecf20Sopenharmony_ci ha->host_no, __func__)); 2128c2ecf20Sopenharmony_ci goto mbox_exit; 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "scsi%ld: Mailbox Cmd 0x%08X timed out, Scheduling Adapter Reset\n", 2158c2ecf20Sopenharmony_ci ha->host_no, mbx_cmd[0]); 2168c2ecf20Sopenharmony_ci ha->mailbox_timeout_count++; 2178c2ecf20Sopenharmony_ci mbx_sts[0] = (-1); 2188c2ecf20Sopenharmony_ci set_bit(DPC_RESET_HA, &ha->dpc_flags); 2198c2ecf20Sopenharmony_ci if (is_qla8022(ha)) { 2208c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 2218c2ecf20Sopenharmony_ci "disabling pause transmit on port 0 & 1.\n"); 2228c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98, 2238c2ecf20Sopenharmony_ci CRB_NIU_XG_PAUSE_CTL_P0 | 2248c2ecf20Sopenharmony_ci CRB_NIU_XG_PAUSE_CTL_P1); 2258c2ecf20Sopenharmony_ci } else if (is_qla8032(ha) || is_qla8042(ha)) { 2268c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, " %s: disabling pause transmit on port 0 & 1.\n", 2278c2ecf20Sopenharmony_ci __func__); 2288c2ecf20Sopenharmony_ci qla4_83xx_disable_pause(ha); 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci goto mbox_exit; 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci /* 2348c2ecf20Sopenharmony_ci * Copy the mailbox out registers to the caller's mailbox in/out 2358c2ecf20Sopenharmony_ci * structure. 2368c2ecf20Sopenharmony_ci */ 2378c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 2388c2ecf20Sopenharmony_ci for (i = 0; i < outCount; i++) 2398c2ecf20Sopenharmony_ci mbx_sts[i] = ha->mbox_status[i]; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci /* Set return status and error flags (if applicable). */ 2428c2ecf20Sopenharmony_ci switch (ha->mbox_status[0]) { 2438c2ecf20Sopenharmony_ci case MBOX_STS_COMMAND_COMPLETE: 2448c2ecf20Sopenharmony_ci status = QLA_SUCCESS; 2458c2ecf20Sopenharmony_ci break; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci case MBOX_STS_INTERMEDIATE_COMPLETION: 2488c2ecf20Sopenharmony_ci status = QLA_SUCCESS; 2498c2ecf20Sopenharmony_ci break; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci case MBOX_STS_BUSY: 2528c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Cmd = %08X, ISP BUSY\n", 2538c2ecf20Sopenharmony_ci ha->host_no, __func__, mbx_cmd[0]); 2548c2ecf20Sopenharmony_ci ha->mailbox_timeout_count++; 2558c2ecf20Sopenharmony_ci break; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci default: 2588c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: FAILED, MBOX CMD = %08X, MBOX STS = %08X %08X %08X %08X %08X %08X %08X %08X\n", 2598c2ecf20Sopenharmony_ci ha->host_no, __func__, mbx_cmd[0], mbx_sts[0], 2608c2ecf20Sopenharmony_ci mbx_sts[1], mbx_sts[2], mbx_sts[3], mbx_sts[4], 2618c2ecf20Sopenharmony_ci mbx_sts[5], mbx_sts[6], mbx_sts[7]); 2628c2ecf20Sopenharmony_ci break; 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cimbox_exit: 2678c2ecf20Sopenharmony_ci mutex_lock(&ha->mbox_sem); 2688c2ecf20Sopenharmony_ci clear_bit(AF_MBOX_COMMAND, &ha->flags); 2698c2ecf20Sopenharmony_ci mutex_unlock(&ha->mbox_sem); 2708c2ecf20Sopenharmony_ci clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci return status; 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci/** 2768c2ecf20Sopenharmony_ci * qla4xxx_get_minidump_template - Get the firmware template 2778c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 2788c2ecf20Sopenharmony_ci * @phys_addr: dma address for template 2798c2ecf20Sopenharmony_ci * 2808c2ecf20Sopenharmony_ci * Obtain the minidump template from firmware during initialization 2818c2ecf20Sopenharmony_ci * as it may not be available when minidump is desired. 2828c2ecf20Sopenharmony_ci **/ 2838c2ecf20Sopenharmony_ciint qla4xxx_get_minidump_template(struct scsi_qla_host *ha, 2848c2ecf20Sopenharmony_ci dma_addr_t phys_addr) 2858c2ecf20Sopenharmony_ci{ 2868c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 2878c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 2888c2ecf20Sopenharmony_ci int status; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 2918c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_MINIDUMP; 2948c2ecf20Sopenharmony_ci mbox_cmd[1] = MINIDUMP_GET_TMPLT_SUBCOMMAND; 2958c2ecf20Sopenharmony_ci mbox_cmd[2] = LSDW(phys_addr); 2968c2ecf20Sopenharmony_ci mbox_cmd[3] = MSDW(phys_addr); 2978c2ecf20Sopenharmony_ci mbox_cmd[4] = ha->fw_dump_tmplt_size; 2988c2ecf20Sopenharmony_ci mbox_cmd[5] = 0; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], 3018c2ecf20Sopenharmony_ci &mbox_sts[0]); 3028c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) { 3038c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 3048c2ecf20Sopenharmony_ci "scsi%ld: %s: Cmd = %08X, mbx[0] = 0x%04x, mbx[1] = 0x%04x\n", 3058c2ecf20Sopenharmony_ci ha->host_no, __func__, mbox_cmd[0], 3068c2ecf20Sopenharmony_ci mbox_sts[0], mbox_sts[1])); 3078c2ecf20Sopenharmony_ci } 3088c2ecf20Sopenharmony_ci return status; 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci/** 3128c2ecf20Sopenharmony_ci * qla4xxx_req_template_size - Get minidump template size from firmware. 3138c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 3148c2ecf20Sopenharmony_ci **/ 3158c2ecf20Sopenharmony_ciint qla4xxx_req_template_size(struct scsi_qla_host *ha) 3168c2ecf20Sopenharmony_ci{ 3178c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 3188c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 3198c2ecf20Sopenharmony_ci int status; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 3228c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_MINIDUMP; 3258c2ecf20Sopenharmony_ci mbox_cmd[1] = MINIDUMP_GET_SIZE_SUBCOMMAND; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0], 3288c2ecf20Sopenharmony_ci &mbox_sts[0]); 3298c2ecf20Sopenharmony_ci if (status == QLA_SUCCESS) { 3308c2ecf20Sopenharmony_ci ha->fw_dump_tmplt_size = mbox_sts[1]; 3318c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 3328c2ecf20Sopenharmony_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", 3338c2ecf20Sopenharmony_ci __func__, mbox_sts[0], mbox_sts[1], 3348c2ecf20Sopenharmony_ci mbox_sts[2], mbox_sts[3], mbox_sts[4], 3358c2ecf20Sopenharmony_ci mbox_sts[5], mbox_sts[6], mbox_sts[7])); 3368c2ecf20Sopenharmony_ci if (ha->fw_dump_tmplt_size == 0) 3378c2ecf20Sopenharmony_ci status = QLA_ERROR; 3388c2ecf20Sopenharmony_ci } else { 3398c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 3408c2ecf20Sopenharmony_ci "%s: Error sts[0]=0x%04x, mbx[1]=0x%04x\n", 3418c2ecf20Sopenharmony_ci __func__, mbox_sts[0], mbox_sts[1]); 3428c2ecf20Sopenharmony_ci status = QLA_ERROR; 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci return status; 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_civoid qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci set_bit(AF_FW_RECOVERY, &ha->flags); 3518c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: set FW RECOVERY!\n", 3528c2ecf20Sopenharmony_ci ha->host_no, __func__); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci if (test_bit(AF_MBOX_COMMAND, &ha->flags)) { 3558c2ecf20Sopenharmony_ci if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags)) { 3568c2ecf20Sopenharmony_ci complete(&ha->mbx_intr_comp); 3578c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw " 3588c2ecf20Sopenharmony_ci "recovery, doing premature completion of " 3598c2ecf20Sopenharmony_ci "mbx cmd\n", ha->host_no, __func__); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci } else { 3628c2ecf20Sopenharmony_ci set_bit(AF_MBOX_COMMAND_DONE, &ha->flags); 3638c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw " 3648c2ecf20Sopenharmony_ci "recovery, doing premature completion of " 3658c2ecf20Sopenharmony_ci "polling mbx cmd\n", ha->host_no, __func__); 3668c2ecf20Sopenharmony_ci } 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci} 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_cistatic uint8_t 3718c2ecf20Sopenharmony_ciqla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, 3728c2ecf20Sopenharmony_ci uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) 3738c2ecf20Sopenharmony_ci{ 3748c2ecf20Sopenharmony_ci memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT); 3758c2ecf20Sopenharmony_ci memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT); 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci if (is_qla8022(ha)) 3788c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, ha->nx_db_wr_ptr, 0); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE; 3818c2ecf20Sopenharmony_ci mbox_cmd[1] = 0; 3828c2ecf20Sopenharmony_ci mbox_cmd[2] = LSDW(init_fw_cb_dma); 3838c2ecf20Sopenharmony_ci mbox_cmd[3] = MSDW(init_fw_cb_dma); 3848c2ecf20Sopenharmony_ci mbox_cmd[4] = sizeof(struct addr_ctrl_blk); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci if (qla4xxx_mailbox_command(ha, 6, 6, mbox_cmd, mbox_sts) != 3878c2ecf20Sopenharmony_ci QLA_SUCCESS) { 3888c2ecf20Sopenharmony_ci DEBUG2(printk(KERN_WARNING "scsi%ld: %s: " 3898c2ecf20Sopenharmony_ci "MBOX_CMD_INITIALIZE_FIRMWARE" 3908c2ecf20Sopenharmony_ci " failed w/ status %04X\n", 3918c2ecf20Sopenharmony_ci ha->host_no, __func__, mbox_sts[0])); 3928c2ecf20Sopenharmony_ci return QLA_ERROR; 3938c2ecf20Sopenharmony_ci } 3948c2ecf20Sopenharmony_ci return QLA_SUCCESS; 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ciuint8_t 3988c2ecf20Sopenharmony_ciqla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, 3998c2ecf20Sopenharmony_ci uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) 4008c2ecf20Sopenharmony_ci{ 4018c2ecf20Sopenharmony_ci memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT); 4028c2ecf20Sopenharmony_ci memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT); 4038c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK; 4048c2ecf20Sopenharmony_ci mbox_cmd[2] = LSDW(init_fw_cb_dma); 4058c2ecf20Sopenharmony_ci mbox_cmd[3] = MSDW(init_fw_cb_dma); 4068c2ecf20Sopenharmony_ci mbox_cmd[4] = sizeof(struct addr_ctrl_blk); 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci if (qla4xxx_mailbox_command(ha, 5, 5, mbox_cmd, mbox_sts) != 4098c2ecf20Sopenharmony_ci QLA_SUCCESS) { 4108c2ecf20Sopenharmony_ci DEBUG2(printk(KERN_WARNING "scsi%ld: %s: " 4118c2ecf20Sopenharmony_ci "MBOX_CMD_GET_INIT_FW_CTRL_BLOCK" 4128c2ecf20Sopenharmony_ci " failed w/ status %04X\n", 4138c2ecf20Sopenharmony_ci ha->host_no, __func__, mbox_sts[0])); 4148c2ecf20Sopenharmony_ci return QLA_ERROR; 4158c2ecf20Sopenharmony_ci } 4168c2ecf20Sopenharmony_ci return QLA_SUCCESS; 4178c2ecf20Sopenharmony_ci} 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ciuint8_t qla4xxx_set_ipaddr_state(uint8_t fw_ipaddr_state) 4208c2ecf20Sopenharmony_ci{ 4218c2ecf20Sopenharmony_ci uint8_t ipaddr_state; 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci switch (fw_ipaddr_state) { 4248c2ecf20Sopenharmony_ci case IP_ADDRSTATE_UNCONFIGURED: 4258c2ecf20Sopenharmony_ci ipaddr_state = ISCSI_IPDDRESS_STATE_UNCONFIGURED; 4268c2ecf20Sopenharmony_ci break; 4278c2ecf20Sopenharmony_ci case IP_ADDRSTATE_INVALID: 4288c2ecf20Sopenharmony_ci ipaddr_state = ISCSI_IPDDRESS_STATE_INVALID; 4298c2ecf20Sopenharmony_ci break; 4308c2ecf20Sopenharmony_ci case IP_ADDRSTATE_ACQUIRING: 4318c2ecf20Sopenharmony_ci ipaddr_state = ISCSI_IPDDRESS_STATE_ACQUIRING; 4328c2ecf20Sopenharmony_ci break; 4338c2ecf20Sopenharmony_ci case IP_ADDRSTATE_TENTATIVE: 4348c2ecf20Sopenharmony_ci ipaddr_state = ISCSI_IPDDRESS_STATE_TENTATIVE; 4358c2ecf20Sopenharmony_ci break; 4368c2ecf20Sopenharmony_ci case IP_ADDRSTATE_DEPRICATED: 4378c2ecf20Sopenharmony_ci ipaddr_state = ISCSI_IPDDRESS_STATE_DEPRECATED; 4388c2ecf20Sopenharmony_ci break; 4398c2ecf20Sopenharmony_ci case IP_ADDRSTATE_PREFERRED: 4408c2ecf20Sopenharmony_ci ipaddr_state = ISCSI_IPDDRESS_STATE_VALID; 4418c2ecf20Sopenharmony_ci break; 4428c2ecf20Sopenharmony_ci case IP_ADDRSTATE_DISABLING: 4438c2ecf20Sopenharmony_ci ipaddr_state = ISCSI_IPDDRESS_STATE_DISABLING; 4448c2ecf20Sopenharmony_ci break; 4458c2ecf20Sopenharmony_ci default: 4468c2ecf20Sopenharmony_ci ipaddr_state = ISCSI_IPDDRESS_STATE_UNCONFIGURED; 4478c2ecf20Sopenharmony_ci } 4488c2ecf20Sopenharmony_ci return ipaddr_state; 4498c2ecf20Sopenharmony_ci} 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_cistatic void 4528c2ecf20Sopenharmony_ciqla4xxx_update_local_ip(struct scsi_qla_host *ha, 4538c2ecf20Sopenharmony_ci struct addr_ctrl_blk *init_fw_cb) 4548c2ecf20Sopenharmony_ci{ 4558c2ecf20Sopenharmony_ci ha->ip_config.tcp_options = le16_to_cpu(init_fw_cb->ipv4_tcp_opts); 4568c2ecf20Sopenharmony_ci ha->ip_config.ipv4_options = le16_to_cpu(init_fw_cb->ipv4_ip_opts); 4578c2ecf20Sopenharmony_ci ha->ip_config.ipv4_addr_state = 4588c2ecf20Sopenharmony_ci qla4xxx_set_ipaddr_state(init_fw_cb->ipv4_addr_state); 4598c2ecf20Sopenharmony_ci ha->ip_config.eth_mtu_size = 4608c2ecf20Sopenharmony_ci le16_to_cpu(init_fw_cb->eth_mtu_size); 4618c2ecf20Sopenharmony_ci ha->ip_config.ipv4_port = le16_to_cpu(init_fw_cb->ipv4_port); 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci if (ha->acb_version == ACB_SUPPORTED) { 4648c2ecf20Sopenharmony_ci ha->ip_config.ipv6_options = le16_to_cpu(init_fw_cb->ipv6_opts); 4658c2ecf20Sopenharmony_ci ha->ip_config.ipv6_addl_options = 4668c2ecf20Sopenharmony_ci le16_to_cpu(init_fw_cb->ipv6_addtl_opts); 4678c2ecf20Sopenharmony_ci ha->ip_config.ipv6_tcp_options = 4688c2ecf20Sopenharmony_ci le16_to_cpu(init_fw_cb->ipv6_tcp_opts); 4698c2ecf20Sopenharmony_ci } 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci /* Save IPv4 Address Info */ 4728c2ecf20Sopenharmony_ci memcpy(ha->ip_config.ip_address, init_fw_cb->ipv4_addr, 4738c2ecf20Sopenharmony_ci min(sizeof(ha->ip_config.ip_address), 4748c2ecf20Sopenharmony_ci sizeof(init_fw_cb->ipv4_addr))); 4758c2ecf20Sopenharmony_ci memcpy(ha->ip_config.subnet_mask, init_fw_cb->ipv4_subnet, 4768c2ecf20Sopenharmony_ci min(sizeof(ha->ip_config.subnet_mask), 4778c2ecf20Sopenharmony_ci sizeof(init_fw_cb->ipv4_subnet))); 4788c2ecf20Sopenharmony_ci memcpy(ha->ip_config.gateway, init_fw_cb->ipv4_gw_addr, 4798c2ecf20Sopenharmony_ci min(sizeof(ha->ip_config.gateway), 4808c2ecf20Sopenharmony_ci sizeof(init_fw_cb->ipv4_gw_addr))); 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci ha->ip_config.ipv4_vlan_tag = be16_to_cpu(init_fw_cb->ipv4_vlan_tag); 4838c2ecf20Sopenharmony_ci ha->ip_config.control = init_fw_cb->control; 4848c2ecf20Sopenharmony_ci ha->ip_config.tcp_wsf = init_fw_cb->ipv4_tcp_wsf; 4858c2ecf20Sopenharmony_ci ha->ip_config.ipv4_tos = init_fw_cb->ipv4_tos; 4868c2ecf20Sopenharmony_ci ha->ip_config.ipv4_cache_id = init_fw_cb->ipv4_cacheid; 4878c2ecf20Sopenharmony_ci ha->ip_config.ipv4_alt_cid_len = init_fw_cb->ipv4_dhcp_alt_cid_len; 4888c2ecf20Sopenharmony_ci memcpy(ha->ip_config.ipv4_alt_cid, init_fw_cb->ipv4_dhcp_alt_cid, 4898c2ecf20Sopenharmony_ci min(sizeof(ha->ip_config.ipv4_alt_cid), 4908c2ecf20Sopenharmony_ci sizeof(init_fw_cb->ipv4_dhcp_alt_cid))); 4918c2ecf20Sopenharmony_ci ha->ip_config.ipv4_vid_len = init_fw_cb->ipv4_dhcp_vid_len; 4928c2ecf20Sopenharmony_ci memcpy(ha->ip_config.ipv4_vid, init_fw_cb->ipv4_dhcp_vid, 4938c2ecf20Sopenharmony_ci min(sizeof(ha->ip_config.ipv4_vid), 4948c2ecf20Sopenharmony_ci sizeof(init_fw_cb->ipv4_dhcp_vid))); 4958c2ecf20Sopenharmony_ci ha->ip_config.ipv4_ttl = init_fw_cb->ipv4_ttl; 4968c2ecf20Sopenharmony_ci ha->ip_config.def_timeout = le16_to_cpu(init_fw_cb->def_timeout); 4978c2ecf20Sopenharmony_ci ha->ip_config.abort_timer = init_fw_cb->abort_timer; 4988c2ecf20Sopenharmony_ci ha->ip_config.iscsi_options = le16_to_cpu(init_fw_cb->iscsi_opts); 4998c2ecf20Sopenharmony_ci ha->ip_config.iscsi_max_pdu_size = 5008c2ecf20Sopenharmony_ci le16_to_cpu(init_fw_cb->iscsi_max_pdu_size); 5018c2ecf20Sopenharmony_ci ha->ip_config.iscsi_first_burst_len = 5028c2ecf20Sopenharmony_ci le16_to_cpu(init_fw_cb->iscsi_fburst_len); 5038c2ecf20Sopenharmony_ci ha->ip_config.iscsi_max_outstnd_r2t = 5048c2ecf20Sopenharmony_ci le16_to_cpu(init_fw_cb->iscsi_max_outstnd_r2t); 5058c2ecf20Sopenharmony_ci ha->ip_config.iscsi_max_burst_len = 5068c2ecf20Sopenharmony_ci le16_to_cpu(init_fw_cb->iscsi_max_burst_len); 5078c2ecf20Sopenharmony_ci memcpy(ha->ip_config.iscsi_name, init_fw_cb->iscsi_name, 5088c2ecf20Sopenharmony_ci min(sizeof(ha->ip_config.iscsi_name), 5098c2ecf20Sopenharmony_ci sizeof(init_fw_cb->iscsi_name))); 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci if (is_ipv6_enabled(ha)) { 5128c2ecf20Sopenharmony_ci /* Save IPv6 Address */ 5138c2ecf20Sopenharmony_ci ha->ip_config.ipv6_link_local_state = 5148c2ecf20Sopenharmony_ci qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_lnk_lcl_addr_state); 5158c2ecf20Sopenharmony_ci ha->ip_config.ipv6_addr0_state = 5168c2ecf20Sopenharmony_ci qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_addr0_state); 5178c2ecf20Sopenharmony_ci ha->ip_config.ipv6_addr1_state = 5188c2ecf20Sopenharmony_ci qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_addr1_state); 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci switch (le16_to_cpu(init_fw_cb->ipv6_dflt_rtr_state)) { 5218c2ecf20Sopenharmony_ci case IPV6_RTRSTATE_UNKNOWN: 5228c2ecf20Sopenharmony_ci ha->ip_config.ipv6_default_router_state = 5238c2ecf20Sopenharmony_ci ISCSI_ROUTER_STATE_UNKNOWN; 5248c2ecf20Sopenharmony_ci break; 5258c2ecf20Sopenharmony_ci case IPV6_RTRSTATE_MANUAL: 5268c2ecf20Sopenharmony_ci ha->ip_config.ipv6_default_router_state = 5278c2ecf20Sopenharmony_ci ISCSI_ROUTER_STATE_MANUAL; 5288c2ecf20Sopenharmony_ci break; 5298c2ecf20Sopenharmony_ci case IPV6_RTRSTATE_ADVERTISED: 5308c2ecf20Sopenharmony_ci ha->ip_config.ipv6_default_router_state = 5318c2ecf20Sopenharmony_ci ISCSI_ROUTER_STATE_ADVERTISED; 5328c2ecf20Sopenharmony_ci break; 5338c2ecf20Sopenharmony_ci case IPV6_RTRSTATE_STALE: 5348c2ecf20Sopenharmony_ci ha->ip_config.ipv6_default_router_state = 5358c2ecf20Sopenharmony_ci ISCSI_ROUTER_STATE_STALE; 5368c2ecf20Sopenharmony_ci break; 5378c2ecf20Sopenharmony_ci default: 5388c2ecf20Sopenharmony_ci ha->ip_config.ipv6_default_router_state = 5398c2ecf20Sopenharmony_ci ISCSI_ROUTER_STATE_UNKNOWN; 5408c2ecf20Sopenharmony_ci } 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[0] = 0xFE; 5438c2ecf20Sopenharmony_ci ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[1] = 0x80; 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci memcpy(&ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[8], 5468c2ecf20Sopenharmony_ci init_fw_cb->ipv6_if_id, 5478c2ecf20Sopenharmony_ci min(sizeof(ha->ip_config.ipv6_link_local_addr)/2, 5488c2ecf20Sopenharmony_ci sizeof(init_fw_cb->ipv6_if_id))); 5498c2ecf20Sopenharmony_ci memcpy(&ha->ip_config.ipv6_addr0, init_fw_cb->ipv6_addr0, 5508c2ecf20Sopenharmony_ci min(sizeof(ha->ip_config.ipv6_addr0), 5518c2ecf20Sopenharmony_ci sizeof(init_fw_cb->ipv6_addr0))); 5528c2ecf20Sopenharmony_ci memcpy(&ha->ip_config.ipv6_addr1, init_fw_cb->ipv6_addr1, 5538c2ecf20Sopenharmony_ci min(sizeof(ha->ip_config.ipv6_addr1), 5548c2ecf20Sopenharmony_ci sizeof(init_fw_cb->ipv6_addr1))); 5558c2ecf20Sopenharmony_ci memcpy(&ha->ip_config.ipv6_default_router_addr, 5568c2ecf20Sopenharmony_ci init_fw_cb->ipv6_dflt_rtr_addr, 5578c2ecf20Sopenharmony_ci min(sizeof(ha->ip_config.ipv6_default_router_addr), 5588c2ecf20Sopenharmony_ci sizeof(init_fw_cb->ipv6_dflt_rtr_addr))); 5598c2ecf20Sopenharmony_ci ha->ip_config.ipv6_vlan_tag = 5608c2ecf20Sopenharmony_ci be16_to_cpu(init_fw_cb->ipv6_vlan_tag); 5618c2ecf20Sopenharmony_ci ha->ip_config.ipv6_port = le16_to_cpu(init_fw_cb->ipv6_port); 5628c2ecf20Sopenharmony_ci ha->ip_config.ipv6_cache_id = init_fw_cb->ipv6_cache_id; 5638c2ecf20Sopenharmony_ci ha->ip_config.ipv6_flow_lbl = 5648c2ecf20Sopenharmony_ci le16_to_cpu(init_fw_cb->ipv6_flow_lbl); 5658c2ecf20Sopenharmony_ci ha->ip_config.ipv6_traffic_class = 5668c2ecf20Sopenharmony_ci init_fw_cb->ipv6_traffic_class; 5678c2ecf20Sopenharmony_ci ha->ip_config.ipv6_hop_limit = init_fw_cb->ipv6_hop_limit; 5688c2ecf20Sopenharmony_ci ha->ip_config.ipv6_nd_reach_time = 5698c2ecf20Sopenharmony_ci le32_to_cpu(init_fw_cb->ipv6_nd_reach_time); 5708c2ecf20Sopenharmony_ci ha->ip_config.ipv6_nd_rexmit_timer = 5718c2ecf20Sopenharmony_ci le32_to_cpu(init_fw_cb->ipv6_nd_rexmit_timer); 5728c2ecf20Sopenharmony_ci ha->ip_config.ipv6_nd_stale_timeout = 5738c2ecf20Sopenharmony_ci le32_to_cpu(init_fw_cb->ipv6_nd_stale_timeout); 5748c2ecf20Sopenharmony_ci ha->ip_config.ipv6_dup_addr_detect_count = 5758c2ecf20Sopenharmony_ci init_fw_cb->ipv6_dup_addr_detect_count; 5768c2ecf20Sopenharmony_ci ha->ip_config.ipv6_gw_advrt_mtu = 5778c2ecf20Sopenharmony_ci le32_to_cpu(init_fw_cb->ipv6_gw_advrt_mtu); 5788c2ecf20Sopenharmony_ci ha->ip_config.ipv6_tcp_wsf = init_fw_cb->ipv6_tcp_wsf; 5798c2ecf20Sopenharmony_ci } 5808c2ecf20Sopenharmony_ci} 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ciuint8_t 5838c2ecf20Sopenharmony_ciqla4xxx_update_local_ifcb(struct scsi_qla_host *ha, 5848c2ecf20Sopenharmony_ci uint32_t *mbox_cmd, 5858c2ecf20Sopenharmony_ci uint32_t *mbox_sts, 5868c2ecf20Sopenharmony_ci struct addr_ctrl_blk *init_fw_cb, 5878c2ecf20Sopenharmony_ci dma_addr_t init_fw_cb_dma) 5888c2ecf20Sopenharmony_ci{ 5898c2ecf20Sopenharmony_ci if (qla4xxx_get_ifcb(ha, mbox_cmd, mbox_sts, init_fw_cb_dma) 5908c2ecf20Sopenharmony_ci != QLA_SUCCESS) { 5918c2ecf20Sopenharmony_ci DEBUG2(printk(KERN_WARNING 5928c2ecf20Sopenharmony_ci "scsi%ld: %s: Failed to get init_fw_ctrl_blk\n", 5938c2ecf20Sopenharmony_ci ha->host_no, __func__)); 5948c2ecf20Sopenharmony_ci return QLA_ERROR; 5958c2ecf20Sopenharmony_ci } 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci DEBUG2(qla4xxx_dump_buffer(init_fw_cb, sizeof(struct addr_ctrl_blk))); 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci /* Save some info in adapter structure. */ 6008c2ecf20Sopenharmony_ci ha->acb_version = init_fw_cb->acb_version; 6018c2ecf20Sopenharmony_ci ha->firmware_options = le16_to_cpu(init_fw_cb->fw_options); 6028c2ecf20Sopenharmony_ci ha->heartbeat_interval = init_fw_cb->hb_interval; 6038c2ecf20Sopenharmony_ci memcpy(ha->name_string, init_fw_cb->iscsi_name, 6048c2ecf20Sopenharmony_ci min(sizeof(ha->name_string), 6058c2ecf20Sopenharmony_ci sizeof(init_fw_cb->iscsi_name))); 6068c2ecf20Sopenharmony_ci ha->def_timeout = le16_to_cpu(init_fw_cb->def_timeout); 6078c2ecf20Sopenharmony_ci /*memcpy(ha->alias, init_fw_cb->Alias, 6088c2ecf20Sopenharmony_ci min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/ 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci qla4xxx_update_local_ip(ha, init_fw_cb); 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci return QLA_SUCCESS; 6138c2ecf20Sopenharmony_ci} 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci/** 6168c2ecf20Sopenharmony_ci * qla4xxx_initialize_fw_cb - initializes firmware control block. 6178c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 6188c2ecf20Sopenharmony_ci **/ 6198c2ecf20Sopenharmony_ciint qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha) 6208c2ecf20Sopenharmony_ci{ 6218c2ecf20Sopenharmony_ci struct addr_ctrl_blk *init_fw_cb; 6228c2ecf20Sopenharmony_ci dma_addr_t init_fw_cb_dma; 6238c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 6248c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 6258c2ecf20Sopenharmony_ci int status = QLA_ERROR; 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci init_fw_cb = dma_alloc_coherent(&ha->pdev->dev, 6288c2ecf20Sopenharmony_ci sizeof(struct addr_ctrl_blk), 6298c2ecf20Sopenharmony_ci &init_fw_cb_dma, GFP_KERNEL); 6308c2ecf20Sopenharmony_ci if (init_fw_cb == NULL) { 6318c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n", 6328c2ecf20Sopenharmony_ci ha->host_no, __func__)); 6338c2ecf20Sopenharmony_ci goto exit_init_fw_cb_no_free; 6348c2ecf20Sopenharmony_ci } 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci /* Get Initialize Firmware Control Block. */ 6378c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 6388c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) != 6418c2ecf20Sopenharmony_ci QLA_SUCCESS) { 6428c2ecf20Sopenharmony_ci goto exit_init_fw_cb; 6438c2ecf20Sopenharmony_ci } 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci /* Fill in the request and response queue information. */ 6468c2ecf20Sopenharmony_ci init_fw_cb->rqq_consumer_idx = cpu_to_le16(ha->request_out); 6478c2ecf20Sopenharmony_ci init_fw_cb->compq_producer_idx = cpu_to_le16(ha->response_in); 6488c2ecf20Sopenharmony_ci init_fw_cb->rqq_len = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH); 6498c2ecf20Sopenharmony_ci init_fw_cb->compq_len = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH); 6508c2ecf20Sopenharmony_ci init_fw_cb->rqq_addr_lo = cpu_to_le32(LSDW(ha->request_dma)); 6518c2ecf20Sopenharmony_ci init_fw_cb->rqq_addr_hi = cpu_to_le32(MSDW(ha->request_dma)); 6528c2ecf20Sopenharmony_ci init_fw_cb->compq_addr_lo = cpu_to_le32(LSDW(ha->response_dma)); 6538c2ecf20Sopenharmony_ci init_fw_cb->compq_addr_hi = cpu_to_le32(MSDW(ha->response_dma)); 6548c2ecf20Sopenharmony_ci init_fw_cb->shdwreg_addr_lo = cpu_to_le32(LSDW(ha->shadow_regs_dma)); 6558c2ecf20Sopenharmony_ci init_fw_cb->shdwreg_addr_hi = cpu_to_le32(MSDW(ha->shadow_regs_dma)); 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci /* Set up required options. */ 6588c2ecf20Sopenharmony_ci init_fw_cb->fw_options |= 6598c2ecf20Sopenharmony_ci __constant_cpu_to_le16(FWOPT_SESSION_MODE | 6608c2ecf20Sopenharmony_ci FWOPT_INITIATOR_MODE); 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) 6638c2ecf20Sopenharmony_ci init_fw_cb->fw_options |= 6648c2ecf20Sopenharmony_ci __constant_cpu_to_le16(FWOPT_ENABLE_CRBDB); 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci init_fw_cb->fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE); 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci init_fw_cb->add_fw_options = 0; 6698c2ecf20Sopenharmony_ci init_fw_cb->add_fw_options |= 6708c2ecf20Sopenharmony_ci __constant_cpu_to_le16(ADFWOPT_SERIALIZE_TASK_MGMT); 6718c2ecf20Sopenharmony_ci init_fw_cb->add_fw_options |= 6728c2ecf20Sopenharmony_ci __constant_cpu_to_le16(ADFWOPT_AUTOCONN_DISABLE); 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci if (qla4xxx_set_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) 6758c2ecf20Sopenharmony_ci != QLA_SUCCESS) { 6768c2ecf20Sopenharmony_ci DEBUG2(printk(KERN_WARNING 6778c2ecf20Sopenharmony_ci "scsi%ld: %s: Failed to set init_fw_ctrl_blk\n", 6788c2ecf20Sopenharmony_ci ha->host_no, __func__)); 6798c2ecf20Sopenharmony_ci goto exit_init_fw_cb; 6808c2ecf20Sopenharmony_ci } 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci if (qla4xxx_update_local_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], 6838c2ecf20Sopenharmony_ci init_fw_cb, init_fw_cb_dma) != QLA_SUCCESS) { 6848c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: Failed to update local ifcb\n", 6858c2ecf20Sopenharmony_ci ha->host_no, __func__)); 6868c2ecf20Sopenharmony_ci goto exit_init_fw_cb; 6878c2ecf20Sopenharmony_ci } 6888c2ecf20Sopenharmony_ci status = QLA_SUCCESS; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ciexit_init_fw_cb: 6918c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk), 6928c2ecf20Sopenharmony_ci init_fw_cb, init_fw_cb_dma); 6938c2ecf20Sopenharmony_ciexit_init_fw_cb_no_free: 6948c2ecf20Sopenharmony_ci return status; 6958c2ecf20Sopenharmony_ci} 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci/** 6988c2ecf20Sopenharmony_ci * qla4xxx_get_dhcp_ip_address - gets HBA ip address via DHCP 6998c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 7008c2ecf20Sopenharmony_ci **/ 7018c2ecf20Sopenharmony_ciint qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha) 7028c2ecf20Sopenharmony_ci{ 7038c2ecf20Sopenharmony_ci struct addr_ctrl_blk *init_fw_cb; 7048c2ecf20Sopenharmony_ci dma_addr_t init_fw_cb_dma; 7058c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 7068c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci init_fw_cb = dma_alloc_coherent(&ha->pdev->dev, 7098c2ecf20Sopenharmony_ci sizeof(struct addr_ctrl_blk), 7108c2ecf20Sopenharmony_ci &init_fw_cb_dma, GFP_KERNEL); 7118c2ecf20Sopenharmony_ci if (init_fw_cb == NULL) { 7128c2ecf20Sopenharmony_ci printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no, 7138c2ecf20Sopenharmony_ci __func__); 7148c2ecf20Sopenharmony_ci return QLA_ERROR; 7158c2ecf20Sopenharmony_ci } 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci /* Get Initialize Firmware Control Block. */ 7188c2ecf20Sopenharmony_ci if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) != 7198c2ecf20Sopenharmony_ci QLA_SUCCESS) { 7208c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n", 7218c2ecf20Sopenharmony_ci ha->host_no, __func__)); 7228c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, 7238c2ecf20Sopenharmony_ci sizeof(struct addr_ctrl_blk), 7248c2ecf20Sopenharmony_ci init_fw_cb, init_fw_cb_dma); 7258c2ecf20Sopenharmony_ci return QLA_ERROR; 7268c2ecf20Sopenharmony_ci } 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci /* Save IP Address. */ 7298c2ecf20Sopenharmony_ci qla4xxx_update_local_ip(ha, init_fw_cb); 7308c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk), 7318c2ecf20Sopenharmony_ci init_fw_cb, init_fw_cb_dma); 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci return QLA_SUCCESS; 7348c2ecf20Sopenharmony_ci} 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci/** 7378c2ecf20Sopenharmony_ci * qla4xxx_get_firmware_state - gets firmware state of HBA 7388c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 7398c2ecf20Sopenharmony_ci **/ 7408c2ecf20Sopenharmony_ciint qla4xxx_get_firmware_state(struct scsi_qla_host * ha) 7418c2ecf20Sopenharmony_ci{ 7428c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 7438c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci /* Get firmware version */ 7468c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 7478c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_FW_STATE; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 4, &mbox_cmd[0], &mbox_sts[0]) != 7528c2ecf20Sopenharmony_ci QLA_SUCCESS) { 7538c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ " 7548c2ecf20Sopenharmony_ci "status %04X\n", ha->host_no, __func__, 7558c2ecf20Sopenharmony_ci mbox_sts[0])); 7568c2ecf20Sopenharmony_ci return QLA_ERROR; 7578c2ecf20Sopenharmony_ci } 7588c2ecf20Sopenharmony_ci ha->firmware_state = mbox_sts[1]; 7598c2ecf20Sopenharmony_ci ha->board_id = mbox_sts[2]; 7608c2ecf20Sopenharmony_ci ha->addl_fw_state = mbox_sts[3]; 7618c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s firmware_state=0x%x\n", 7628c2ecf20Sopenharmony_ci ha->host_no, __func__, ha->firmware_state);) 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci return QLA_SUCCESS; 7658c2ecf20Sopenharmony_ci} 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci/** 7688c2ecf20Sopenharmony_ci * qla4xxx_get_firmware_status - retrieves firmware status 7698c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 7708c2ecf20Sopenharmony_ci **/ 7718c2ecf20Sopenharmony_ciint qla4xxx_get_firmware_status(struct scsi_qla_host * ha) 7728c2ecf20Sopenharmony_ci{ 7738c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 7748c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci /* Get firmware version */ 7778c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 7788c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS; 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) != 7838c2ecf20Sopenharmony_ci QLA_SUCCESS) { 7848c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ " 7858c2ecf20Sopenharmony_ci "status %04X\n", ha->host_no, __func__, 7868c2ecf20Sopenharmony_ci mbox_sts[0])); 7878c2ecf20Sopenharmony_ci return QLA_ERROR; 7888c2ecf20Sopenharmony_ci } 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci /* High-water mark of IOCBs */ 7918c2ecf20Sopenharmony_ci ha->iocb_hiwat = mbox_sts[2]; 7928c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 7938c2ecf20Sopenharmony_ci "%s: firmware IOCBs available = %d\n", __func__, 7948c2ecf20Sopenharmony_ci ha->iocb_hiwat)); 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci if (ha->iocb_hiwat > IOCB_HIWAT_CUSHION) 7978c2ecf20Sopenharmony_ci ha->iocb_hiwat -= IOCB_HIWAT_CUSHION; 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci /* Ideally, we should not enter this code, as the # of firmware 8008c2ecf20Sopenharmony_ci * IOCBs is hard-coded in the firmware. We set a default 8018c2ecf20Sopenharmony_ci * iocb_hiwat here just in case */ 8028c2ecf20Sopenharmony_ci if (ha->iocb_hiwat == 0) { 8038c2ecf20Sopenharmony_ci ha->iocb_hiwat = REQUEST_QUEUE_DEPTH / 4; 8048c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, 8058c2ecf20Sopenharmony_ci "%s: Setting IOCB's to = %d\n", __func__, 8068c2ecf20Sopenharmony_ci ha->iocb_hiwat)); 8078c2ecf20Sopenharmony_ci } 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci return QLA_SUCCESS; 8108c2ecf20Sopenharmony_ci} 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci/* 8138c2ecf20Sopenharmony_ci * qla4xxx_get_fwddb_entry - retrieves firmware ddb entry 8148c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 8158c2ecf20Sopenharmony_ci * @fw_ddb_index: Firmware's device database index 8168c2ecf20Sopenharmony_ci * @fw_ddb_entry: Pointer to firmware's device database entry structure 8178c2ecf20Sopenharmony_ci * @num_valid_ddb_entries: Pointer to number of valid ddb entries 8188c2ecf20Sopenharmony_ci * @next_ddb_index: Pointer to next valid device database index 8198c2ecf20Sopenharmony_ci * @fw_ddb_device_state: Pointer to device state 8208c2ecf20Sopenharmony_ci **/ 8218c2ecf20Sopenharmony_ciint qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha, 8228c2ecf20Sopenharmony_ci uint16_t fw_ddb_index, 8238c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry, 8248c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma, 8258c2ecf20Sopenharmony_ci uint32_t *num_valid_ddb_entries, 8268c2ecf20Sopenharmony_ci uint32_t *next_ddb_index, 8278c2ecf20Sopenharmony_ci uint32_t *fw_ddb_device_state, 8288c2ecf20Sopenharmony_ci uint32_t *conn_err_detail, 8298c2ecf20Sopenharmony_ci uint16_t *tcp_source_port_num, 8308c2ecf20Sopenharmony_ci uint16_t *connection_id) 8318c2ecf20Sopenharmony_ci{ 8328c2ecf20Sopenharmony_ci int status = QLA_ERROR; 8338c2ecf20Sopenharmony_ci uint16_t options; 8348c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 8358c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci /* Make sure the device index is valid */ 8388c2ecf20Sopenharmony_ci if (fw_ddb_index >= MAX_DDB_ENTRIES) { 8398c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: ddb [%d] out of range.\n", 8408c2ecf20Sopenharmony_ci ha->host_no, __func__, fw_ddb_index)); 8418c2ecf20Sopenharmony_ci goto exit_get_fwddb; 8428c2ecf20Sopenharmony_ci } 8438c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 8448c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 8458c2ecf20Sopenharmony_ci if (fw_ddb_entry) 8468c2ecf20Sopenharmony_ci memset(fw_ddb_entry, 0, sizeof(struct dev_db_entry)); 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY; 8498c2ecf20Sopenharmony_ci mbox_cmd[1] = (uint32_t) fw_ddb_index; 8508c2ecf20Sopenharmony_ci mbox_cmd[2] = LSDW(fw_ddb_entry_dma); 8518c2ecf20Sopenharmony_ci mbox_cmd[3] = MSDW(fw_ddb_entry_dma); 8528c2ecf20Sopenharmony_ci mbox_cmd[4] = sizeof(struct dev_db_entry); 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 7, &mbox_cmd[0], &mbox_sts[0]) == 8558c2ecf20Sopenharmony_ci QLA_ERROR) { 8568c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed" 8578c2ecf20Sopenharmony_ci " with status 0x%04X\n", ha->host_no, __func__, 8588c2ecf20Sopenharmony_ci mbox_sts[0])); 8598c2ecf20Sopenharmony_ci goto exit_get_fwddb; 8608c2ecf20Sopenharmony_ci } 8618c2ecf20Sopenharmony_ci if (fw_ddb_index != mbox_sts[1]) { 8628c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: ddb mismatch [%d] != [%d].\n", 8638c2ecf20Sopenharmony_ci ha->host_no, __func__, fw_ddb_index, 8648c2ecf20Sopenharmony_ci mbox_sts[1])); 8658c2ecf20Sopenharmony_ci goto exit_get_fwddb; 8668c2ecf20Sopenharmony_ci } 8678c2ecf20Sopenharmony_ci if (fw_ddb_entry) { 8688c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->options); 8698c2ecf20Sopenharmony_ci if (options & DDB_OPT_IPV6_DEVICE) { 8708c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d " 8718c2ecf20Sopenharmony_ci "Next %d State %04x ConnErr %08x %pI6 " 8728c2ecf20Sopenharmony_ci ":%04d \"%s\"\n", __func__, fw_ddb_index, 8738c2ecf20Sopenharmony_ci mbox_sts[0], mbox_sts[2], mbox_sts[3], 8748c2ecf20Sopenharmony_ci mbox_sts[4], mbox_sts[5], 8758c2ecf20Sopenharmony_ci fw_ddb_entry->ip_addr, 8768c2ecf20Sopenharmony_ci le16_to_cpu(fw_ddb_entry->port), 8778c2ecf20Sopenharmony_ci fw_ddb_entry->iscsi_name); 8788c2ecf20Sopenharmony_ci } else { 8798c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d " 8808c2ecf20Sopenharmony_ci "Next %d State %04x ConnErr %08x %pI4 " 8818c2ecf20Sopenharmony_ci ":%04d \"%s\"\n", __func__, fw_ddb_index, 8828c2ecf20Sopenharmony_ci mbox_sts[0], mbox_sts[2], mbox_sts[3], 8838c2ecf20Sopenharmony_ci mbox_sts[4], mbox_sts[5], 8848c2ecf20Sopenharmony_ci fw_ddb_entry->ip_addr, 8858c2ecf20Sopenharmony_ci le16_to_cpu(fw_ddb_entry->port), 8868c2ecf20Sopenharmony_ci fw_ddb_entry->iscsi_name); 8878c2ecf20Sopenharmony_ci } 8888c2ecf20Sopenharmony_ci } 8898c2ecf20Sopenharmony_ci if (num_valid_ddb_entries) 8908c2ecf20Sopenharmony_ci *num_valid_ddb_entries = mbox_sts[2]; 8918c2ecf20Sopenharmony_ci if (next_ddb_index) 8928c2ecf20Sopenharmony_ci *next_ddb_index = mbox_sts[3]; 8938c2ecf20Sopenharmony_ci if (fw_ddb_device_state) 8948c2ecf20Sopenharmony_ci *fw_ddb_device_state = mbox_sts[4]; 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci /* 8978c2ecf20Sopenharmony_ci * RA: This mailbox has been changed to pass connection error and 8988c2ecf20Sopenharmony_ci * details. Its true for ISP4010 as per Version E - Not sure when it 8998c2ecf20Sopenharmony_ci * was changed. Get the time2wait from the fw_dd_entry field : 9008c2ecf20Sopenharmony_ci * default_time2wait which we call it as minTime2Wait DEV_DB_ENTRY 9018c2ecf20Sopenharmony_ci * struct. 9028c2ecf20Sopenharmony_ci */ 9038c2ecf20Sopenharmony_ci if (conn_err_detail) 9048c2ecf20Sopenharmony_ci *conn_err_detail = mbox_sts[5]; 9058c2ecf20Sopenharmony_ci if (tcp_source_port_num) 9068c2ecf20Sopenharmony_ci *tcp_source_port_num = (uint16_t) (mbox_sts[6] >> 16); 9078c2ecf20Sopenharmony_ci if (connection_id) 9088c2ecf20Sopenharmony_ci *connection_id = (uint16_t) mbox_sts[6] & 0x00FF; 9098c2ecf20Sopenharmony_ci status = QLA_SUCCESS; 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ciexit_get_fwddb: 9128c2ecf20Sopenharmony_ci return status; 9138c2ecf20Sopenharmony_ci} 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ciint qla4xxx_conn_open(struct scsi_qla_host *ha, uint16_t fw_ddb_index) 9168c2ecf20Sopenharmony_ci{ 9178c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 9188c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 9198c2ecf20Sopenharmony_ci int status; 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 9228c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_CONN_OPEN; 9258c2ecf20Sopenharmony_ci mbox_cmd[1] = fw_ddb_index; 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], 9288c2ecf20Sopenharmony_ci &mbox_sts[0]); 9298c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 9308c2ecf20Sopenharmony_ci "%s: status = %d mbx0 = 0x%x mbx1 = 0x%x\n", 9318c2ecf20Sopenharmony_ci __func__, status, mbox_sts[0], mbox_sts[1])); 9328c2ecf20Sopenharmony_ci return status; 9338c2ecf20Sopenharmony_ci} 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_ci/** 9368c2ecf20Sopenharmony_ci * qla4xxx_set_fwddb_entry - sets a ddb entry. 9378c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 9388c2ecf20Sopenharmony_ci * @fw_ddb_index: Firmware's device database index 9398c2ecf20Sopenharmony_ci * @fw_ddb_entry_dma: dma address of ddb entry 9408c2ecf20Sopenharmony_ci * @mbx_sts: mailbox 0 to be returned or NULL 9418c2ecf20Sopenharmony_ci * 9428c2ecf20Sopenharmony_ci * This routine initializes or updates the adapter's device database 9438c2ecf20Sopenharmony_ci * entry for the specified device. 9448c2ecf20Sopenharmony_ci **/ 9458c2ecf20Sopenharmony_ciint qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index, 9468c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma, uint32_t *mbx_sts) 9478c2ecf20Sopenharmony_ci{ 9488c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 9498c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 9508c2ecf20Sopenharmony_ci int status; 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci /* Do not wait for completion. The firmware will send us an 9538c2ecf20Sopenharmony_ci * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status. 9548c2ecf20Sopenharmony_ci */ 9558c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 9568c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_SET_DATABASE_ENTRY; 9598c2ecf20Sopenharmony_ci mbox_cmd[1] = (uint32_t) fw_ddb_index; 9608c2ecf20Sopenharmony_ci mbox_cmd[2] = LSDW(fw_ddb_entry_dma); 9618c2ecf20Sopenharmony_ci mbox_cmd[3] = MSDW(fw_ddb_entry_dma); 9628c2ecf20Sopenharmony_ci mbox_cmd[4] = sizeof(struct dev_db_entry); 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], 9658c2ecf20Sopenharmony_ci &mbox_sts[0]); 9668c2ecf20Sopenharmony_ci if (mbx_sts) 9678c2ecf20Sopenharmony_ci *mbx_sts = mbox_sts[0]; 9688c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: status=%d mbx0=0x%x mbx4=0x%x\n", 9698c2ecf20Sopenharmony_ci ha->host_no, __func__, status, mbox_sts[0], mbox_sts[4]);) 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci return status; 9728c2ecf20Sopenharmony_ci} 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ciint qla4xxx_session_logout_ddb(struct scsi_qla_host *ha, 9758c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry, int options) 9768c2ecf20Sopenharmony_ci{ 9778c2ecf20Sopenharmony_ci int status; 9788c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 9798c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 9828c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT; 9858c2ecf20Sopenharmony_ci mbox_cmd[1] = ddb_entry->fw_ddb_index; 9868c2ecf20Sopenharmony_ci mbox_cmd[3] = options; 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], 9898c2ecf20Sopenharmony_ci &mbox_sts[0]); 9908c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) { 9918c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 9928c2ecf20Sopenharmony_ci "%s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT " 9938c2ecf20Sopenharmony_ci "failed sts %04X %04X", __func__, 9948c2ecf20Sopenharmony_ci mbox_sts[0], mbox_sts[1])); 9958c2ecf20Sopenharmony_ci if ((mbox_sts[0] == MBOX_STS_COMMAND_ERROR) && 9968c2ecf20Sopenharmony_ci (mbox_sts[1] == DDB_NOT_LOGGED_IN)) { 9978c2ecf20Sopenharmony_ci set_bit(DDB_CONN_CLOSE_FAILURE, &ddb_entry->flags); 9988c2ecf20Sopenharmony_ci } 9998c2ecf20Sopenharmony_ci } 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci return status; 10028c2ecf20Sopenharmony_ci} 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci/** 10058c2ecf20Sopenharmony_ci * qla4xxx_get_crash_record - retrieves crash record. 10068c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 10078c2ecf20Sopenharmony_ci * 10088c2ecf20Sopenharmony_ci * This routine retrieves a crash record from the QLA4010 after an 8002h aen. 10098c2ecf20Sopenharmony_ci **/ 10108c2ecf20Sopenharmony_civoid qla4xxx_get_crash_record(struct scsi_qla_host * ha) 10118c2ecf20Sopenharmony_ci{ 10128c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 10138c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 10148c2ecf20Sopenharmony_ci struct crash_record *crash_record = NULL; 10158c2ecf20Sopenharmony_ci dma_addr_t crash_record_dma = 0; 10168c2ecf20Sopenharmony_ci uint32_t crash_record_size = 0; 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 10198c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_cmd)); 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci /* Get size of crash record. */ 10228c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD; 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != 10258c2ecf20Sopenharmony_ci QLA_SUCCESS) { 10268c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n", 10278c2ecf20Sopenharmony_ci ha->host_no, __func__)); 10288c2ecf20Sopenharmony_ci goto exit_get_crash_record; 10298c2ecf20Sopenharmony_ci } 10308c2ecf20Sopenharmony_ci crash_record_size = mbox_sts[4]; 10318c2ecf20Sopenharmony_ci if (crash_record_size == 0) { 10328c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: ERROR: Crash record size is 0!\n", 10338c2ecf20Sopenharmony_ci ha->host_no, __func__)); 10348c2ecf20Sopenharmony_ci goto exit_get_crash_record; 10358c2ecf20Sopenharmony_ci } 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci /* Alloc Memory for Crash Record. */ 10388c2ecf20Sopenharmony_ci crash_record = dma_alloc_coherent(&ha->pdev->dev, crash_record_size, 10398c2ecf20Sopenharmony_ci &crash_record_dma, GFP_KERNEL); 10408c2ecf20Sopenharmony_ci if (crash_record == NULL) 10418c2ecf20Sopenharmony_ci goto exit_get_crash_record; 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci /* Get Crash Record. */ 10448c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 10458c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_cmd)); 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD; 10488c2ecf20Sopenharmony_ci mbox_cmd[2] = LSDW(crash_record_dma); 10498c2ecf20Sopenharmony_ci mbox_cmd[3] = MSDW(crash_record_dma); 10508c2ecf20Sopenharmony_ci mbox_cmd[4] = crash_record_size; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != 10538c2ecf20Sopenharmony_ci QLA_SUCCESS) 10548c2ecf20Sopenharmony_ci goto exit_get_crash_record; 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci /* Dump Crash Record. */ 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ciexit_get_crash_record: 10598c2ecf20Sopenharmony_ci if (crash_record) 10608c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, crash_record_size, 10618c2ecf20Sopenharmony_ci crash_record, crash_record_dma); 10628c2ecf20Sopenharmony_ci} 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci/** 10658c2ecf20Sopenharmony_ci * qla4xxx_get_conn_event_log - retrieves connection event log 10668c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 10678c2ecf20Sopenharmony_ci **/ 10688c2ecf20Sopenharmony_civoid qla4xxx_get_conn_event_log(struct scsi_qla_host * ha) 10698c2ecf20Sopenharmony_ci{ 10708c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 10718c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 10728c2ecf20Sopenharmony_ci struct conn_event_log_entry *event_log = NULL; 10738c2ecf20Sopenharmony_ci dma_addr_t event_log_dma = 0; 10748c2ecf20Sopenharmony_ci uint32_t event_log_size = 0; 10758c2ecf20Sopenharmony_ci uint32_t num_valid_entries; 10768c2ecf20Sopenharmony_ci uint32_t oldest_entry = 0; 10778c2ecf20Sopenharmony_ci uint32_t max_event_log_entries; 10788c2ecf20Sopenharmony_ci uint8_t i; 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 10818c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_cmd)); 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci /* Get size of crash record. */ 10848c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG; 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != 10878c2ecf20Sopenharmony_ci QLA_SUCCESS) 10888c2ecf20Sopenharmony_ci goto exit_get_event_log; 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci event_log_size = mbox_sts[4]; 10918c2ecf20Sopenharmony_ci if (event_log_size == 0) 10928c2ecf20Sopenharmony_ci goto exit_get_event_log; 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci /* Alloc Memory for Crash Record. */ 10958c2ecf20Sopenharmony_ci event_log = dma_alloc_coherent(&ha->pdev->dev, event_log_size, 10968c2ecf20Sopenharmony_ci &event_log_dma, GFP_KERNEL); 10978c2ecf20Sopenharmony_ci if (event_log == NULL) 10988c2ecf20Sopenharmony_ci goto exit_get_event_log; 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci /* Get Crash Record. */ 11018c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 11028c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_cmd)); 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG; 11058c2ecf20Sopenharmony_ci mbox_cmd[2] = LSDW(event_log_dma); 11068c2ecf20Sopenharmony_ci mbox_cmd[3] = MSDW(event_log_dma); 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != 11098c2ecf20Sopenharmony_ci QLA_SUCCESS) { 11108c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event " 11118c2ecf20Sopenharmony_ci "log!\n", ha->host_no, __func__)); 11128c2ecf20Sopenharmony_ci goto exit_get_event_log; 11138c2ecf20Sopenharmony_ci } 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci /* Dump Event Log. */ 11168c2ecf20Sopenharmony_ci num_valid_entries = mbox_sts[1]; 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci max_event_log_entries = event_log_size / 11198c2ecf20Sopenharmony_ci sizeof(struct conn_event_log_entry); 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci if (num_valid_entries > max_event_log_entries) 11228c2ecf20Sopenharmony_ci oldest_entry = num_valid_entries % max_event_log_entries; 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci DEBUG3(printk("scsi%ld: Connection Event Log Dump (%d entries):\n", 11258c2ecf20Sopenharmony_ci ha->host_no, num_valid_entries)); 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci if (ql4xextended_error_logging == 3) { 11288c2ecf20Sopenharmony_ci if (oldest_entry == 0) { 11298c2ecf20Sopenharmony_ci /* Circular Buffer has not wrapped around */ 11308c2ecf20Sopenharmony_ci for (i=0; i < num_valid_entries; i++) { 11318c2ecf20Sopenharmony_ci qla4xxx_dump_buffer((uint8_t *)event_log+ 11328c2ecf20Sopenharmony_ci (i*sizeof(*event_log)), 11338c2ecf20Sopenharmony_ci sizeof(*event_log)); 11348c2ecf20Sopenharmony_ci } 11358c2ecf20Sopenharmony_ci } 11368c2ecf20Sopenharmony_ci else { 11378c2ecf20Sopenharmony_ci /* Circular Buffer has wrapped around - 11388c2ecf20Sopenharmony_ci * display accordingly*/ 11398c2ecf20Sopenharmony_ci for (i=oldest_entry; i < max_event_log_entries; i++) { 11408c2ecf20Sopenharmony_ci qla4xxx_dump_buffer((uint8_t *)event_log+ 11418c2ecf20Sopenharmony_ci (i*sizeof(*event_log)), 11428c2ecf20Sopenharmony_ci sizeof(*event_log)); 11438c2ecf20Sopenharmony_ci } 11448c2ecf20Sopenharmony_ci for (i=0; i < oldest_entry; i++) { 11458c2ecf20Sopenharmony_ci qla4xxx_dump_buffer((uint8_t *)event_log+ 11468c2ecf20Sopenharmony_ci (i*sizeof(*event_log)), 11478c2ecf20Sopenharmony_ci sizeof(*event_log)); 11488c2ecf20Sopenharmony_ci } 11498c2ecf20Sopenharmony_ci } 11508c2ecf20Sopenharmony_ci } 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ciexit_get_event_log: 11538c2ecf20Sopenharmony_ci if (event_log) 11548c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, event_log_size, event_log, 11558c2ecf20Sopenharmony_ci event_log_dma); 11568c2ecf20Sopenharmony_ci} 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci/** 11598c2ecf20Sopenharmony_ci * qla4xxx_abort_task - issues Abort Task 11608c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 11618c2ecf20Sopenharmony_ci * @srb: Pointer to srb entry 11628c2ecf20Sopenharmony_ci * 11638c2ecf20Sopenharmony_ci * This routine performs a LUN RESET on the specified target/lun. 11648c2ecf20Sopenharmony_ci * The caller must ensure that the ddb_entry and lun_entry pointers 11658c2ecf20Sopenharmony_ci * are valid before calling this routine. 11668c2ecf20Sopenharmony_ci **/ 11678c2ecf20Sopenharmony_ciint qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb) 11688c2ecf20Sopenharmony_ci{ 11698c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 11708c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 11718c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd = srb->cmd; 11728c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 11738c2ecf20Sopenharmony_ci unsigned long flags = 0; 11748c2ecf20Sopenharmony_ci uint32_t index; 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci /* 11778c2ecf20Sopenharmony_ci * Send abort task command to ISP, so that the ISP will return 11788c2ecf20Sopenharmony_ci * request with ABORT status 11798c2ecf20Sopenharmony_ci */ 11808c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 11818c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 11848c2ecf20Sopenharmony_ci index = (unsigned long)(unsigned char *)cmd->host_scribble; 11858c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci /* Firmware already posted completion on response queue */ 11888c2ecf20Sopenharmony_ci if (index == MAX_SRBS) 11898c2ecf20Sopenharmony_ci return status; 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_ABORT_TASK; 11928c2ecf20Sopenharmony_ci mbox_cmd[1] = srb->ddb->fw_ddb_index; 11938c2ecf20Sopenharmony_ci mbox_cmd[2] = index; 11948c2ecf20Sopenharmony_ci /* Immediate Command Enable */ 11958c2ecf20Sopenharmony_ci mbox_cmd[5] = 0x01; 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], 11988c2ecf20Sopenharmony_ci &mbox_sts[0]); 11998c2ecf20Sopenharmony_ci if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE) { 12008c2ecf20Sopenharmony_ci status = QLA_ERROR; 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci DEBUG2(printk(KERN_WARNING "scsi%ld:%d:%llu: abort task FAILED: " 12038c2ecf20Sopenharmony_ci "mbx0=%04X, mb1=%04X, mb2=%04X, mb3=%04X, mb4=%04X\n", 12048c2ecf20Sopenharmony_ci ha->host_no, cmd->device->id, cmd->device->lun, mbox_sts[0], 12058c2ecf20Sopenharmony_ci mbox_sts[1], mbox_sts[2], mbox_sts[3], mbox_sts[4])); 12068c2ecf20Sopenharmony_ci } 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci return status; 12098c2ecf20Sopenharmony_ci} 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci/** 12128c2ecf20Sopenharmony_ci * qla4xxx_reset_lun - issues LUN Reset 12138c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 12148c2ecf20Sopenharmony_ci * @ddb_entry: Pointer to device database entry 12158c2ecf20Sopenharmony_ci * @lun: lun number 12168c2ecf20Sopenharmony_ci * 12178c2ecf20Sopenharmony_ci * This routine performs a LUN RESET on the specified target/lun. 12188c2ecf20Sopenharmony_ci * The caller must ensure that the ddb_entry and lun_entry pointers 12198c2ecf20Sopenharmony_ci * are valid before calling this routine. 12208c2ecf20Sopenharmony_ci **/ 12218c2ecf20Sopenharmony_ciint qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry, 12228c2ecf20Sopenharmony_ci uint64_t lun) 12238c2ecf20Sopenharmony_ci{ 12248c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 12258c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 12268c2ecf20Sopenharmony_ci uint32_t scsi_lun[2]; 12278c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld:%d:%llu: lun reset issued\n", ha->host_no, 12308c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_index, lun)); 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci /* 12338c2ecf20Sopenharmony_ci * Send lun reset command to ISP, so that the ISP will return all 12348c2ecf20Sopenharmony_ci * outstanding requests with RESET status 12358c2ecf20Sopenharmony_ci */ 12368c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 12378c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 12388c2ecf20Sopenharmony_ci int_to_scsilun(lun, (struct scsi_lun *) scsi_lun); 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_LUN_RESET; 12418c2ecf20Sopenharmony_ci mbox_cmd[1] = ddb_entry->fw_ddb_index; 12428c2ecf20Sopenharmony_ci /* FW expects LUN bytes 0-3 in Incoming Mailbox 2 12438c2ecf20Sopenharmony_ci * (LUN byte 0 is LSByte, byte 3 is MSByte) */ 12448c2ecf20Sopenharmony_ci mbox_cmd[2] = cpu_to_le32(scsi_lun[0]); 12458c2ecf20Sopenharmony_ci /* FW expects LUN bytes 4-7 in Incoming Mailbox 3 12468c2ecf20Sopenharmony_ci * (LUN byte 4 is LSByte, byte 7 is MSByte) */ 12478c2ecf20Sopenharmony_ci mbox_cmd[3] = cpu_to_le32(scsi_lun[1]); 12488c2ecf20Sopenharmony_ci mbox_cmd[5] = 0x01; /* Immediate Command Enable */ 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]); 12518c2ecf20Sopenharmony_ci if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE && 12528c2ecf20Sopenharmony_ci mbox_sts[0] != MBOX_STS_COMMAND_ERROR) 12538c2ecf20Sopenharmony_ci status = QLA_ERROR; 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ci return status; 12568c2ecf20Sopenharmony_ci} 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci/** 12598c2ecf20Sopenharmony_ci * qla4xxx_reset_target - issues target Reset 12608c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 12618c2ecf20Sopenharmony_ci * @ddb_entry: Pointer to device database entry 12628c2ecf20Sopenharmony_ci * 12638c2ecf20Sopenharmony_ci * This routine performs a TARGET RESET on the specified target. 12648c2ecf20Sopenharmony_ci * The caller must ensure that the ddb_entry pointers 12658c2ecf20Sopenharmony_ci * are valid before calling this routine. 12668c2ecf20Sopenharmony_ci **/ 12678c2ecf20Sopenharmony_ciint qla4xxx_reset_target(struct scsi_qla_host *ha, 12688c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry) 12698c2ecf20Sopenharmony_ci{ 12708c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 12718c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 12728c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no, 12758c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_index)); 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci /* 12788c2ecf20Sopenharmony_ci * Send target reset command to ISP, so that the ISP will return all 12798c2ecf20Sopenharmony_ci * outstanding requests with RESET status 12808c2ecf20Sopenharmony_ci */ 12818c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 12828c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_TARGET_WARM_RESET; 12858c2ecf20Sopenharmony_ci mbox_cmd[1] = ddb_entry->fw_ddb_index; 12868c2ecf20Sopenharmony_ci mbox_cmd[5] = 0x01; /* Immediate Command Enable */ 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], 12898c2ecf20Sopenharmony_ci &mbox_sts[0]); 12908c2ecf20Sopenharmony_ci if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE && 12918c2ecf20Sopenharmony_ci mbox_sts[0] != MBOX_STS_COMMAND_ERROR) 12928c2ecf20Sopenharmony_ci status = QLA_ERROR; 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci return status; 12958c2ecf20Sopenharmony_ci} 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ciint qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr, 12988c2ecf20Sopenharmony_ci uint32_t offset, uint32_t len) 12998c2ecf20Sopenharmony_ci{ 13008c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 13018c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 13048c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_READ_FLASH; 13078c2ecf20Sopenharmony_ci mbox_cmd[1] = LSDW(dma_addr); 13088c2ecf20Sopenharmony_ci mbox_cmd[2] = MSDW(dma_addr); 13098c2ecf20Sopenharmony_ci mbox_cmd[3] = offset; 13108c2ecf20Sopenharmony_ci mbox_cmd[4] = len; 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], &mbox_sts[0]) != 13138c2ecf20Sopenharmony_ci QLA_SUCCESS) { 13148c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ " 13158c2ecf20Sopenharmony_ci "status %04X %04X, offset %08x, len %08x\n", ha->host_no, 13168c2ecf20Sopenharmony_ci __func__, mbox_sts[0], mbox_sts[1], offset, len)); 13178c2ecf20Sopenharmony_ci return QLA_ERROR; 13188c2ecf20Sopenharmony_ci } 13198c2ecf20Sopenharmony_ci return QLA_SUCCESS; 13208c2ecf20Sopenharmony_ci} 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci/** 13238c2ecf20Sopenharmony_ci * qla4xxx_about_firmware - gets FW, iscsi draft and boot loader version 13248c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 13258c2ecf20Sopenharmony_ci * 13268c2ecf20Sopenharmony_ci * Retrieves the FW version, iSCSI draft version & bootloader version of HBA. 13278c2ecf20Sopenharmony_ci * Mailboxes 2 & 3 may hold an address for data. Make sure that we write 0 to 13288c2ecf20Sopenharmony_ci * those mailboxes, if unused. 13298c2ecf20Sopenharmony_ci **/ 13308c2ecf20Sopenharmony_ciint qla4xxx_about_firmware(struct scsi_qla_host *ha) 13318c2ecf20Sopenharmony_ci{ 13328c2ecf20Sopenharmony_ci struct about_fw_info *about_fw = NULL; 13338c2ecf20Sopenharmony_ci dma_addr_t about_fw_dma; 13348c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 13358c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 13368c2ecf20Sopenharmony_ci int status = QLA_ERROR; 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_ci about_fw = dma_alloc_coherent(&ha->pdev->dev, 13398c2ecf20Sopenharmony_ci sizeof(struct about_fw_info), 13408c2ecf20Sopenharmony_ci &about_fw_dma, GFP_KERNEL); 13418c2ecf20Sopenharmony_ci if (!about_fw) { 13428c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Unable to alloc memory " 13438c2ecf20Sopenharmony_ci "for about_fw\n", __func__)); 13448c2ecf20Sopenharmony_ci return status; 13458c2ecf20Sopenharmony_ci } 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 13488c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_ABOUT_FW; 13518c2ecf20Sopenharmony_ci mbox_cmd[2] = LSDW(about_fw_dma); 13528c2ecf20Sopenharmony_ci mbox_cmd[3] = MSDW(about_fw_dma); 13538c2ecf20Sopenharmony_ci mbox_cmd[4] = sizeof(struct about_fw_info); 13548c2ecf20Sopenharmony_ci 13558c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT, 13568c2ecf20Sopenharmony_ci &mbox_cmd[0], &mbox_sts[0]); 13578c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) { 13588c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_ABOUT_FW " 13598c2ecf20Sopenharmony_ci "failed w/ status %04X\n", __func__, 13608c2ecf20Sopenharmony_ci mbox_sts[0])); 13618c2ecf20Sopenharmony_ci goto exit_about_fw; 13628c2ecf20Sopenharmony_ci } 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci /* Save version information. */ 13658c2ecf20Sopenharmony_ci ha->fw_info.fw_major = le16_to_cpu(about_fw->fw_major); 13668c2ecf20Sopenharmony_ci ha->fw_info.fw_minor = le16_to_cpu(about_fw->fw_minor); 13678c2ecf20Sopenharmony_ci ha->fw_info.fw_patch = le16_to_cpu(about_fw->fw_patch); 13688c2ecf20Sopenharmony_ci ha->fw_info.fw_build = le16_to_cpu(about_fw->fw_build); 13698c2ecf20Sopenharmony_ci memcpy(ha->fw_info.fw_build_date, about_fw->fw_build_date, 13708c2ecf20Sopenharmony_ci sizeof(about_fw->fw_build_date)); 13718c2ecf20Sopenharmony_ci memcpy(ha->fw_info.fw_build_time, about_fw->fw_build_time, 13728c2ecf20Sopenharmony_ci sizeof(about_fw->fw_build_time)); 13738c2ecf20Sopenharmony_ci strcpy((char *)ha->fw_info.fw_build_user, 13748c2ecf20Sopenharmony_ci skip_spaces((char *)about_fw->fw_build_user)); 13758c2ecf20Sopenharmony_ci ha->fw_info.fw_load_source = le16_to_cpu(about_fw->fw_load_source); 13768c2ecf20Sopenharmony_ci ha->fw_info.iscsi_major = le16_to_cpu(about_fw->iscsi_major); 13778c2ecf20Sopenharmony_ci ha->fw_info.iscsi_minor = le16_to_cpu(about_fw->iscsi_minor); 13788c2ecf20Sopenharmony_ci ha->fw_info.bootload_major = le16_to_cpu(about_fw->bootload_major); 13798c2ecf20Sopenharmony_ci ha->fw_info.bootload_minor = le16_to_cpu(about_fw->bootload_minor); 13808c2ecf20Sopenharmony_ci ha->fw_info.bootload_patch = le16_to_cpu(about_fw->bootload_patch); 13818c2ecf20Sopenharmony_ci ha->fw_info.bootload_build = le16_to_cpu(about_fw->bootload_build); 13828c2ecf20Sopenharmony_ci strcpy((char *)ha->fw_info.extended_timestamp, 13838c2ecf20Sopenharmony_ci skip_spaces((char *)about_fw->extended_timestamp)); 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci ha->fw_uptime_secs = le32_to_cpu(mbox_sts[5]); 13868c2ecf20Sopenharmony_ci ha->fw_uptime_msecs = le32_to_cpu(mbox_sts[6]); 13878c2ecf20Sopenharmony_ci status = QLA_SUCCESS; 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_ciexit_about_fw: 13908c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(struct about_fw_info), 13918c2ecf20Sopenharmony_ci about_fw, about_fw_dma); 13928c2ecf20Sopenharmony_ci return status; 13938c2ecf20Sopenharmony_ci} 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ciint qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options, 13968c2ecf20Sopenharmony_ci dma_addr_t dma_addr) 13978c2ecf20Sopenharmony_ci{ 13988c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 13998c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 14028c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS; 14058c2ecf20Sopenharmony_ci mbox_cmd[1] = options; 14068c2ecf20Sopenharmony_ci mbox_cmd[2] = LSDW(dma_addr); 14078c2ecf20Sopenharmony_ci mbox_cmd[3] = MSDW(dma_addr); 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) != 14108c2ecf20Sopenharmony_ci QLA_SUCCESS) { 14118c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: failed status %04X\n", 14128c2ecf20Sopenharmony_ci ha->host_no, __func__, mbox_sts[0])); 14138c2ecf20Sopenharmony_ci return QLA_ERROR; 14148c2ecf20Sopenharmony_ci } 14158c2ecf20Sopenharmony_ci return QLA_SUCCESS; 14168c2ecf20Sopenharmony_ci} 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_ciint qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index, 14198c2ecf20Sopenharmony_ci uint32_t *mbx_sts) 14208c2ecf20Sopenharmony_ci{ 14218c2ecf20Sopenharmony_ci int status; 14228c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 14238c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 14268c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 14278c2ecf20Sopenharmony_ci 14288c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY; 14298c2ecf20Sopenharmony_ci mbox_cmd[1] = ddb_index; 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], 14328c2ecf20Sopenharmony_ci &mbox_sts[0]); 14338c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) { 14348c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", 14358c2ecf20Sopenharmony_ci __func__, mbox_sts[0])); 14368c2ecf20Sopenharmony_ci } 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci *mbx_sts = mbox_sts[0]; 14398c2ecf20Sopenharmony_ci return status; 14408c2ecf20Sopenharmony_ci} 14418c2ecf20Sopenharmony_ci 14428c2ecf20Sopenharmony_ciint qla4xxx_clear_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index) 14438c2ecf20Sopenharmony_ci{ 14448c2ecf20Sopenharmony_ci int status; 14458c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 14468c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 14498c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY; 14528c2ecf20Sopenharmony_ci mbox_cmd[1] = ddb_index; 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, 2, 1, &mbox_cmd[0], 14558c2ecf20Sopenharmony_ci &mbox_sts[0]); 14568c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) { 14578c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", 14588c2ecf20Sopenharmony_ci __func__, mbox_sts[0])); 14598c2ecf20Sopenharmony_ci } 14608c2ecf20Sopenharmony_ci 14618c2ecf20Sopenharmony_ci return status; 14628c2ecf20Sopenharmony_ci} 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_ciint qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr, 14658c2ecf20Sopenharmony_ci uint32_t offset, uint32_t length, uint32_t options) 14668c2ecf20Sopenharmony_ci{ 14678c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 14688c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 14698c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 14728c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_WRITE_FLASH; 14758c2ecf20Sopenharmony_ci mbox_cmd[1] = LSDW(dma_addr); 14768c2ecf20Sopenharmony_ci mbox_cmd[2] = MSDW(dma_addr); 14778c2ecf20Sopenharmony_ci mbox_cmd[3] = offset; 14788c2ecf20Sopenharmony_ci mbox_cmd[4] = length; 14798c2ecf20Sopenharmony_ci mbox_cmd[5] = options; 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, 6, 2, &mbox_cmd[0], &mbox_sts[0]); 14828c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) { 14838c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_WRITE_FLASH " 14848c2ecf20Sopenharmony_ci "failed w/ status %04X, mbx1 %04X\n", 14858c2ecf20Sopenharmony_ci __func__, mbox_sts[0], mbox_sts[1])); 14868c2ecf20Sopenharmony_ci } 14878c2ecf20Sopenharmony_ci return status; 14888c2ecf20Sopenharmony_ci} 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ciint qla4xxx_bootdb_by_index(struct scsi_qla_host *ha, 14918c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry, 14928c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index) 14938c2ecf20Sopenharmony_ci{ 14948c2ecf20Sopenharmony_ci uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO; 14958c2ecf20Sopenharmony_ci uint32_t dev_db_end_offset; 14968c2ecf20Sopenharmony_ci int status = QLA_ERROR; 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry)); 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry)); 15018c2ecf20Sopenharmony_ci dev_db_end_offset = FLASH_OFFSET_DB_END; 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci if (dev_db_start_offset > dev_db_end_offset) { 15048c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, 15058c2ecf20Sopenharmony_ci "%s:Invalid DDB index %d", __func__, 15068c2ecf20Sopenharmony_ci ddb_index)); 15078c2ecf20Sopenharmony_ci goto exit_bootdb_failed; 15088c2ecf20Sopenharmony_ci } 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset, 15118c2ecf20Sopenharmony_ci sizeof(*fw_ddb_entry)) != QLA_SUCCESS) { 15128c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash" 15138c2ecf20Sopenharmony_ci "failed\n", ha->host_no, __func__); 15148c2ecf20Sopenharmony_ci goto exit_bootdb_failed; 15158c2ecf20Sopenharmony_ci } 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci if (fw_ddb_entry->cookie == DDB_VALID_COOKIE) 15188c2ecf20Sopenharmony_ci status = QLA_SUCCESS; 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_ciexit_bootdb_failed: 15218c2ecf20Sopenharmony_ci return status; 15228c2ecf20Sopenharmony_ci} 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ciint qla4xxx_flashdb_by_index(struct scsi_qla_host *ha, 15258c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry, 15268c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index) 15278c2ecf20Sopenharmony_ci{ 15288c2ecf20Sopenharmony_ci uint32_t dev_db_start_offset; 15298c2ecf20Sopenharmony_ci uint32_t dev_db_end_offset; 15308c2ecf20Sopenharmony_ci int status = QLA_ERROR; 15318c2ecf20Sopenharmony_ci 15328c2ecf20Sopenharmony_ci memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry)); 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_ci if (is_qla40XX(ha)) { 15358c2ecf20Sopenharmony_ci dev_db_start_offset = FLASH_OFFSET_DB_INFO; 15368c2ecf20Sopenharmony_ci dev_db_end_offset = FLASH_OFFSET_DB_END; 15378c2ecf20Sopenharmony_ci } else { 15388c2ecf20Sopenharmony_ci dev_db_start_offset = FLASH_RAW_ACCESS_ADDR + 15398c2ecf20Sopenharmony_ci (ha->hw.flt_region_ddb << 2); 15408c2ecf20Sopenharmony_ci /* flt_ddb_size is DDB table size for both ports 15418c2ecf20Sopenharmony_ci * so divide it by 2 to calculate the offset for second port 15428c2ecf20Sopenharmony_ci */ 15438c2ecf20Sopenharmony_ci if (ha->port_num == 1) 15448c2ecf20Sopenharmony_ci dev_db_start_offset += (ha->hw.flt_ddb_size / 2); 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci dev_db_end_offset = dev_db_start_offset + 15478c2ecf20Sopenharmony_ci (ha->hw.flt_ddb_size / 2); 15488c2ecf20Sopenharmony_ci } 15498c2ecf20Sopenharmony_ci 15508c2ecf20Sopenharmony_ci dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry)); 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_ci if (dev_db_start_offset > dev_db_end_offset) { 15538c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, 15548c2ecf20Sopenharmony_ci "%s:Invalid DDB index %d", __func__, 15558c2ecf20Sopenharmony_ci ddb_index)); 15568c2ecf20Sopenharmony_ci goto exit_fdb_failed; 15578c2ecf20Sopenharmony_ci } 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset, 15608c2ecf20Sopenharmony_ci sizeof(*fw_ddb_entry)) != QLA_SUCCESS) { 15618c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash failed\n", 15628c2ecf20Sopenharmony_ci ha->host_no, __func__); 15638c2ecf20Sopenharmony_ci goto exit_fdb_failed; 15648c2ecf20Sopenharmony_ci } 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci if (fw_ddb_entry->cookie == DDB_VALID_COOKIE) 15678c2ecf20Sopenharmony_ci status = QLA_SUCCESS; 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ciexit_fdb_failed: 15708c2ecf20Sopenharmony_ci return status; 15718c2ecf20Sopenharmony_ci} 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_ciint qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password, 15748c2ecf20Sopenharmony_ci uint16_t idx) 15758c2ecf20Sopenharmony_ci{ 15768c2ecf20Sopenharmony_ci int ret = 0; 15778c2ecf20Sopenharmony_ci int rval = QLA_ERROR; 15788c2ecf20Sopenharmony_ci uint32_t offset = 0, chap_size; 15798c2ecf20Sopenharmony_ci struct ql4_chap_table *chap_table; 15808c2ecf20Sopenharmony_ci dma_addr_t chap_dma; 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_ci chap_table = dma_pool_zalloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma); 15838c2ecf20Sopenharmony_ci if (chap_table == NULL) 15848c2ecf20Sopenharmony_ci return -ENOMEM; 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci chap_size = sizeof(struct ql4_chap_table); 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci if (is_qla40XX(ha)) 15898c2ecf20Sopenharmony_ci offset = FLASH_CHAP_OFFSET | (idx * chap_size); 15908c2ecf20Sopenharmony_ci else { 15918c2ecf20Sopenharmony_ci offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2); 15928c2ecf20Sopenharmony_ci /* flt_chap_size is CHAP table size for both ports 15938c2ecf20Sopenharmony_ci * so divide it by 2 to calculate the offset for second port 15948c2ecf20Sopenharmony_ci */ 15958c2ecf20Sopenharmony_ci if (ha->port_num == 1) 15968c2ecf20Sopenharmony_ci offset += (ha->hw.flt_chap_size / 2); 15978c2ecf20Sopenharmony_ci offset += (idx * chap_size); 15988c2ecf20Sopenharmony_ci } 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size); 16018c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 16028c2ecf20Sopenharmony_ci ret = -EINVAL; 16038c2ecf20Sopenharmony_ci goto exit_get_chap; 16048c2ecf20Sopenharmony_ci } 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Chap Cookie: x%x\n", 16078c2ecf20Sopenharmony_ci __le16_to_cpu(chap_table->cookie))); 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci if (__le16_to_cpu(chap_table->cookie) != CHAP_VALID_COOKIE) { 16108c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "No valid chap entry found\n"); 16118c2ecf20Sopenharmony_ci goto exit_get_chap; 16128c2ecf20Sopenharmony_ci } 16138c2ecf20Sopenharmony_ci 16148c2ecf20Sopenharmony_ci strlcpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); 16158c2ecf20Sopenharmony_ci strlcpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); 16168c2ecf20Sopenharmony_ci chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE); 16178c2ecf20Sopenharmony_ci 16188c2ecf20Sopenharmony_ciexit_get_chap: 16198c2ecf20Sopenharmony_ci dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma); 16208c2ecf20Sopenharmony_ci return ret; 16218c2ecf20Sopenharmony_ci} 16228c2ecf20Sopenharmony_ci 16238c2ecf20Sopenharmony_ci/** 16248c2ecf20Sopenharmony_ci * qla4xxx_set_chap - Make a chap entry at the given index 16258c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 16268c2ecf20Sopenharmony_ci * @username: CHAP username to set 16278c2ecf20Sopenharmony_ci * @password: CHAP password to set 16288c2ecf20Sopenharmony_ci * @idx: CHAP index at which to make the entry 16298c2ecf20Sopenharmony_ci * @bidi: type of chap entry (chap_in or chap_out) 16308c2ecf20Sopenharmony_ci * 16318c2ecf20Sopenharmony_ci * Create chap entry at the given index with the information provided. 16328c2ecf20Sopenharmony_ci * 16338c2ecf20Sopenharmony_ci * Note: Caller should acquire the chap lock before getting here. 16348c2ecf20Sopenharmony_ci **/ 16358c2ecf20Sopenharmony_ciint qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, char *password, 16368c2ecf20Sopenharmony_ci uint16_t idx, int bidi) 16378c2ecf20Sopenharmony_ci{ 16388c2ecf20Sopenharmony_ci int ret = 0; 16398c2ecf20Sopenharmony_ci int rval = QLA_ERROR; 16408c2ecf20Sopenharmony_ci uint32_t offset = 0; 16418c2ecf20Sopenharmony_ci struct ql4_chap_table *chap_table; 16428c2ecf20Sopenharmony_ci uint32_t chap_size = 0; 16438c2ecf20Sopenharmony_ci dma_addr_t chap_dma; 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ci chap_table = dma_pool_zalloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma); 16468c2ecf20Sopenharmony_ci if (chap_table == NULL) { 16478c2ecf20Sopenharmony_ci ret = -ENOMEM; 16488c2ecf20Sopenharmony_ci goto exit_set_chap; 16498c2ecf20Sopenharmony_ci } 16508c2ecf20Sopenharmony_ci 16518c2ecf20Sopenharmony_ci if (bidi) 16528c2ecf20Sopenharmony_ci chap_table->flags |= BIT_6; /* peer */ 16538c2ecf20Sopenharmony_ci else 16548c2ecf20Sopenharmony_ci chap_table->flags |= BIT_7; /* local */ 16558c2ecf20Sopenharmony_ci chap_table->secret_len = strlen(password); 16568c2ecf20Sopenharmony_ci strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN - 1); 16578c2ecf20Sopenharmony_ci strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN - 1); 16588c2ecf20Sopenharmony_ci chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE); 16598c2ecf20Sopenharmony_ci 16608c2ecf20Sopenharmony_ci if (is_qla40XX(ha)) { 16618c2ecf20Sopenharmony_ci chap_size = MAX_CHAP_ENTRIES_40XX * sizeof(*chap_table); 16628c2ecf20Sopenharmony_ci offset = FLASH_CHAP_OFFSET; 16638c2ecf20Sopenharmony_ci } else { /* Single region contains CHAP info for both ports which is 16648c2ecf20Sopenharmony_ci * divided into half for each port. 16658c2ecf20Sopenharmony_ci */ 16668c2ecf20Sopenharmony_ci chap_size = ha->hw.flt_chap_size / 2; 16678c2ecf20Sopenharmony_ci offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2); 16688c2ecf20Sopenharmony_ci if (ha->port_num == 1) 16698c2ecf20Sopenharmony_ci offset += chap_size; 16708c2ecf20Sopenharmony_ci } 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci offset += (idx * sizeof(struct ql4_chap_table)); 16738c2ecf20Sopenharmony_ci rval = qla4xxx_set_flash(ha, chap_dma, offset, 16748c2ecf20Sopenharmony_ci sizeof(struct ql4_chap_table), 16758c2ecf20Sopenharmony_ci FLASH_OPT_RMW_COMMIT); 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci if (rval == QLA_SUCCESS && ha->chap_list) { 16788c2ecf20Sopenharmony_ci /* Update ha chap_list cache */ 16798c2ecf20Sopenharmony_ci memcpy((struct ql4_chap_table *)ha->chap_list + idx, 16808c2ecf20Sopenharmony_ci chap_table, sizeof(struct ql4_chap_table)); 16818c2ecf20Sopenharmony_ci } 16828c2ecf20Sopenharmony_ci dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma); 16838c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 16848c2ecf20Sopenharmony_ci ret = -EINVAL; 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_ciexit_set_chap: 16878c2ecf20Sopenharmony_ci return ret; 16888c2ecf20Sopenharmony_ci} 16898c2ecf20Sopenharmony_ci 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_ciint qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username, 16928c2ecf20Sopenharmony_ci char *password, uint16_t chap_index) 16938c2ecf20Sopenharmony_ci{ 16948c2ecf20Sopenharmony_ci int rval = QLA_ERROR; 16958c2ecf20Sopenharmony_ci struct ql4_chap_table *chap_table = NULL; 16968c2ecf20Sopenharmony_ci int max_chap_entries; 16978c2ecf20Sopenharmony_ci 16988c2ecf20Sopenharmony_ci if (!ha->chap_list) { 16998c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n"); 17008c2ecf20Sopenharmony_ci rval = QLA_ERROR; 17018c2ecf20Sopenharmony_ci goto exit_uni_chap; 17028c2ecf20Sopenharmony_ci } 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_ci if (!username || !password) { 17058c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "No memory for username & secret\n"); 17068c2ecf20Sopenharmony_ci rval = QLA_ERROR; 17078c2ecf20Sopenharmony_ci goto exit_uni_chap; 17088c2ecf20Sopenharmony_ci } 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) 17118c2ecf20Sopenharmony_ci max_chap_entries = (ha->hw.flt_chap_size / 2) / 17128c2ecf20Sopenharmony_ci sizeof(struct ql4_chap_table); 17138c2ecf20Sopenharmony_ci else 17148c2ecf20Sopenharmony_ci max_chap_entries = MAX_CHAP_ENTRIES_40XX; 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_ci if (chap_index > max_chap_entries) { 17178c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Invalid Chap index\n"); 17188c2ecf20Sopenharmony_ci rval = QLA_ERROR; 17198c2ecf20Sopenharmony_ci goto exit_uni_chap; 17208c2ecf20Sopenharmony_ci } 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci mutex_lock(&ha->chap_sem); 17238c2ecf20Sopenharmony_ci chap_table = (struct ql4_chap_table *)ha->chap_list + chap_index; 17248c2ecf20Sopenharmony_ci if (chap_table->cookie != __constant_cpu_to_le16(CHAP_VALID_COOKIE)) { 17258c2ecf20Sopenharmony_ci rval = QLA_ERROR; 17268c2ecf20Sopenharmony_ci goto exit_unlock_uni_chap; 17278c2ecf20Sopenharmony_ci } 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci if (!(chap_table->flags & BIT_7)) { 17308c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Unidirectional entry not set\n"); 17318c2ecf20Sopenharmony_ci rval = QLA_ERROR; 17328c2ecf20Sopenharmony_ci goto exit_unlock_uni_chap; 17338c2ecf20Sopenharmony_ci } 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci strlcpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN); 17368c2ecf20Sopenharmony_ci strlcpy(username, chap_table->name, MAX_CHAP_NAME_LEN); 17378c2ecf20Sopenharmony_ci 17388c2ecf20Sopenharmony_ci rval = QLA_SUCCESS; 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ciexit_unlock_uni_chap: 17418c2ecf20Sopenharmony_ci mutex_unlock(&ha->chap_sem); 17428c2ecf20Sopenharmony_ciexit_uni_chap: 17438c2ecf20Sopenharmony_ci return rval; 17448c2ecf20Sopenharmony_ci} 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_ci/** 17478c2ecf20Sopenharmony_ci * qla4xxx_get_chap_index - Get chap index given username and secret 17488c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 17498c2ecf20Sopenharmony_ci * @username: CHAP username to be searched 17508c2ecf20Sopenharmony_ci * @password: CHAP password to be searched 17518c2ecf20Sopenharmony_ci * @bidi: Is this a BIDI CHAP 17528c2ecf20Sopenharmony_ci * @chap_index: CHAP index to be returned 17538c2ecf20Sopenharmony_ci * 17548c2ecf20Sopenharmony_ci * Match the username and password in the chap_list, return the index if a 17558c2ecf20Sopenharmony_ci * match is found. If a match is not found then add the entry in FLASH and 17568c2ecf20Sopenharmony_ci * return the index at which entry is written in the FLASH. 17578c2ecf20Sopenharmony_ci **/ 17588c2ecf20Sopenharmony_ciint qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username, 17598c2ecf20Sopenharmony_ci char *password, int bidi, uint16_t *chap_index) 17608c2ecf20Sopenharmony_ci{ 17618c2ecf20Sopenharmony_ci int i, rval; 17628c2ecf20Sopenharmony_ci int free_index = -1; 17638c2ecf20Sopenharmony_ci int found_index = 0; 17648c2ecf20Sopenharmony_ci int max_chap_entries = 0; 17658c2ecf20Sopenharmony_ci struct ql4_chap_table *chap_table; 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) 17688c2ecf20Sopenharmony_ci max_chap_entries = (ha->hw.flt_chap_size / 2) / 17698c2ecf20Sopenharmony_ci sizeof(struct ql4_chap_table); 17708c2ecf20Sopenharmony_ci else 17718c2ecf20Sopenharmony_ci max_chap_entries = MAX_CHAP_ENTRIES_40XX; 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_ci if (!ha->chap_list) { 17748c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n"); 17758c2ecf20Sopenharmony_ci return QLA_ERROR; 17768c2ecf20Sopenharmony_ci } 17778c2ecf20Sopenharmony_ci 17788c2ecf20Sopenharmony_ci if (!username || !password) { 17798c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Do not have username and psw\n"); 17808c2ecf20Sopenharmony_ci return QLA_ERROR; 17818c2ecf20Sopenharmony_ci } 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_ci mutex_lock(&ha->chap_sem); 17848c2ecf20Sopenharmony_ci for (i = 0; i < max_chap_entries; i++) { 17858c2ecf20Sopenharmony_ci chap_table = (struct ql4_chap_table *)ha->chap_list + i; 17868c2ecf20Sopenharmony_ci if (chap_table->cookie != 17878c2ecf20Sopenharmony_ci __constant_cpu_to_le16(CHAP_VALID_COOKIE)) { 17888c2ecf20Sopenharmony_ci if (i > MAX_RESRV_CHAP_IDX && free_index == -1) 17898c2ecf20Sopenharmony_ci free_index = i; 17908c2ecf20Sopenharmony_ci continue; 17918c2ecf20Sopenharmony_ci } 17928c2ecf20Sopenharmony_ci if (bidi) { 17938c2ecf20Sopenharmony_ci if (chap_table->flags & BIT_7) 17948c2ecf20Sopenharmony_ci continue; 17958c2ecf20Sopenharmony_ci } else { 17968c2ecf20Sopenharmony_ci if (chap_table->flags & BIT_6) 17978c2ecf20Sopenharmony_ci continue; 17988c2ecf20Sopenharmony_ci } 17998c2ecf20Sopenharmony_ci if (!strncmp(chap_table->secret, password, 18008c2ecf20Sopenharmony_ci MAX_CHAP_SECRET_LEN) && 18018c2ecf20Sopenharmony_ci !strncmp(chap_table->name, username, 18028c2ecf20Sopenharmony_ci MAX_CHAP_NAME_LEN)) { 18038c2ecf20Sopenharmony_ci *chap_index = i; 18048c2ecf20Sopenharmony_ci found_index = 1; 18058c2ecf20Sopenharmony_ci break; 18068c2ecf20Sopenharmony_ci } 18078c2ecf20Sopenharmony_ci } 18088c2ecf20Sopenharmony_ci 18098c2ecf20Sopenharmony_ci /* If chap entry is not present and a free index is available then 18108c2ecf20Sopenharmony_ci * write the entry in flash 18118c2ecf20Sopenharmony_ci */ 18128c2ecf20Sopenharmony_ci if (!found_index && free_index != -1) { 18138c2ecf20Sopenharmony_ci rval = qla4xxx_set_chap(ha, username, password, 18148c2ecf20Sopenharmony_ci free_index, bidi); 18158c2ecf20Sopenharmony_ci if (!rval) { 18168c2ecf20Sopenharmony_ci *chap_index = free_index; 18178c2ecf20Sopenharmony_ci found_index = 1; 18188c2ecf20Sopenharmony_ci } 18198c2ecf20Sopenharmony_ci } 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ci mutex_unlock(&ha->chap_sem); 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci if (found_index) 18248c2ecf20Sopenharmony_ci return QLA_SUCCESS; 18258c2ecf20Sopenharmony_ci return QLA_ERROR; 18268c2ecf20Sopenharmony_ci} 18278c2ecf20Sopenharmony_ci 18288c2ecf20Sopenharmony_ciint qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha, 18298c2ecf20Sopenharmony_ci uint16_t fw_ddb_index, 18308c2ecf20Sopenharmony_ci uint16_t connection_id, 18318c2ecf20Sopenharmony_ci uint16_t option) 18328c2ecf20Sopenharmony_ci{ 18338c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 18348c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 18358c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 18368c2ecf20Sopenharmony_ci 18378c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 18388c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 18398c2ecf20Sopenharmony_ci 18408c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT; 18418c2ecf20Sopenharmony_ci mbox_cmd[1] = fw_ddb_index; 18428c2ecf20Sopenharmony_ci mbox_cmd[2] = connection_id; 18438c2ecf20Sopenharmony_ci mbox_cmd[3] = option; 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]); 18468c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) { 18478c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_CONN_CLOSE " 18488c2ecf20Sopenharmony_ci "option %04x failed w/ status %04X %04X\n", 18498c2ecf20Sopenharmony_ci __func__, option, mbox_sts[0], mbox_sts[1])); 18508c2ecf20Sopenharmony_ci } 18518c2ecf20Sopenharmony_ci return status; 18528c2ecf20Sopenharmony_ci} 18538c2ecf20Sopenharmony_ci 18548c2ecf20Sopenharmony_ci/** 18558c2ecf20Sopenharmony_ci * qla4_84xx_extend_idc_tmo - Extend IDC Timeout. 18568c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 18578c2ecf20Sopenharmony_ci * @ext_tmo: idc timeout value 18588c2ecf20Sopenharmony_ci * 18598c2ecf20Sopenharmony_ci * Requests firmware to extend the idc timeout value. 18608c2ecf20Sopenharmony_ci **/ 18618c2ecf20Sopenharmony_cistatic int qla4_84xx_extend_idc_tmo(struct scsi_qla_host *ha, uint32_t ext_tmo) 18628c2ecf20Sopenharmony_ci{ 18638c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 18648c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 18658c2ecf20Sopenharmony_ci int status; 18668c2ecf20Sopenharmony_ci 18678c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 18688c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 18698c2ecf20Sopenharmony_ci ext_tmo &= 0xf; 18708c2ecf20Sopenharmony_ci 18718c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_IDC_TIME_EXTEND; 18728c2ecf20Sopenharmony_ci mbox_cmd[1] = ((ha->idc_info.request_desc & 0xfffff0ff) | 18738c2ecf20Sopenharmony_ci (ext_tmo << 8)); /* new timeout */ 18748c2ecf20Sopenharmony_ci mbox_cmd[2] = ha->idc_info.info1; 18758c2ecf20Sopenharmony_ci mbox_cmd[3] = ha->idc_info.info2; 18768c2ecf20Sopenharmony_ci mbox_cmd[4] = ha->idc_info.info3; 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT, 18798c2ecf20Sopenharmony_ci mbox_cmd, mbox_sts); 18808c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) { 18818c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 18828c2ecf20Sopenharmony_ci "scsi%ld: %s: failed status %04X\n", 18838c2ecf20Sopenharmony_ci ha->host_no, __func__, mbox_sts[0])); 18848c2ecf20Sopenharmony_ci return QLA_ERROR; 18858c2ecf20Sopenharmony_ci } else { 18868c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: IDC timeout extended by %d secs\n", 18878c2ecf20Sopenharmony_ci __func__, ext_tmo); 18888c2ecf20Sopenharmony_ci } 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_ci return QLA_SUCCESS; 18918c2ecf20Sopenharmony_ci} 18928c2ecf20Sopenharmony_ci 18938c2ecf20Sopenharmony_ciint qla4xxx_disable_acb(struct scsi_qla_host *ha) 18948c2ecf20Sopenharmony_ci{ 18958c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 18968c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 18978c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 18988c2ecf20Sopenharmony_ci 18998c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 19008c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 19018c2ecf20Sopenharmony_ci 19028c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_DISABLE_ACB; 19038c2ecf20Sopenharmony_ci 19048c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, 8, 5, &mbox_cmd[0], &mbox_sts[0]); 19058c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) { 19068c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_DISABLE_ACB " 19078c2ecf20Sopenharmony_ci "failed w/ status %04X %04X %04X", __func__, 19088c2ecf20Sopenharmony_ci mbox_sts[0], mbox_sts[1], mbox_sts[2])); 19098c2ecf20Sopenharmony_ci } else { 19108c2ecf20Sopenharmony_ci if (is_qla8042(ha) && 19118c2ecf20Sopenharmony_ci test_bit(DPC_POST_IDC_ACK, &ha->dpc_flags) && 19128c2ecf20Sopenharmony_ci (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE)) { 19138c2ecf20Sopenharmony_ci /* 19148c2ecf20Sopenharmony_ci * Disable ACB mailbox command takes time to complete 19158c2ecf20Sopenharmony_ci * based on the total number of targets connected. 19168c2ecf20Sopenharmony_ci * For 512 targets, it took approximately 5 secs to 19178c2ecf20Sopenharmony_ci * complete. Setting the timeout value to 8, with the 3 19188c2ecf20Sopenharmony_ci * secs buffer. 19198c2ecf20Sopenharmony_ci */ 19208c2ecf20Sopenharmony_ci qla4_84xx_extend_idc_tmo(ha, IDC_EXTEND_TOV); 19218c2ecf20Sopenharmony_ci if (!wait_for_completion_timeout(&ha->disable_acb_comp, 19228c2ecf20Sopenharmony_ci IDC_EXTEND_TOV * HZ)) { 19238c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "%s: Disable ACB Completion not received\n", 19248c2ecf20Sopenharmony_ci __func__); 19258c2ecf20Sopenharmony_ci } 19268c2ecf20Sopenharmony_ci } 19278c2ecf20Sopenharmony_ci } 19288c2ecf20Sopenharmony_ci return status; 19298c2ecf20Sopenharmony_ci} 19308c2ecf20Sopenharmony_ci 19318c2ecf20Sopenharmony_ciint qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma, 19328c2ecf20Sopenharmony_ci uint32_t acb_type, uint32_t len) 19338c2ecf20Sopenharmony_ci{ 19348c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 19358c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 19368c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 19378c2ecf20Sopenharmony_ci 19388c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 19398c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 19408c2ecf20Sopenharmony_ci 19418c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_ACB; 19428c2ecf20Sopenharmony_ci mbox_cmd[1] = acb_type; 19438c2ecf20Sopenharmony_ci mbox_cmd[2] = LSDW(acb_dma); 19448c2ecf20Sopenharmony_ci mbox_cmd[3] = MSDW(acb_dma); 19458c2ecf20Sopenharmony_ci mbox_cmd[4] = len; 19468c2ecf20Sopenharmony_ci 19478c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]); 19488c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) { 19498c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_GET_ACB " 19508c2ecf20Sopenharmony_ci "failed w/ status %04X\n", __func__, 19518c2ecf20Sopenharmony_ci mbox_sts[0])); 19528c2ecf20Sopenharmony_ci } 19538c2ecf20Sopenharmony_ci return status; 19548c2ecf20Sopenharmony_ci} 19558c2ecf20Sopenharmony_ci 19568c2ecf20Sopenharmony_ciint qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, 19578c2ecf20Sopenharmony_ci uint32_t *mbox_sts, dma_addr_t acb_dma) 19588c2ecf20Sopenharmony_ci{ 19598c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 19608c2ecf20Sopenharmony_ci 19618c2ecf20Sopenharmony_ci memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT); 19628c2ecf20Sopenharmony_ci memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT); 19638c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_SET_ACB; 19648c2ecf20Sopenharmony_ci mbox_cmd[1] = 0; /* Primary ACB */ 19658c2ecf20Sopenharmony_ci mbox_cmd[2] = LSDW(acb_dma); 19668c2ecf20Sopenharmony_ci mbox_cmd[3] = MSDW(acb_dma); 19678c2ecf20Sopenharmony_ci mbox_cmd[4] = sizeof(struct addr_ctrl_blk); 19688c2ecf20Sopenharmony_ci 19698c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]); 19708c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) { 19718c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_SET_ACB " 19728c2ecf20Sopenharmony_ci "failed w/ status %04X\n", __func__, 19738c2ecf20Sopenharmony_ci mbox_sts[0])); 19748c2ecf20Sopenharmony_ci } 19758c2ecf20Sopenharmony_ci return status; 19768c2ecf20Sopenharmony_ci} 19778c2ecf20Sopenharmony_ci 19788c2ecf20Sopenharmony_ciint qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha, 19798c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry, 19808c2ecf20Sopenharmony_ci struct iscsi_cls_conn *cls_conn, 19818c2ecf20Sopenharmony_ci uint32_t *mbx_sts) 19828c2ecf20Sopenharmony_ci{ 19838c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry; 19848c2ecf20Sopenharmony_ci struct iscsi_conn *conn; 19858c2ecf20Sopenharmony_ci struct iscsi_session *sess; 19868c2ecf20Sopenharmony_ci struct qla_conn *qla_conn; 19878c2ecf20Sopenharmony_ci struct sockaddr *dst_addr; 19888c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma; 19898c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 19908c2ecf20Sopenharmony_ci int rval = 0; 19918c2ecf20Sopenharmony_ci struct sockaddr_in *addr; 19928c2ecf20Sopenharmony_ci struct sockaddr_in6 *addr6; 19938c2ecf20Sopenharmony_ci char *ip; 19948c2ecf20Sopenharmony_ci uint16_t iscsi_opts = 0; 19958c2ecf20Sopenharmony_ci uint32_t options = 0; 19968c2ecf20Sopenharmony_ci uint16_t idx, *ptid; 19978c2ecf20Sopenharmony_ci 19988c2ecf20Sopenharmony_ci fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 19998c2ecf20Sopenharmony_ci &fw_ddb_entry_dma, GFP_KERNEL); 20008c2ecf20Sopenharmony_ci if (!fw_ddb_entry) { 20018c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, 20028c2ecf20Sopenharmony_ci "%s: Unable to allocate dma buffer.\n", 20038c2ecf20Sopenharmony_ci __func__)); 20048c2ecf20Sopenharmony_ci rval = -ENOMEM; 20058c2ecf20Sopenharmony_ci goto exit_set_param_no_free; 20068c2ecf20Sopenharmony_ci } 20078c2ecf20Sopenharmony_ci 20088c2ecf20Sopenharmony_ci conn = cls_conn->dd_data; 20098c2ecf20Sopenharmony_ci qla_conn = conn->dd_data; 20108c2ecf20Sopenharmony_ci sess = conn->session; 20118c2ecf20Sopenharmony_ci dst_addr = (struct sockaddr *)&qla_conn->qla_ep->dst_addr; 20128c2ecf20Sopenharmony_ci 20138c2ecf20Sopenharmony_ci if (dst_addr->sa_family == AF_INET6) 20148c2ecf20Sopenharmony_ci options |= IPV6_DEFAULT_DDB_ENTRY; 20158c2ecf20Sopenharmony_ci 20168c2ecf20Sopenharmony_ci status = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma); 20178c2ecf20Sopenharmony_ci if (status == QLA_ERROR) { 20188c2ecf20Sopenharmony_ci rval = -EINVAL; 20198c2ecf20Sopenharmony_ci goto exit_set_param; 20208c2ecf20Sopenharmony_ci } 20218c2ecf20Sopenharmony_ci 20228c2ecf20Sopenharmony_ci ptid = (uint16_t *)&fw_ddb_entry->isid[1]; 20238c2ecf20Sopenharmony_ci *ptid = cpu_to_le16((uint16_t)ddb_entry->sess->target_id); 20248c2ecf20Sopenharmony_ci 20258c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "ISID [%pmR]\n", fw_ddb_entry->isid)); 20268c2ecf20Sopenharmony_ci 20278c2ecf20Sopenharmony_ci iscsi_opts = le16_to_cpu(fw_ddb_entry->iscsi_options); 20288c2ecf20Sopenharmony_ci memset(fw_ddb_entry->iscsi_alias, 0, sizeof(fw_ddb_entry->iscsi_alias)); 20298c2ecf20Sopenharmony_ci 20308c2ecf20Sopenharmony_ci memset(fw_ddb_entry->iscsi_name, 0, sizeof(fw_ddb_entry->iscsi_name)); 20318c2ecf20Sopenharmony_ci 20328c2ecf20Sopenharmony_ci if (sess->targetname != NULL) { 20338c2ecf20Sopenharmony_ci memcpy(fw_ddb_entry->iscsi_name, sess->targetname, 20348c2ecf20Sopenharmony_ci min(strlen(sess->targetname), 20358c2ecf20Sopenharmony_ci sizeof(fw_ddb_entry->iscsi_name))); 20368c2ecf20Sopenharmony_ci } 20378c2ecf20Sopenharmony_ci 20388c2ecf20Sopenharmony_ci memset(fw_ddb_entry->ip_addr, 0, sizeof(fw_ddb_entry->ip_addr)); 20398c2ecf20Sopenharmony_ci memset(fw_ddb_entry->tgt_addr, 0, sizeof(fw_ddb_entry->tgt_addr)); 20408c2ecf20Sopenharmony_ci 20418c2ecf20Sopenharmony_ci fw_ddb_entry->options = DDB_OPT_TARGET | DDB_OPT_AUTO_SENDTGTS_DISABLE; 20428c2ecf20Sopenharmony_ci 20438c2ecf20Sopenharmony_ci if (dst_addr->sa_family == AF_INET) { 20448c2ecf20Sopenharmony_ci addr = (struct sockaddr_in *)dst_addr; 20458c2ecf20Sopenharmony_ci ip = (char *)&addr->sin_addr; 20468c2ecf20Sopenharmony_ci memcpy(fw_ddb_entry->ip_addr, ip, IP_ADDR_LEN); 20478c2ecf20Sopenharmony_ci fw_ddb_entry->port = cpu_to_le16(ntohs(addr->sin_port)); 20488c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 20498c2ecf20Sopenharmony_ci "%s: Destination Address [%pI4]: index [%d]\n", 20508c2ecf20Sopenharmony_ci __func__, fw_ddb_entry->ip_addr, 20518c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_index)); 20528c2ecf20Sopenharmony_ci } else if (dst_addr->sa_family == AF_INET6) { 20538c2ecf20Sopenharmony_ci addr6 = (struct sockaddr_in6 *)dst_addr; 20548c2ecf20Sopenharmony_ci ip = (char *)&addr6->sin6_addr; 20558c2ecf20Sopenharmony_ci memcpy(fw_ddb_entry->ip_addr, ip, IPv6_ADDR_LEN); 20568c2ecf20Sopenharmony_ci fw_ddb_entry->port = cpu_to_le16(ntohs(addr6->sin6_port)); 20578c2ecf20Sopenharmony_ci fw_ddb_entry->options |= DDB_OPT_IPV6_DEVICE; 20588c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 20598c2ecf20Sopenharmony_ci "%s: Destination Address [%pI6]: index [%d]\n", 20608c2ecf20Sopenharmony_ci __func__, fw_ddb_entry->ip_addr, 20618c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_index)); 20628c2ecf20Sopenharmony_ci } else { 20638c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 20648c2ecf20Sopenharmony_ci "%s: Failed to get IP Address\n", 20658c2ecf20Sopenharmony_ci __func__); 20668c2ecf20Sopenharmony_ci rval = -EINVAL; 20678c2ecf20Sopenharmony_ci goto exit_set_param; 20688c2ecf20Sopenharmony_ci } 20698c2ecf20Sopenharmony_ci 20708c2ecf20Sopenharmony_ci /* CHAP */ 20718c2ecf20Sopenharmony_ci if (sess->username != NULL && sess->password != NULL) { 20728c2ecf20Sopenharmony_ci if (strlen(sess->username) && strlen(sess->password)) { 20738c2ecf20Sopenharmony_ci iscsi_opts |= BIT_7; 20748c2ecf20Sopenharmony_ci 20758c2ecf20Sopenharmony_ci rval = qla4xxx_get_chap_index(ha, sess->username, 20768c2ecf20Sopenharmony_ci sess->password, 20778c2ecf20Sopenharmony_ci LOCAL_CHAP, &idx); 20788c2ecf20Sopenharmony_ci if (rval) 20798c2ecf20Sopenharmony_ci goto exit_set_param; 20808c2ecf20Sopenharmony_ci 20818c2ecf20Sopenharmony_ci fw_ddb_entry->chap_tbl_idx = cpu_to_le16(idx); 20828c2ecf20Sopenharmony_ci } 20838c2ecf20Sopenharmony_ci } 20848c2ecf20Sopenharmony_ci 20858c2ecf20Sopenharmony_ci if (sess->username_in != NULL && sess->password_in != NULL) { 20868c2ecf20Sopenharmony_ci /* Check if BIDI CHAP */ 20878c2ecf20Sopenharmony_ci if (strlen(sess->username_in) && strlen(sess->password_in)) { 20888c2ecf20Sopenharmony_ci iscsi_opts |= BIT_4; 20898c2ecf20Sopenharmony_ci 20908c2ecf20Sopenharmony_ci rval = qla4xxx_get_chap_index(ha, sess->username_in, 20918c2ecf20Sopenharmony_ci sess->password_in, 20928c2ecf20Sopenharmony_ci BIDI_CHAP, &idx); 20938c2ecf20Sopenharmony_ci if (rval) 20948c2ecf20Sopenharmony_ci goto exit_set_param; 20958c2ecf20Sopenharmony_ci } 20968c2ecf20Sopenharmony_ci } 20978c2ecf20Sopenharmony_ci 20988c2ecf20Sopenharmony_ci if (sess->initial_r2t_en) 20998c2ecf20Sopenharmony_ci iscsi_opts |= BIT_10; 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_ci if (sess->imm_data_en) 21028c2ecf20Sopenharmony_ci iscsi_opts |= BIT_11; 21038c2ecf20Sopenharmony_ci 21048c2ecf20Sopenharmony_ci fw_ddb_entry->iscsi_options = cpu_to_le16(iscsi_opts); 21058c2ecf20Sopenharmony_ci 21068c2ecf20Sopenharmony_ci if (conn->max_recv_dlength) 21078c2ecf20Sopenharmony_ci fw_ddb_entry->iscsi_max_rcv_data_seg_len = 21088c2ecf20Sopenharmony_ci __constant_cpu_to_le16((conn->max_recv_dlength / BYTE_UNITS)); 21098c2ecf20Sopenharmony_ci 21108c2ecf20Sopenharmony_ci if (sess->max_r2t) 21118c2ecf20Sopenharmony_ci fw_ddb_entry->iscsi_max_outsnd_r2t = cpu_to_le16(sess->max_r2t); 21128c2ecf20Sopenharmony_ci 21138c2ecf20Sopenharmony_ci if (sess->first_burst) 21148c2ecf20Sopenharmony_ci fw_ddb_entry->iscsi_first_burst_len = 21158c2ecf20Sopenharmony_ci __constant_cpu_to_le16((sess->first_burst / BYTE_UNITS)); 21168c2ecf20Sopenharmony_ci 21178c2ecf20Sopenharmony_ci if (sess->max_burst) 21188c2ecf20Sopenharmony_ci fw_ddb_entry->iscsi_max_burst_len = 21198c2ecf20Sopenharmony_ci __constant_cpu_to_le16((sess->max_burst / BYTE_UNITS)); 21208c2ecf20Sopenharmony_ci 21218c2ecf20Sopenharmony_ci if (sess->time2wait) 21228c2ecf20Sopenharmony_ci fw_ddb_entry->iscsi_def_time2wait = 21238c2ecf20Sopenharmony_ci cpu_to_le16(sess->time2wait); 21248c2ecf20Sopenharmony_ci 21258c2ecf20Sopenharmony_ci if (sess->time2retain) 21268c2ecf20Sopenharmony_ci fw_ddb_entry->iscsi_def_time2retain = 21278c2ecf20Sopenharmony_ci cpu_to_le16(sess->time2retain); 21288c2ecf20Sopenharmony_ci 21298c2ecf20Sopenharmony_ci status = qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index, 21308c2ecf20Sopenharmony_ci fw_ddb_entry_dma, mbx_sts); 21318c2ecf20Sopenharmony_ci 21328c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) 21338c2ecf20Sopenharmony_ci rval = -EINVAL; 21348c2ecf20Sopenharmony_ciexit_set_param: 21358c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 21368c2ecf20Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma); 21378c2ecf20Sopenharmony_ciexit_set_param_no_free: 21388c2ecf20Sopenharmony_ci return rval; 21398c2ecf20Sopenharmony_ci} 21408c2ecf20Sopenharmony_ci 21418c2ecf20Sopenharmony_ciint qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index, 21428c2ecf20Sopenharmony_ci uint16_t stats_size, dma_addr_t stats_dma) 21438c2ecf20Sopenharmony_ci{ 21448c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 21458c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 21468c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 21478c2ecf20Sopenharmony_ci 21488c2ecf20Sopenharmony_ci memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT); 21498c2ecf20Sopenharmony_ci memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT); 21508c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_MANAGEMENT_DATA; 21518c2ecf20Sopenharmony_ci mbox_cmd[1] = fw_ddb_index; 21528c2ecf20Sopenharmony_ci mbox_cmd[2] = LSDW(stats_dma); 21538c2ecf20Sopenharmony_ci mbox_cmd[3] = MSDW(stats_dma); 21548c2ecf20Sopenharmony_ci mbox_cmd[4] = stats_size; 21558c2ecf20Sopenharmony_ci 21568c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, 5, 1, &mbox_cmd[0], &mbox_sts[0]); 21578c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) { 21588c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, 21598c2ecf20Sopenharmony_ci "%s: MBOX_CMD_GET_MANAGEMENT_DATA " 21608c2ecf20Sopenharmony_ci "failed w/ status %04X\n", __func__, 21618c2ecf20Sopenharmony_ci mbox_sts[0])); 21628c2ecf20Sopenharmony_ci } 21638c2ecf20Sopenharmony_ci return status; 21648c2ecf20Sopenharmony_ci} 21658c2ecf20Sopenharmony_ci 21668c2ecf20Sopenharmony_ciint qla4xxx_get_ip_state(struct scsi_qla_host *ha, uint32_t acb_idx, 21678c2ecf20Sopenharmony_ci uint32_t ip_idx, uint32_t *sts) 21688c2ecf20Sopenharmony_ci{ 21698c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 21708c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 21718c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 21728c2ecf20Sopenharmony_ci 21738c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 21748c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 21758c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_IP_ADDR_STATE; 21768c2ecf20Sopenharmony_ci mbox_cmd[1] = acb_idx; 21778c2ecf20Sopenharmony_ci mbox_cmd[2] = ip_idx; 21788c2ecf20Sopenharmony_ci 21798c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, 3, 8, &mbox_cmd[0], &mbox_sts[0]); 21808c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) { 21818c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: " 21828c2ecf20Sopenharmony_ci "MBOX_CMD_GET_IP_ADDR_STATE failed w/ " 21838c2ecf20Sopenharmony_ci "status %04X\n", __func__, mbox_sts[0])); 21848c2ecf20Sopenharmony_ci } 21858c2ecf20Sopenharmony_ci memcpy(sts, mbox_sts, sizeof(mbox_sts)); 21868c2ecf20Sopenharmony_ci return status; 21878c2ecf20Sopenharmony_ci} 21888c2ecf20Sopenharmony_ci 21898c2ecf20Sopenharmony_ciint qla4xxx_get_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma, 21908c2ecf20Sopenharmony_ci uint32_t offset, uint32_t size) 21918c2ecf20Sopenharmony_ci{ 21928c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 21938c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 21948c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 21958c2ecf20Sopenharmony_ci 21968c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 21978c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 21988c2ecf20Sopenharmony_ci 21998c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_NVRAM; 22008c2ecf20Sopenharmony_ci mbox_cmd[1] = LSDW(nvram_dma); 22018c2ecf20Sopenharmony_ci mbox_cmd[2] = MSDW(nvram_dma); 22028c2ecf20Sopenharmony_ci mbox_cmd[3] = offset; 22038c2ecf20Sopenharmony_ci mbox_cmd[4] = size; 22048c2ecf20Sopenharmony_ci 22058c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], 22068c2ecf20Sopenharmony_ci &mbox_sts[0]); 22078c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) { 22088c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed " 22098c2ecf20Sopenharmony_ci "status %04X\n", ha->host_no, __func__, 22108c2ecf20Sopenharmony_ci mbox_sts[0])); 22118c2ecf20Sopenharmony_ci } 22128c2ecf20Sopenharmony_ci return status; 22138c2ecf20Sopenharmony_ci} 22148c2ecf20Sopenharmony_ci 22158c2ecf20Sopenharmony_ciint qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma, 22168c2ecf20Sopenharmony_ci uint32_t offset, uint32_t size) 22178c2ecf20Sopenharmony_ci{ 22188c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 22198c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 22208c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 22218c2ecf20Sopenharmony_ci 22228c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 22238c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 22248c2ecf20Sopenharmony_ci 22258c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_SET_NVRAM; 22268c2ecf20Sopenharmony_ci mbox_cmd[1] = LSDW(nvram_dma); 22278c2ecf20Sopenharmony_ci mbox_cmd[2] = MSDW(nvram_dma); 22288c2ecf20Sopenharmony_ci mbox_cmd[3] = offset; 22298c2ecf20Sopenharmony_ci mbox_cmd[4] = size; 22308c2ecf20Sopenharmony_ci 22318c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], 22328c2ecf20Sopenharmony_ci &mbox_sts[0]); 22338c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) { 22348c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed " 22358c2ecf20Sopenharmony_ci "status %04X\n", ha->host_no, __func__, 22368c2ecf20Sopenharmony_ci mbox_sts[0])); 22378c2ecf20Sopenharmony_ci } 22388c2ecf20Sopenharmony_ci return status; 22398c2ecf20Sopenharmony_ci} 22408c2ecf20Sopenharmony_ci 22418c2ecf20Sopenharmony_ciint qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha, 22428c2ecf20Sopenharmony_ci uint32_t region, uint32_t field0, 22438c2ecf20Sopenharmony_ci uint32_t field1) 22448c2ecf20Sopenharmony_ci{ 22458c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 22468c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 22478c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 22488c2ecf20Sopenharmony_ci 22498c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 22508c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 22518c2ecf20Sopenharmony_ci 22528c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_RESTORE_FACTORY_DEFAULTS; 22538c2ecf20Sopenharmony_ci mbox_cmd[3] = region; 22548c2ecf20Sopenharmony_ci mbox_cmd[4] = field0; 22558c2ecf20Sopenharmony_ci mbox_cmd[5] = field1; 22568c2ecf20Sopenharmony_ci 22578c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], 22588c2ecf20Sopenharmony_ci &mbox_sts[0]); 22598c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) { 22608c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed " 22618c2ecf20Sopenharmony_ci "status %04X\n", ha->host_no, __func__, 22628c2ecf20Sopenharmony_ci mbox_sts[0])); 22638c2ecf20Sopenharmony_ci } 22648c2ecf20Sopenharmony_ci return status; 22658c2ecf20Sopenharmony_ci} 22668c2ecf20Sopenharmony_ci 22678c2ecf20Sopenharmony_ci/** 22688c2ecf20Sopenharmony_ci * qla4_8xxx_set_param - set driver version in firmware. 22698c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 22708c2ecf20Sopenharmony_ci * @param: Parameter to set i.e driver version 22718c2ecf20Sopenharmony_ci **/ 22728c2ecf20Sopenharmony_ciint qla4_8xxx_set_param(struct scsi_qla_host *ha, int param) 22738c2ecf20Sopenharmony_ci{ 22748c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 22758c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 22768c2ecf20Sopenharmony_ci uint32_t status; 22778c2ecf20Sopenharmony_ci 22788c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 22798c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 22808c2ecf20Sopenharmony_ci 22818c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_SET_PARAM; 22828c2ecf20Sopenharmony_ci if (param == SET_DRVR_VERSION) { 22838c2ecf20Sopenharmony_ci mbox_cmd[1] = SET_DRVR_VERSION; 22848c2ecf20Sopenharmony_ci strncpy((char *)&mbox_cmd[2], QLA4XXX_DRIVER_VERSION, 22858c2ecf20Sopenharmony_ci MAX_DRVR_VER_LEN - 1); 22868c2ecf20Sopenharmony_ci } else { 22878c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: invalid parameter 0x%x\n", 22888c2ecf20Sopenharmony_ci __func__, param); 22898c2ecf20Sopenharmony_ci status = QLA_ERROR; 22908c2ecf20Sopenharmony_ci goto exit_set_param; 22918c2ecf20Sopenharmony_ci } 22928c2ecf20Sopenharmony_ci 22938c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, mbox_cmd, 22948c2ecf20Sopenharmony_ci mbox_sts); 22958c2ecf20Sopenharmony_ci if (status == QLA_ERROR) 22968c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", 22978c2ecf20Sopenharmony_ci __func__, mbox_sts[0]); 22988c2ecf20Sopenharmony_ci 22998c2ecf20Sopenharmony_ciexit_set_param: 23008c2ecf20Sopenharmony_ci return status; 23018c2ecf20Sopenharmony_ci} 23028c2ecf20Sopenharmony_ci 23038c2ecf20Sopenharmony_ci/** 23048c2ecf20Sopenharmony_ci * qla4_83xx_post_idc_ack - post IDC ACK 23058c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 23068c2ecf20Sopenharmony_ci * 23078c2ecf20Sopenharmony_ci * Posts IDC ACK for IDC Request Notification AEN. 23088c2ecf20Sopenharmony_ci **/ 23098c2ecf20Sopenharmony_ciint qla4_83xx_post_idc_ack(struct scsi_qla_host *ha) 23108c2ecf20Sopenharmony_ci{ 23118c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 23128c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 23138c2ecf20Sopenharmony_ci int status; 23148c2ecf20Sopenharmony_ci 23158c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 23168c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 23178c2ecf20Sopenharmony_ci 23188c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_IDC_ACK; 23198c2ecf20Sopenharmony_ci mbox_cmd[1] = ha->idc_info.request_desc; 23208c2ecf20Sopenharmony_ci mbox_cmd[2] = ha->idc_info.info1; 23218c2ecf20Sopenharmony_ci mbox_cmd[3] = ha->idc_info.info2; 23228c2ecf20Sopenharmony_ci mbox_cmd[4] = ha->idc_info.info3; 23238c2ecf20Sopenharmony_ci 23248c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT, 23258c2ecf20Sopenharmony_ci mbox_cmd, mbox_sts); 23268c2ecf20Sopenharmony_ci if (status == QLA_ERROR) 23278c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__, 23288c2ecf20Sopenharmony_ci mbox_sts[0]); 23298c2ecf20Sopenharmony_ci else 23308c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: IDC ACK posted\n", __func__); 23318c2ecf20Sopenharmony_ci 23328c2ecf20Sopenharmony_ci return status; 23338c2ecf20Sopenharmony_ci} 23348c2ecf20Sopenharmony_ci 23358c2ecf20Sopenharmony_ciint qla4_84xx_config_acb(struct scsi_qla_host *ha, int acb_config) 23368c2ecf20Sopenharmony_ci{ 23378c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 23388c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 23398c2ecf20Sopenharmony_ci struct addr_ctrl_blk *acb = NULL; 23408c2ecf20Sopenharmony_ci uint32_t acb_len = sizeof(struct addr_ctrl_blk); 23418c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 23428c2ecf20Sopenharmony_ci dma_addr_t acb_dma; 23438c2ecf20Sopenharmony_ci 23448c2ecf20Sopenharmony_ci acb = dma_alloc_coherent(&ha->pdev->dev, 23458c2ecf20Sopenharmony_ci sizeof(struct addr_ctrl_blk), 23468c2ecf20Sopenharmony_ci &acb_dma, GFP_KERNEL); 23478c2ecf20Sopenharmony_ci if (!acb) { 23488c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Unable to alloc acb\n", __func__); 23498c2ecf20Sopenharmony_ci rval = QLA_ERROR; 23508c2ecf20Sopenharmony_ci goto exit_config_acb; 23518c2ecf20Sopenharmony_ci } 23528c2ecf20Sopenharmony_ci memset(acb, 0, acb_len); 23538c2ecf20Sopenharmony_ci 23548c2ecf20Sopenharmony_ci switch (acb_config) { 23558c2ecf20Sopenharmony_ci case ACB_CONFIG_DISABLE: 23568c2ecf20Sopenharmony_ci rval = qla4xxx_get_acb(ha, acb_dma, 0, acb_len); 23578c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 23588c2ecf20Sopenharmony_ci goto exit_free_acb; 23598c2ecf20Sopenharmony_ci 23608c2ecf20Sopenharmony_ci rval = qla4xxx_disable_acb(ha); 23618c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 23628c2ecf20Sopenharmony_ci goto exit_free_acb; 23638c2ecf20Sopenharmony_ci 23648c2ecf20Sopenharmony_ci if (!ha->saved_acb) 23658c2ecf20Sopenharmony_ci ha->saved_acb = kzalloc(acb_len, GFP_KERNEL); 23668c2ecf20Sopenharmony_ci 23678c2ecf20Sopenharmony_ci if (!ha->saved_acb) { 23688c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Unable to alloc acb\n", 23698c2ecf20Sopenharmony_ci __func__); 23708c2ecf20Sopenharmony_ci rval = QLA_ERROR; 23718c2ecf20Sopenharmony_ci goto exit_free_acb; 23728c2ecf20Sopenharmony_ci } 23738c2ecf20Sopenharmony_ci memcpy(ha->saved_acb, acb, acb_len); 23748c2ecf20Sopenharmony_ci break; 23758c2ecf20Sopenharmony_ci case ACB_CONFIG_SET: 23768c2ecf20Sopenharmony_ci 23778c2ecf20Sopenharmony_ci if (!ha->saved_acb) { 23788c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Can't set ACB, Saved ACB not available\n", 23798c2ecf20Sopenharmony_ci __func__); 23808c2ecf20Sopenharmony_ci rval = QLA_ERROR; 23818c2ecf20Sopenharmony_ci goto exit_free_acb; 23828c2ecf20Sopenharmony_ci } 23838c2ecf20Sopenharmony_ci 23848c2ecf20Sopenharmony_ci memcpy(acb, ha->saved_acb, acb_len); 23858c2ecf20Sopenharmony_ci 23868c2ecf20Sopenharmony_ci rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], acb_dma); 23878c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 23888c2ecf20Sopenharmony_ci goto exit_free_acb; 23898c2ecf20Sopenharmony_ci 23908c2ecf20Sopenharmony_ci break; 23918c2ecf20Sopenharmony_ci default: 23928c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Invalid ACB Configuration\n", 23938c2ecf20Sopenharmony_ci __func__); 23948c2ecf20Sopenharmony_ci } 23958c2ecf20Sopenharmony_ci 23968c2ecf20Sopenharmony_ciexit_free_acb: 23978c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk), acb, 23988c2ecf20Sopenharmony_ci acb_dma); 23998c2ecf20Sopenharmony_ciexit_config_acb: 24008c2ecf20Sopenharmony_ci if ((acb_config == ACB_CONFIG_SET) && ha->saved_acb) { 24018c2ecf20Sopenharmony_ci kfree(ha->saved_acb); 24028c2ecf20Sopenharmony_ci ha->saved_acb = NULL; 24038c2ecf20Sopenharmony_ci } 24048c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 24058c2ecf20Sopenharmony_ci "%s %s\n", __func__, 24068c2ecf20Sopenharmony_ci rval == QLA_SUCCESS ? "SUCCEEDED" : "FAILED")); 24078c2ecf20Sopenharmony_ci return rval; 24088c2ecf20Sopenharmony_ci} 24098c2ecf20Sopenharmony_ci 24108c2ecf20Sopenharmony_ciint qla4_83xx_get_port_config(struct scsi_qla_host *ha, uint32_t *config) 24118c2ecf20Sopenharmony_ci{ 24128c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 24138c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 24148c2ecf20Sopenharmony_ci int status; 24158c2ecf20Sopenharmony_ci 24168c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 24178c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 24188c2ecf20Sopenharmony_ci 24198c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_PORT_CONFIG; 24208c2ecf20Sopenharmony_ci 24218c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT, 24228c2ecf20Sopenharmony_ci mbox_cmd, mbox_sts); 24238c2ecf20Sopenharmony_ci if (status == QLA_SUCCESS) 24248c2ecf20Sopenharmony_ci *config = mbox_sts[1]; 24258c2ecf20Sopenharmony_ci else 24268c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__, 24278c2ecf20Sopenharmony_ci mbox_sts[0]); 24288c2ecf20Sopenharmony_ci 24298c2ecf20Sopenharmony_ci return status; 24308c2ecf20Sopenharmony_ci} 24318c2ecf20Sopenharmony_ci 24328c2ecf20Sopenharmony_ciint qla4_83xx_set_port_config(struct scsi_qla_host *ha, uint32_t *config) 24338c2ecf20Sopenharmony_ci{ 24348c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 24358c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 24368c2ecf20Sopenharmony_ci int status; 24378c2ecf20Sopenharmony_ci 24388c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 24398c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 24408c2ecf20Sopenharmony_ci 24418c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_SET_PORT_CONFIG; 24428c2ecf20Sopenharmony_ci mbox_cmd[1] = *config; 24438c2ecf20Sopenharmony_ci 24448c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT, 24458c2ecf20Sopenharmony_ci mbox_cmd, mbox_sts); 24468c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) 24478c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__, 24488c2ecf20Sopenharmony_ci mbox_sts[0]); 24498c2ecf20Sopenharmony_ci 24508c2ecf20Sopenharmony_ci return status; 24518c2ecf20Sopenharmony_ci} 2452