18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * QLogic Fibre Channel HBA Driver 48c2ecf20Sopenharmony_ci * Copyright (c) 2003-2014 QLogic Corporation 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci#include "qla_def.h" 78c2ecf20Sopenharmony_ci#include <linux/delay.h> 88c2ecf20Sopenharmony_ci#include <linux/ktime.h> 98c2ecf20Sopenharmony_ci#include <linux/pci.h> 108c2ecf20Sopenharmony_ci#include <linux/ratelimit.h> 118c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 128c2ecf20Sopenharmony_ci#include <scsi/scsi_tcq.h> 138c2ecf20Sopenharmony_ci#include <linux/utsname.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/* QLAFX00 specific Mailbox implementation functions */ 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/* 198c2ecf20Sopenharmony_ci * qlafx00_mailbox_command 208c2ecf20Sopenharmony_ci * Issue mailbox command and waits for completion. 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * Input: 238c2ecf20Sopenharmony_ci * ha = adapter block pointer. 248c2ecf20Sopenharmony_ci * mcp = driver internal mbx struct pointer. 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * Output: 278c2ecf20Sopenharmony_ci * mb[MAX_MAILBOX_REGISTER_COUNT] = returned mailbox data. 288c2ecf20Sopenharmony_ci * 298c2ecf20Sopenharmony_ci * Returns: 308c2ecf20Sopenharmony_ci * 0 : QLA_SUCCESS = cmd performed success 318c2ecf20Sopenharmony_ci * 1 : QLA_FUNCTION_FAILED (error encountered) 328c2ecf20Sopenharmony_ci * 6 : QLA_FUNCTION_TIMEOUT (timeout condition encountered) 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * Context: 358c2ecf20Sopenharmony_ci * Kernel context. 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_cistatic int 388c2ecf20Sopenharmony_ciqlafx00_mailbox_command(scsi_qla_host_t *vha, struct mbx_cmd_32 *mcp) 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci int rval; 428c2ecf20Sopenharmony_ci unsigned long flags = 0; 438c2ecf20Sopenharmony_ci device_reg_t *reg; 448c2ecf20Sopenharmony_ci uint8_t abort_active; 458c2ecf20Sopenharmony_ci uint8_t io_lock_on; 468c2ecf20Sopenharmony_ci uint16_t command = 0; 478c2ecf20Sopenharmony_ci uint32_t *iptr; 488c2ecf20Sopenharmony_ci __le32 __iomem *optr; 498c2ecf20Sopenharmony_ci uint32_t cnt; 508c2ecf20Sopenharmony_ci uint32_t mboxes; 518c2ecf20Sopenharmony_ci unsigned long wait_time; 528c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 538c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (ha->pdev->error_state == pci_channel_io_perm_failure) { 568c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x115c, 578c2ecf20Sopenharmony_ci "PCI channel failed permanently, exiting.\n"); 588c2ecf20Sopenharmony_ci return QLA_FUNCTION_TIMEOUT; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci if (vha->device_flags & DFLG_DEV_FAILED) { 628c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x115f, 638c2ecf20Sopenharmony_ci "Device in failed state, exiting.\n"); 648c2ecf20Sopenharmony_ci return QLA_FUNCTION_TIMEOUT; 658c2ecf20Sopenharmony_ci } 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci reg = ha->iobase; 688c2ecf20Sopenharmony_ci io_lock_on = base_vha->flags.init_done; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci rval = QLA_SUCCESS; 718c2ecf20Sopenharmony_ci abort_active = test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci if (ha->flags.pci_channel_io_perm_failure) { 748c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1175, 758c2ecf20Sopenharmony_ci "Perm failure on EEH timeout MBX, exiting.\n"); 768c2ecf20Sopenharmony_ci return QLA_FUNCTION_TIMEOUT; 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci if (ha->flags.isp82xx_fw_hung) { 808c2ecf20Sopenharmony_ci /* Setting Link-Down error */ 818c2ecf20Sopenharmony_ci mcp->mb[0] = MBS_LINK_DOWN_ERROR; 828c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1176, 838c2ecf20Sopenharmony_ci "FW hung = %d.\n", ha->flags.isp82xx_fw_hung); 848c2ecf20Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 858c2ecf20Sopenharmony_ci goto premature_exit; 868c2ecf20Sopenharmony_ci } 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci /* 898c2ecf20Sopenharmony_ci * Wait for active mailbox commands to finish by waiting at most tov 908c2ecf20Sopenharmony_ci * seconds. This is to serialize actual issuing of mailbox cmds during 918c2ecf20Sopenharmony_ci * non ISP abort time. 928c2ecf20Sopenharmony_ci */ 938c2ecf20Sopenharmony_ci if (!wait_for_completion_timeout(&ha->mbx_cmd_comp, mcp->tov * HZ)) { 948c2ecf20Sopenharmony_ci /* Timeout occurred. Return error. */ 958c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1177, 968c2ecf20Sopenharmony_ci "Cmd access timeout, cmd=0x%x, Exiting.\n", 978c2ecf20Sopenharmony_ci mcp->mb[0]); 988c2ecf20Sopenharmony_ci return QLA_FUNCTION_TIMEOUT; 998c2ecf20Sopenharmony_ci } 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci ha->flags.mbox_busy = 1; 1028c2ecf20Sopenharmony_ci /* Save mailbox command for debug */ 1038c2ecf20Sopenharmony_ci ha->mcp32 = mcp; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1178, 1068c2ecf20Sopenharmony_ci "Prepare to issue mbox cmd=0x%x.\n", mcp->mb[0]); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci /* Load mailbox registers. */ 1118c2ecf20Sopenharmony_ci optr = ®->ispfx00.mailbox0; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci iptr = mcp->mb; 1148c2ecf20Sopenharmony_ci command = mcp->mb[0]; 1158c2ecf20Sopenharmony_ci mboxes = mcp->out_mb; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci for (cnt = 0; cnt < ha->mbx_count; cnt++) { 1188c2ecf20Sopenharmony_ci if (mboxes & BIT_0) 1198c2ecf20Sopenharmony_ci wrt_reg_dword(optr, *iptr); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci mboxes >>= 1; 1228c2ecf20Sopenharmony_ci optr++; 1238c2ecf20Sopenharmony_ci iptr++; 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* Issue set host interrupt command to send cmd out. */ 1278c2ecf20Sopenharmony_ci ha->flags.mbox_int = 0; 1288c2ecf20Sopenharmony_ci clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1172, 1318c2ecf20Sopenharmony_ci (uint8_t *)mcp->mb, 16); 1328c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1173, 1338c2ecf20Sopenharmony_ci ((uint8_t *)mcp->mb + 0x10), 16); 1348c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1174, 1358c2ecf20Sopenharmony_ci ((uint8_t *)mcp->mb + 0x20), 8); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci /* Unlock mbx registers and wait for interrupt */ 1388c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1179, 1398c2ecf20Sopenharmony_ci "Going to unlock irq & waiting for interrupts. " 1408c2ecf20Sopenharmony_ci "jiffies=%lx.\n", jiffies); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci /* Wait for mbx cmd completion until timeout */ 1438c2ecf20Sopenharmony_ci if ((!abort_active && io_lock_on) || IS_NOPOLLING_TYPE(ha)) { 1448c2ecf20Sopenharmony_ci set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci QLAFX00_SET_HST_INTR(ha, ha->mbx_intr_code); 1478c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci WARN_ON_ONCE(wait_for_completion_timeout(&ha->mbx_intr_comp, 1508c2ecf20Sopenharmony_ci mcp->tov * HZ) != 0); 1518c2ecf20Sopenharmony_ci } else { 1528c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x112c, 1538c2ecf20Sopenharmony_ci "Cmd=%x Polling Mode.\n", command); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci QLAFX00_SET_HST_INTR(ha, ha->mbx_intr_code); 1568c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci wait_time = jiffies + mcp->tov * HZ; /* wait at most tov secs */ 1598c2ecf20Sopenharmony_ci while (!ha->flags.mbox_int) { 1608c2ecf20Sopenharmony_ci if (time_after(jiffies, wait_time)) 1618c2ecf20Sopenharmony_ci break; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* Check for pending interrupts. */ 1648c2ecf20Sopenharmony_ci qla2x00_poll(ha->rsp_q_map[0]); 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci if (!ha->flags.mbox_int && 1678c2ecf20Sopenharmony_ci !(IS_QLA2200(ha) && 1688c2ecf20Sopenharmony_ci command == MBC_LOAD_RISC_RAM_EXTENDED)) 1698c2ecf20Sopenharmony_ci usleep_range(10000, 11000); 1708c2ecf20Sopenharmony_ci } /* while */ 1718c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x112d, 1728c2ecf20Sopenharmony_ci "Waited %d sec.\n", 1738c2ecf20Sopenharmony_ci (uint)((jiffies - (wait_time - (mcp->tov * HZ)))/HZ)); 1748c2ecf20Sopenharmony_ci } 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci /* Check whether we timed out */ 1778c2ecf20Sopenharmony_ci if (ha->flags.mbox_int) { 1788c2ecf20Sopenharmony_ci uint32_t *iptr2; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x112e, 1818c2ecf20Sopenharmony_ci "Cmd=%x completed.\n", command); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci /* Got interrupt. Clear the flag. */ 1848c2ecf20Sopenharmony_ci ha->flags.mbox_int = 0; 1858c2ecf20Sopenharmony_ci clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci if (ha->mailbox_out32[0] != MBS_COMMAND_COMPLETE) 1888c2ecf20Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci /* Load return mailbox registers. */ 1918c2ecf20Sopenharmony_ci iptr2 = mcp->mb; 1928c2ecf20Sopenharmony_ci iptr = (uint32_t *)&ha->mailbox_out32[0]; 1938c2ecf20Sopenharmony_ci mboxes = mcp->in_mb; 1948c2ecf20Sopenharmony_ci for (cnt = 0; cnt < ha->mbx_count; cnt++) { 1958c2ecf20Sopenharmony_ci if (mboxes & BIT_0) 1968c2ecf20Sopenharmony_ci *iptr2 = *iptr; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci mboxes >>= 1; 1998c2ecf20Sopenharmony_ci iptr2++; 2008c2ecf20Sopenharmony_ci iptr++; 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci } else { 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci rval = QLA_FUNCTION_TIMEOUT; 2058c2ecf20Sopenharmony_ci } 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci ha->flags.mbox_busy = 0; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci /* Clean up */ 2108c2ecf20Sopenharmony_ci ha->mcp32 = NULL; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci if ((abort_active || !io_lock_on) && !IS_NOPOLLING_TYPE(ha)) { 2138c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x113a, 2148c2ecf20Sopenharmony_ci "checking for additional resp interrupt.\n"); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci /* polling mode for non isp_abort commands. */ 2178c2ecf20Sopenharmony_ci qla2x00_poll(ha->rsp_q_map[0]); 2188c2ecf20Sopenharmony_ci } 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci if (rval == QLA_FUNCTION_TIMEOUT && 2218c2ecf20Sopenharmony_ci mcp->mb[0] != MBC_GEN_SYSTEM_ERROR) { 2228c2ecf20Sopenharmony_ci if (!io_lock_on || (mcp->flags & IOCTL_CMD) || 2238c2ecf20Sopenharmony_ci ha->flags.eeh_busy) { 2248c2ecf20Sopenharmony_ci /* not in dpc. schedule it for dpc to take over. */ 2258c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x115d, 2268c2ecf20Sopenharmony_ci "Timeout, schedule isp_abort_needed.\n"); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) && 2298c2ecf20Sopenharmony_ci !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && 2308c2ecf20Sopenharmony_ci !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci ql_log(ql_log_info, base_vha, 0x115e, 2338c2ecf20Sopenharmony_ci "Mailbox cmd timeout occurred, cmd=0x%x, " 2348c2ecf20Sopenharmony_ci "mb[0]=0x%x, eeh_busy=0x%x. Scheduling ISP " 2358c2ecf20Sopenharmony_ci "abort.\n", command, mcp->mb[0], 2368c2ecf20Sopenharmony_ci ha->flags.eeh_busy); 2378c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 2388c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci } else if (!abort_active) { 2418c2ecf20Sopenharmony_ci /* call abort directly since we are in the DPC thread */ 2428c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1160, 2438c2ecf20Sopenharmony_ci "Timeout, calling abort_isp.\n"); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) && 2468c2ecf20Sopenharmony_ci !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && 2478c2ecf20Sopenharmony_ci !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci ql_log(ql_log_info, base_vha, 0x1161, 2508c2ecf20Sopenharmony_ci "Mailbox cmd timeout occurred, cmd=0x%x, " 2518c2ecf20Sopenharmony_ci "mb[0]=0x%x. Scheduling ISP abort ", 2528c2ecf20Sopenharmony_ci command, mcp->mb[0]); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags); 2558c2ecf20Sopenharmony_ci clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 2568c2ecf20Sopenharmony_ci if (ha->isp_ops->abort_isp(vha)) { 2578c2ecf20Sopenharmony_ci /* Failed. retry later. */ 2588c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, 2598c2ecf20Sopenharmony_ci &vha->dpc_flags); 2608c2ecf20Sopenharmony_ci } 2618c2ecf20Sopenharmony_ci clear_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags); 2628c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1162, 2638c2ecf20Sopenharmony_ci "Finished abort_isp.\n"); 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_cipremature_exit: 2698c2ecf20Sopenharmony_ci /* Allow next mbx cmd to come in. */ 2708c2ecf20Sopenharmony_ci complete(&ha->mbx_cmd_comp); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci if (rval) { 2738c2ecf20Sopenharmony_ci ql_log(ql_log_warn, base_vha, 0x1163, 2748c2ecf20Sopenharmony_ci "**** Failed=%x mbx[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x, cmd=%x ****.\n", 2758c2ecf20Sopenharmony_ci rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], 2768c2ecf20Sopenharmony_ci command); 2778c2ecf20Sopenharmony_ci } else { 2788c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx, base_vha, 0x1164, "Done %s.\n", __func__); 2798c2ecf20Sopenharmony_ci } 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci return rval; 2828c2ecf20Sopenharmony_ci} 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci/* 2858c2ecf20Sopenharmony_ci * qlafx00_driver_shutdown 2868c2ecf20Sopenharmony_ci * Indicate a driver shutdown to firmware. 2878c2ecf20Sopenharmony_ci * 2888c2ecf20Sopenharmony_ci * Input: 2898c2ecf20Sopenharmony_ci * ha = adapter block pointer. 2908c2ecf20Sopenharmony_ci * 2918c2ecf20Sopenharmony_ci * Returns: 2928c2ecf20Sopenharmony_ci * local function return status code. 2938c2ecf20Sopenharmony_ci * 2948c2ecf20Sopenharmony_ci * Context: 2958c2ecf20Sopenharmony_ci * Kernel context. 2968c2ecf20Sopenharmony_ci */ 2978c2ecf20Sopenharmony_ciint 2988c2ecf20Sopenharmony_ciqlafx00_driver_shutdown(scsi_qla_host_t *vha, int tmo) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci int rval; 3018c2ecf20Sopenharmony_ci struct mbx_cmd_32 mc; 3028c2ecf20Sopenharmony_ci struct mbx_cmd_32 *mcp = &mc; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1166, 3058c2ecf20Sopenharmony_ci "Entered %s.\n", __func__); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci mcp->mb[0] = MBC_MR_DRV_SHUTDOWN; 3088c2ecf20Sopenharmony_ci mcp->out_mb = MBX_0; 3098c2ecf20Sopenharmony_ci mcp->in_mb = MBX_0; 3108c2ecf20Sopenharmony_ci if (tmo) 3118c2ecf20Sopenharmony_ci mcp->tov = tmo; 3128c2ecf20Sopenharmony_ci else 3138c2ecf20Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 3148c2ecf20Sopenharmony_ci mcp->flags = 0; 3158c2ecf20Sopenharmony_ci rval = qlafx00_mailbox_command(vha, mcp); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 3188c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1167, 3198c2ecf20Sopenharmony_ci "Failed=%x.\n", rval); 3208c2ecf20Sopenharmony_ci } else { 3218c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1168, 3228c2ecf20Sopenharmony_ci "Done %s.\n", __func__); 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci return rval; 3268c2ecf20Sopenharmony_ci} 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci/* 3298c2ecf20Sopenharmony_ci * qlafx00_get_firmware_state 3308c2ecf20Sopenharmony_ci * Get adapter firmware state. 3318c2ecf20Sopenharmony_ci * 3328c2ecf20Sopenharmony_ci * Input: 3338c2ecf20Sopenharmony_ci * ha = adapter block pointer. 3348c2ecf20Sopenharmony_ci * TARGET_QUEUE_LOCK must be released. 3358c2ecf20Sopenharmony_ci * ADAPTER_STATE_LOCK must be released. 3368c2ecf20Sopenharmony_ci * 3378c2ecf20Sopenharmony_ci * Returns: 3388c2ecf20Sopenharmony_ci * qla7xxx local function return status code. 3398c2ecf20Sopenharmony_ci * 3408c2ecf20Sopenharmony_ci * Context: 3418c2ecf20Sopenharmony_ci * Kernel context. 3428c2ecf20Sopenharmony_ci */ 3438c2ecf20Sopenharmony_cistatic int 3448c2ecf20Sopenharmony_ciqlafx00_get_firmware_state(scsi_qla_host_t *vha, uint32_t *states) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci int rval; 3478c2ecf20Sopenharmony_ci struct mbx_cmd_32 mc; 3488c2ecf20Sopenharmony_ci struct mbx_cmd_32 *mcp = &mc; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1169, 3518c2ecf20Sopenharmony_ci "Entered %s.\n", __func__); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci mcp->mb[0] = MBC_GET_FIRMWARE_STATE; 3548c2ecf20Sopenharmony_ci mcp->out_mb = MBX_0; 3558c2ecf20Sopenharmony_ci mcp->in_mb = MBX_1|MBX_0; 3568c2ecf20Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 3578c2ecf20Sopenharmony_ci mcp->flags = 0; 3588c2ecf20Sopenharmony_ci rval = qlafx00_mailbox_command(vha, mcp); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci /* Return firmware states. */ 3618c2ecf20Sopenharmony_ci states[0] = mcp->mb[1]; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 3648c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x116a, 3658c2ecf20Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 3668c2ecf20Sopenharmony_ci } else { 3678c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x116b, 3688c2ecf20Sopenharmony_ci "Done %s.\n", __func__); 3698c2ecf20Sopenharmony_ci } 3708c2ecf20Sopenharmony_ci return rval; 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci/* 3748c2ecf20Sopenharmony_ci * qlafx00_init_firmware 3758c2ecf20Sopenharmony_ci * Initialize adapter firmware. 3768c2ecf20Sopenharmony_ci * 3778c2ecf20Sopenharmony_ci * Input: 3788c2ecf20Sopenharmony_ci * ha = adapter block pointer. 3798c2ecf20Sopenharmony_ci * dptr = Initialization control block pointer. 3808c2ecf20Sopenharmony_ci * size = size of initialization control block. 3818c2ecf20Sopenharmony_ci * TARGET_QUEUE_LOCK must be released. 3828c2ecf20Sopenharmony_ci * ADAPTER_STATE_LOCK must be released. 3838c2ecf20Sopenharmony_ci * 3848c2ecf20Sopenharmony_ci * Returns: 3858c2ecf20Sopenharmony_ci * qlafx00 local function return status code. 3868c2ecf20Sopenharmony_ci * 3878c2ecf20Sopenharmony_ci * Context: 3888c2ecf20Sopenharmony_ci * Kernel context. 3898c2ecf20Sopenharmony_ci */ 3908c2ecf20Sopenharmony_ciint 3918c2ecf20Sopenharmony_ciqlafx00_init_firmware(scsi_qla_host_t *vha, uint16_t size) 3928c2ecf20Sopenharmony_ci{ 3938c2ecf20Sopenharmony_ci int rval; 3948c2ecf20Sopenharmony_ci struct mbx_cmd_32 mc; 3958c2ecf20Sopenharmony_ci struct mbx_cmd_32 *mcp = &mc; 3968c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x116c, 3998c2ecf20Sopenharmony_ci "Entered %s.\n", __func__); 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci mcp->mb[0] = MBC_INITIALIZE_FIRMWARE; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci mcp->mb[1] = 0; 4048c2ecf20Sopenharmony_ci mcp->mb[2] = MSD(ha->init_cb_dma); 4058c2ecf20Sopenharmony_ci mcp->mb[3] = LSD(ha->init_cb_dma); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; 4088c2ecf20Sopenharmony_ci mcp->in_mb = MBX_0; 4098c2ecf20Sopenharmony_ci mcp->buf_size = size; 4108c2ecf20Sopenharmony_ci mcp->flags = MBX_DMA_OUT; 4118c2ecf20Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 4128c2ecf20Sopenharmony_ci rval = qlafx00_mailbox_command(vha, mcp); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 4158c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x116d, 4168c2ecf20Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 4178c2ecf20Sopenharmony_ci } else { 4188c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x116e, 4198c2ecf20Sopenharmony_ci "Done %s.\n", __func__); 4208c2ecf20Sopenharmony_ci } 4218c2ecf20Sopenharmony_ci return rval; 4228c2ecf20Sopenharmony_ci} 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci/* 4258c2ecf20Sopenharmony_ci * qlafx00_mbx_reg_test 4268c2ecf20Sopenharmony_ci */ 4278c2ecf20Sopenharmony_cistatic int 4288c2ecf20Sopenharmony_ciqlafx00_mbx_reg_test(scsi_qla_host_t *vha) 4298c2ecf20Sopenharmony_ci{ 4308c2ecf20Sopenharmony_ci int rval; 4318c2ecf20Sopenharmony_ci struct mbx_cmd_32 mc; 4328c2ecf20Sopenharmony_ci struct mbx_cmd_32 *mcp = &mc; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x116f, 4358c2ecf20Sopenharmony_ci "Entered %s.\n", __func__); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST; 4398c2ecf20Sopenharmony_ci mcp->mb[1] = 0xAAAA; 4408c2ecf20Sopenharmony_ci mcp->mb[2] = 0x5555; 4418c2ecf20Sopenharmony_ci mcp->mb[3] = 0xAA55; 4428c2ecf20Sopenharmony_ci mcp->mb[4] = 0x55AA; 4438c2ecf20Sopenharmony_ci mcp->mb[5] = 0xA5A5; 4448c2ecf20Sopenharmony_ci mcp->mb[6] = 0x5A5A; 4458c2ecf20Sopenharmony_ci mcp->mb[7] = 0x2525; 4468c2ecf20Sopenharmony_ci mcp->mb[8] = 0xBBBB; 4478c2ecf20Sopenharmony_ci mcp->mb[9] = 0x6666; 4488c2ecf20Sopenharmony_ci mcp->mb[10] = 0xBB66; 4498c2ecf20Sopenharmony_ci mcp->mb[11] = 0x66BB; 4508c2ecf20Sopenharmony_ci mcp->mb[12] = 0xB6B6; 4518c2ecf20Sopenharmony_ci mcp->mb[13] = 0x6B6B; 4528c2ecf20Sopenharmony_ci mcp->mb[14] = 0x3636; 4538c2ecf20Sopenharmony_ci mcp->mb[15] = 0xCCCC; 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci mcp->out_mb = MBX_15|MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8| 4578c2ecf20Sopenharmony_ci MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 4588c2ecf20Sopenharmony_ci mcp->in_mb = MBX_15|MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8| 4598c2ecf20Sopenharmony_ci MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; 4608c2ecf20Sopenharmony_ci mcp->buf_size = 0; 4618c2ecf20Sopenharmony_ci mcp->flags = MBX_DMA_OUT; 4628c2ecf20Sopenharmony_ci mcp->tov = MBX_TOV_SECONDS; 4638c2ecf20Sopenharmony_ci rval = qlafx00_mailbox_command(vha, mcp); 4648c2ecf20Sopenharmony_ci if (rval == QLA_SUCCESS) { 4658c2ecf20Sopenharmony_ci if (mcp->mb[17] != 0xAAAA || mcp->mb[18] != 0x5555 || 4668c2ecf20Sopenharmony_ci mcp->mb[19] != 0xAA55 || mcp->mb[20] != 0x55AA) 4678c2ecf20Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 4688c2ecf20Sopenharmony_ci if (mcp->mb[21] != 0xA5A5 || mcp->mb[22] != 0x5A5A || 4698c2ecf20Sopenharmony_ci mcp->mb[23] != 0x2525 || mcp->mb[24] != 0xBBBB) 4708c2ecf20Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 4718c2ecf20Sopenharmony_ci if (mcp->mb[25] != 0x6666 || mcp->mb[26] != 0xBB66 || 4728c2ecf20Sopenharmony_ci mcp->mb[27] != 0x66BB || mcp->mb[28] != 0xB6B6) 4738c2ecf20Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 4748c2ecf20Sopenharmony_ci if (mcp->mb[29] != 0x6B6B || mcp->mb[30] != 0x3636 || 4758c2ecf20Sopenharmony_ci mcp->mb[31] != 0xCCCC) 4768c2ecf20Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 4808c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x1170, 4818c2ecf20Sopenharmony_ci "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); 4828c2ecf20Sopenharmony_ci } else { 4838c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1171, 4848c2ecf20Sopenharmony_ci "Done %s.\n", __func__); 4858c2ecf20Sopenharmony_ci } 4868c2ecf20Sopenharmony_ci return rval; 4878c2ecf20Sopenharmony_ci} 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci/** 4908c2ecf20Sopenharmony_ci * qlafx00_pci_config() - Setup ISPFx00 PCI configuration registers. 4918c2ecf20Sopenharmony_ci * @vha: HA context 4928c2ecf20Sopenharmony_ci * 4938c2ecf20Sopenharmony_ci * Returns 0 on success. 4948c2ecf20Sopenharmony_ci */ 4958c2ecf20Sopenharmony_ciint 4968c2ecf20Sopenharmony_ciqlafx00_pci_config(scsi_qla_host_t *vha) 4978c2ecf20Sopenharmony_ci{ 4988c2ecf20Sopenharmony_ci uint16_t w; 4998c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci pci_set_master(ha->pdev); 5028c2ecf20Sopenharmony_ci pci_try_set_mwi(ha->pdev); 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci pci_read_config_word(ha->pdev, PCI_COMMAND, &w); 5058c2ecf20Sopenharmony_ci w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); 5068c2ecf20Sopenharmony_ci w &= ~PCI_COMMAND_INTX_DISABLE; 5078c2ecf20Sopenharmony_ci pci_write_config_word(ha->pdev, PCI_COMMAND, w); 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci /* PCIe -- adjust Maximum Read Request Size (2048). */ 5108c2ecf20Sopenharmony_ci if (pci_is_pcie(ha->pdev)) 5118c2ecf20Sopenharmony_ci pcie_set_readrq(ha->pdev, 2048); 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci ha->chip_revision = ha->pdev->revision; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci return QLA_SUCCESS; 5168c2ecf20Sopenharmony_ci} 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci/** 5198c2ecf20Sopenharmony_ci * qlafx00_warm_reset() - Perform warm reset of iSA(CPUs being reset on SOC). 5208c2ecf20Sopenharmony_ci * @vha: HA context 5218c2ecf20Sopenharmony_ci * 5228c2ecf20Sopenharmony_ci */ 5238c2ecf20Sopenharmony_cistatic inline void 5248c2ecf20Sopenharmony_ciqlafx00_soc_cpu_reset(scsi_qla_host_t *vha) 5258c2ecf20Sopenharmony_ci{ 5268c2ecf20Sopenharmony_ci unsigned long flags = 0; 5278c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 5288c2ecf20Sopenharmony_ci int i, core; 5298c2ecf20Sopenharmony_ci uint32_t cnt; 5308c2ecf20Sopenharmony_ci uint32_t reg_val; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 0x80004, 0); 5358c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 0x82004, 0); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci /* stop the XOR DMA engines */ 5388c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 0x60920, 0x02); 5398c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 0x60924, 0x02); 5408c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 0xf0920, 0x02); 5418c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 0xf0924, 0x02); 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci /* stop the IDMA engines */ 5448c2ecf20Sopenharmony_ci reg_val = QLAFX00_GET_HBA_SOC_REG(ha, 0x60840); 5458c2ecf20Sopenharmony_ci reg_val &= ~(1<<12); 5468c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 0x60840, reg_val); 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci reg_val = QLAFX00_GET_HBA_SOC_REG(ha, 0x60844); 5498c2ecf20Sopenharmony_ci reg_val &= ~(1<<12); 5508c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 0x60844, reg_val); 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci reg_val = QLAFX00_GET_HBA_SOC_REG(ha, 0x60848); 5538c2ecf20Sopenharmony_ci reg_val &= ~(1<<12); 5548c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 0x60848, reg_val); 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci reg_val = QLAFX00_GET_HBA_SOC_REG(ha, 0x6084C); 5578c2ecf20Sopenharmony_ci reg_val &= ~(1<<12); 5588c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 0x6084C, reg_val); 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci for (i = 0; i < 100000; i++) { 5618c2ecf20Sopenharmony_ci if ((QLAFX00_GET_HBA_SOC_REG(ha, 0xd0000) & 0x10000000) == 0 && 5628c2ecf20Sopenharmony_ci (QLAFX00_GET_HBA_SOC_REG(ha, 0x10600) & 0x1) == 0) 5638c2ecf20Sopenharmony_ci break; 5648c2ecf20Sopenharmony_ci udelay(100); 5658c2ecf20Sopenharmony_ci } 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci /* Set all 4 cores in reset */ 5688c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 5698c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 5708c2ecf20Sopenharmony_ci (SOC_SW_RST_CONTROL_REG_CORE0 + 8*i), (0xF01)); 5718c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 5728c2ecf20Sopenharmony_ci (SOC_SW_RST_CONTROL_REG_CORE0 + 4 + 8*i), (0x01010101)); 5738c2ecf20Sopenharmony_ci } 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci /* Reset all units in Fabric */ 5768c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, SOC_FABRIC_RST_CONTROL_REG, (0x011f0101)); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci /* */ 5798c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 0x10610, 1); 5808c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 0x10600, 0); 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci /* Set all 4 core Memory Power Down Registers */ 5838c2ecf20Sopenharmony_ci for (i = 0; i < 5; i++) { 5848c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 5858c2ecf20Sopenharmony_ci (SOC_PWR_MANAGEMENT_PWR_DOWN_REG + 4*i), (0x0)); 5868c2ecf20Sopenharmony_ci } 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci /* Reset all interrupt control registers */ 5898c2ecf20Sopenharmony_ci for (i = 0; i < 115; i++) { 5908c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 5918c2ecf20Sopenharmony_ci (SOC_INTERRUPT_SOURCE_I_CONTROL_REG + 4*i), (0x0)); 5928c2ecf20Sopenharmony_ci } 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci /* Reset Timers control registers. per core */ 5958c2ecf20Sopenharmony_ci for (core = 0; core < 4; core++) 5968c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 5978c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 5988c2ecf20Sopenharmony_ci (SOC_CORE_TIMER_REG + 0x100*core + 4*i), (0x0)); 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci /* Reset per core IRQ ack register */ 6018c2ecf20Sopenharmony_ci for (core = 0; core < 4; core++) 6028c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, 6038c2ecf20Sopenharmony_ci (SOC_IRQ_ACK_REG + 0x100*core), (0x3FF)); 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci /* Set Fabric control and config to defaults */ 6068c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, SOC_FABRIC_CONTROL_REG, (0x2)); 6078c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, SOC_FABRIC_CONFIG_REG, (0x3)); 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci /* Kick in Fabric units */ 6108c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, SOC_FABRIC_RST_CONTROL_REG, (0x0)); 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci /* Kick in Core0 to start boot process */ 6138c2ecf20Sopenharmony_ci QLAFX00_SET_HBA_SOC_REG(ha, SOC_SW_RST_CONTROL_REG_CORE0, (0xF00)); 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci /* Wait 10secs for soft-reset to complete. */ 6188c2ecf20Sopenharmony_ci for (cnt = 10; cnt; cnt--) { 6198c2ecf20Sopenharmony_ci msleep(1000); 6208c2ecf20Sopenharmony_ci barrier(); 6218c2ecf20Sopenharmony_ci } 6228c2ecf20Sopenharmony_ci} 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci/** 6258c2ecf20Sopenharmony_ci * qlafx00_soft_reset() - Soft Reset ISPFx00. 6268c2ecf20Sopenharmony_ci * @vha: HA context 6278c2ecf20Sopenharmony_ci * 6288c2ecf20Sopenharmony_ci * Returns 0 on success. 6298c2ecf20Sopenharmony_ci */ 6308c2ecf20Sopenharmony_ciint 6318c2ecf20Sopenharmony_ciqlafx00_soft_reset(scsi_qla_host_t *vha) 6328c2ecf20Sopenharmony_ci{ 6338c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 6348c2ecf20Sopenharmony_ci int rval = QLA_FUNCTION_FAILED; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci if (unlikely(pci_channel_offline(ha->pdev) && 6378c2ecf20Sopenharmony_ci ha->flags.pci_channel_io_perm_failure)) 6388c2ecf20Sopenharmony_ci return rval; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci ha->isp_ops->disable_intrs(ha); 6418c2ecf20Sopenharmony_ci qlafx00_soc_cpu_reset(vha); 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci return QLA_SUCCESS; 6448c2ecf20Sopenharmony_ci} 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci/** 6478c2ecf20Sopenharmony_ci * qlafx00_chip_diag() - Test ISPFx00 for proper operation. 6488c2ecf20Sopenharmony_ci * @vha: HA context 6498c2ecf20Sopenharmony_ci * 6508c2ecf20Sopenharmony_ci * Returns 0 on success. 6518c2ecf20Sopenharmony_ci */ 6528c2ecf20Sopenharmony_ciint 6538c2ecf20Sopenharmony_ciqlafx00_chip_diag(scsi_qla_host_t *vha) 6548c2ecf20Sopenharmony_ci{ 6558c2ecf20Sopenharmony_ci int rval = 0; 6568c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 6578c2ecf20Sopenharmony_ci struct req_que *req = ha->req_q_map[0]; 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci ha->fw_transfer_size = REQUEST_ENTRY_SIZE * req->length; 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci rval = qlafx00_mbx_reg_test(vha); 6628c2ecf20Sopenharmony_ci if (rval) { 6638c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1165, 6648c2ecf20Sopenharmony_ci "Failed mailbox send register test\n"); 6658c2ecf20Sopenharmony_ci } else { 6668c2ecf20Sopenharmony_ci /* Flag a successful rval */ 6678c2ecf20Sopenharmony_ci rval = QLA_SUCCESS; 6688c2ecf20Sopenharmony_ci } 6698c2ecf20Sopenharmony_ci return rval; 6708c2ecf20Sopenharmony_ci} 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_civoid 6738c2ecf20Sopenharmony_ciqlafx00_config_rings(struct scsi_qla_host *vha) 6748c2ecf20Sopenharmony_ci{ 6758c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 6768c2ecf20Sopenharmony_ci struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00; 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci wrt_reg_dword(®->req_q_in, 0); 6798c2ecf20Sopenharmony_ci wrt_reg_dword(®->req_q_out, 0); 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci wrt_reg_dword(®->rsp_q_in, 0); 6828c2ecf20Sopenharmony_ci wrt_reg_dword(®->rsp_q_out, 0); 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci /* PCI posting */ 6858c2ecf20Sopenharmony_ci rd_reg_dword(®->rsp_q_out); 6868c2ecf20Sopenharmony_ci} 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_cichar * 6898c2ecf20Sopenharmony_ciqlafx00_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len) 6908c2ecf20Sopenharmony_ci{ 6918c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci if (pci_is_pcie(ha->pdev)) 6948c2ecf20Sopenharmony_ci strlcpy(str, "PCIe iSA", str_len); 6958c2ecf20Sopenharmony_ci return str; 6968c2ecf20Sopenharmony_ci} 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_cichar * 6998c2ecf20Sopenharmony_ciqlafx00_fw_version_str(struct scsi_qla_host *vha, char *str, size_t size) 7008c2ecf20Sopenharmony_ci{ 7018c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci snprintf(str, size, "%s", ha->mr.fw_version); 7048c2ecf20Sopenharmony_ci return str; 7058c2ecf20Sopenharmony_ci} 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_civoid 7088c2ecf20Sopenharmony_ciqlafx00_enable_intrs(struct qla_hw_data *ha) 7098c2ecf20Sopenharmony_ci{ 7108c2ecf20Sopenharmony_ci unsigned long flags = 0; 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 7138c2ecf20Sopenharmony_ci ha->interrupts_on = 1; 7148c2ecf20Sopenharmony_ci QLAFX00_ENABLE_ICNTRL_REG(ha); 7158c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 7168c2ecf20Sopenharmony_ci} 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_civoid 7198c2ecf20Sopenharmony_ciqlafx00_disable_intrs(struct qla_hw_data *ha) 7208c2ecf20Sopenharmony_ci{ 7218c2ecf20Sopenharmony_ci unsigned long flags = 0; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 7248c2ecf20Sopenharmony_ci ha->interrupts_on = 0; 7258c2ecf20Sopenharmony_ci QLAFX00_DISABLE_ICNTRL_REG(ha); 7268c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 7278c2ecf20Sopenharmony_ci} 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ciint 7308c2ecf20Sopenharmony_ciqlafx00_abort_target(fc_port_t *fcport, uint64_t l, int tag) 7318c2ecf20Sopenharmony_ci{ 7328c2ecf20Sopenharmony_ci return qla2x00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag); 7338c2ecf20Sopenharmony_ci} 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ciint 7368c2ecf20Sopenharmony_ciqlafx00_lun_reset(fc_port_t *fcport, uint64_t l, int tag) 7378c2ecf20Sopenharmony_ci{ 7388c2ecf20Sopenharmony_ci return qla2x00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag); 7398c2ecf20Sopenharmony_ci} 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ciint 7428c2ecf20Sopenharmony_ciqlafx00_iospace_config(struct qla_hw_data *ha) 7438c2ecf20Sopenharmony_ci{ 7448c2ecf20Sopenharmony_ci if (pci_request_selected_regions(ha->pdev, ha->bars, 7458c2ecf20Sopenharmony_ci QLA2XXX_DRIVER_NAME)) { 7468c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x014e, 7478c2ecf20Sopenharmony_ci "Failed to reserve PIO/MMIO regions (%s), aborting.\n", 7488c2ecf20Sopenharmony_ci pci_name(ha->pdev)); 7498c2ecf20Sopenharmony_ci goto iospace_error_exit; 7508c2ecf20Sopenharmony_ci } 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci /* Use MMIO operations for all accesses. */ 7538c2ecf20Sopenharmony_ci if (!(pci_resource_flags(ha->pdev, 0) & IORESOURCE_MEM)) { 7548c2ecf20Sopenharmony_ci ql_log_pci(ql_log_warn, ha->pdev, 0x014f, 7558c2ecf20Sopenharmony_ci "Invalid pci I/O region size (%s).\n", 7568c2ecf20Sopenharmony_ci pci_name(ha->pdev)); 7578c2ecf20Sopenharmony_ci goto iospace_error_exit; 7588c2ecf20Sopenharmony_ci } 7598c2ecf20Sopenharmony_ci if (pci_resource_len(ha->pdev, 0) < BAR0_LEN_FX00) { 7608c2ecf20Sopenharmony_ci ql_log_pci(ql_log_warn, ha->pdev, 0x0127, 7618c2ecf20Sopenharmony_ci "Invalid PCI mem BAR0 region size (%s), aborting\n", 7628c2ecf20Sopenharmony_ci pci_name(ha->pdev)); 7638c2ecf20Sopenharmony_ci goto iospace_error_exit; 7648c2ecf20Sopenharmony_ci } 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci ha->cregbase = 7678c2ecf20Sopenharmony_ci ioremap(pci_resource_start(ha->pdev, 0), BAR0_LEN_FX00); 7688c2ecf20Sopenharmony_ci if (!ha->cregbase) { 7698c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x0128, 7708c2ecf20Sopenharmony_ci "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev)); 7718c2ecf20Sopenharmony_ci goto iospace_error_exit; 7728c2ecf20Sopenharmony_ci } 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci if (!(pci_resource_flags(ha->pdev, 2) & IORESOURCE_MEM)) { 7758c2ecf20Sopenharmony_ci ql_log_pci(ql_log_warn, ha->pdev, 0x0129, 7768c2ecf20Sopenharmony_ci "region #2 not an MMIO resource (%s), aborting\n", 7778c2ecf20Sopenharmony_ci pci_name(ha->pdev)); 7788c2ecf20Sopenharmony_ci goto iospace_error_exit; 7798c2ecf20Sopenharmony_ci } 7808c2ecf20Sopenharmony_ci if (pci_resource_len(ha->pdev, 2) < BAR2_LEN_FX00) { 7818c2ecf20Sopenharmony_ci ql_log_pci(ql_log_warn, ha->pdev, 0x012a, 7828c2ecf20Sopenharmony_ci "Invalid PCI mem BAR2 region size (%s), aborting\n", 7838c2ecf20Sopenharmony_ci pci_name(ha->pdev)); 7848c2ecf20Sopenharmony_ci goto iospace_error_exit; 7858c2ecf20Sopenharmony_ci } 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci ha->iobase = 7888c2ecf20Sopenharmony_ci ioremap(pci_resource_start(ha->pdev, 2), BAR2_LEN_FX00); 7898c2ecf20Sopenharmony_ci if (!ha->iobase) { 7908c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x012b, 7918c2ecf20Sopenharmony_ci "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev)); 7928c2ecf20Sopenharmony_ci goto iospace_error_exit; 7938c2ecf20Sopenharmony_ci } 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci /* Determine queue resources */ 7968c2ecf20Sopenharmony_ci ha->max_req_queues = ha->max_rsp_queues = 1; 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci ql_log_pci(ql_log_info, ha->pdev, 0x012c, 7998c2ecf20Sopenharmony_ci "Bars 0x%x, iobase0 0x%p, iobase2 0x%p\n", 8008c2ecf20Sopenharmony_ci ha->bars, ha->cregbase, ha->iobase); 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci return 0; 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ciiospace_error_exit: 8058c2ecf20Sopenharmony_ci return -ENOMEM; 8068c2ecf20Sopenharmony_ci} 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_cistatic void 8098c2ecf20Sopenharmony_ciqlafx00_save_queue_ptrs(struct scsi_qla_host *vha) 8108c2ecf20Sopenharmony_ci{ 8118c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 8128c2ecf20Sopenharmony_ci struct req_que *req = ha->req_q_map[0]; 8138c2ecf20Sopenharmony_ci struct rsp_que *rsp = ha->rsp_q_map[0]; 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci req->length_fx00 = req->length; 8168c2ecf20Sopenharmony_ci req->ring_fx00 = req->ring; 8178c2ecf20Sopenharmony_ci req->dma_fx00 = req->dma; 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci rsp->length_fx00 = rsp->length; 8208c2ecf20Sopenharmony_ci rsp->ring_fx00 = rsp->ring; 8218c2ecf20Sopenharmony_ci rsp->dma_fx00 = rsp->dma; 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x012d, 8248c2ecf20Sopenharmony_ci "req: %p, ring_fx00: %p, length_fx00: 0x%x," 8258c2ecf20Sopenharmony_ci "req->dma_fx00: 0x%llx\n", req, req->ring_fx00, 8268c2ecf20Sopenharmony_ci req->length_fx00, (u64)req->dma_fx00); 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x012e, 8298c2ecf20Sopenharmony_ci "rsp: %p, ring_fx00: %p, length_fx00: 0x%x," 8308c2ecf20Sopenharmony_ci "rsp->dma_fx00: 0x%llx\n", rsp, rsp->ring_fx00, 8318c2ecf20Sopenharmony_ci rsp->length_fx00, (u64)rsp->dma_fx00); 8328c2ecf20Sopenharmony_ci} 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_cistatic int 8358c2ecf20Sopenharmony_ciqlafx00_config_queues(struct scsi_qla_host *vha) 8368c2ecf20Sopenharmony_ci{ 8378c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 8388c2ecf20Sopenharmony_ci struct req_que *req = ha->req_q_map[0]; 8398c2ecf20Sopenharmony_ci struct rsp_que *rsp = ha->rsp_q_map[0]; 8408c2ecf20Sopenharmony_ci dma_addr_t bar2_hdl = pci_resource_start(ha->pdev, 2); 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci req->length = ha->req_que_len; 8438c2ecf20Sopenharmony_ci req->ring = (void __force *)ha->iobase + ha->req_que_off; 8448c2ecf20Sopenharmony_ci req->dma = bar2_hdl + ha->req_que_off; 8458c2ecf20Sopenharmony_ci if ((!req->ring) || (req->length == 0)) { 8468c2ecf20Sopenharmony_ci ql_log_pci(ql_log_info, ha->pdev, 0x012f, 8478c2ecf20Sopenharmony_ci "Unable to allocate memory for req_ring\n"); 8488c2ecf20Sopenharmony_ci return QLA_FUNCTION_FAILED; 8498c2ecf20Sopenharmony_ci } 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0130, 8528c2ecf20Sopenharmony_ci "req: %p req_ring pointer %p req len 0x%x " 8538c2ecf20Sopenharmony_ci "req off 0x%x\n, req->dma: 0x%llx", 8548c2ecf20Sopenharmony_ci req, req->ring, req->length, 8558c2ecf20Sopenharmony_ci ha->req_que_off, (u64)req->dma); 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci rsp->length = ha->rsp_que_len; 8588c2ecf20Sopenharmony_ci rsp->ring = (void __force *)ha->iobase + ha->rsp_que_off; 8598c2ecf20Sopenharmony_ci rsp->dma = bar2_hdl + ha->rsp_que_off; 8608c2ecf20Sopenharmony_ci if ((!rsp->ring) || (rsp->length == 0)) { 8618c2ecf20Sopenharmony_ci ql_log_pci(ql_log_info, ha->pdev, 0x0131, 8628c2ecf20Sopenharmony_ci "Unable to allocate memory for rsp_ring\n"); 8638c2ecf20Sopenharmony_ci return QLA_FUNCTION_FAILED; 8648c2ecf20Sopenharmony_ci } 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0132, 8678c2ecf20Sopenharmony_ci "rsp: %p rsp_ring pointer %p rsp len 0x%x " 8688c2ecf20Sopenharmony_ci "rsp off 0x%x, rsp->dma: 0x%llx\n", 8698c2ecf20Sopenharmony_ci rsp, rsp->ring, rsp->length, 8708c2ecf20Sopenharmony_ci ha->rsp_que_off, (u64)rsp->dma); 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci return QLA_SUCCESS; 8738c2ecf20Sopenharmony_ci} 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_cistatic int 8768c2ecf20Sopenharmony_ciqlafx00_init_fw_ready(scsi_qla_host_t *vha) 8778c2ecf20Sopenharmony_ci{ 8788c2ecf20Sopenharmony_ci int rval = 0; 8798c2ecf20Sopenharmony_ci unsigned long wtime; 8808c2ecf20Sopenharmony_ci uint16_t wait_time; /* Wait time */ 8818c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 8828c2ecf20Sopenharmony_ci struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00; 8838c2ecf20Sopenharmony_ci uint32_t aenmbx, aenmbx7 = 0; 8848c2ecf20Sopenharmony_ci uint32_t pseudo_aen; 8858c2ecf20Sopenharmony_ci uint32_t state[5]; 8868c2ecf20Sopenharmony_ci bool done = false; 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci /* 30 seconds wait - Adjust if required */ 8898c2ecf20Sopenharmony_ci wait_time = 30; 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci pseudo_aen = rd_reg_dword(®->pseudoaen); 8928c2ecf20Sopenharmony_ci if (pseudo_aen == 1) { 8938c2ecf20Sopenharmony_ci aenmbx7 = rd_reg_dword(®->initval7); 8948c2ecf20Sopenharmony_ci ha->mbx_intr_code = MSW(aenmbx7); 8958c2ecf20Sopenharmony_ci ha->rqstq_intr_code = LSW(aenmbx7); 8968c2ecf20Sopenharmony_ci rval = qlafx00_driver_shutdown(vha, 10); 8978c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 8988c2ecf20Sopenharmony_ci qlafx00_soft_reset(vha); 8998c2ecf20Sopenharmony_ci } 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci /* wait time before firmware ready */ 9028c2ecf20Sopenharmony_ci wtime = jiffies + (wait_time * HZ); 9038c2ecf20Sopenharmony_ci do { 9048c2ecf20Sopenharmony_ci aenmbx = rd_reg_dword(®->aenmailbox0); 9058c2ecf20Sopenharmony_ci barrier(); 9068c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_mbx, vha, 0x0133, 9078c2ecf20Sopenharmony_ci "aenmbx: 0x%x\n", aenmbx); 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci switch (aenmbx) { 9108c2ecf20Sopenharmony_ci case MBA_FW_NOT_STARTED: 9118c2ecf20Sopenharmony_ci case MBA_FW_STARTING: 9128c2ecf20Sopenharmony_ci break; 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci case MBA_SYSTEM_ERR: 9158c2ecf20Sopenharmony_ci case MBA_REQ_TRANSFER_ERR: 9168c2ecf20Sopenharmony_ci case MBA_RSP_TRANSFER_ERR: 9178c2ecf20Sopenharmony_ci case MBA_FW_INIT_FAILURE: 9188c2ecf20Sopenharmony_ci qlafx00_soft_reset(vha); 9198c2ecf20Sopenharmony_ci break; 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci case MBA_FW_RESTART_CMPLT: 9228c2ecf20Sopenharmony_ci /* Set the mbx and rqstq intr code */ 9238c2ecf20Sopenharmony_ci aenmbx7 = rd_reg_dword(®->aenmailbox7); 9248c2ecf20Sopenharmony_ci ha->mbx_intr_code = MSW(aenmbx7); 9258c2ecf20Sopenharmony_ci ha->rqstq_intr_code = LSW(aenmbx7); 9268c2ecf20Sopenharmony_ci ha->req_que_off = rd_reg_dword(®->aenmailbox1); 9278c2ecf20Sopenharmony_ci ha->rsp_que_off = rd_reg_dword(®->aenmailbox3); 9288c2ecf20Sopenharmony_ci ha->req_que_len = rd_reg_dword(®->aenmailbox5); 9298c2ecf20Sopenharmony_ci ha->rsp_que_len = rd_reg_dword(®->aenmailbox6); 9308c2ecf20Sopenharmony_ci wrt_reg_dword(®->aenmailbox0, 0); 9318c2ecf20Sopenharmony_ci rd_reg_dword_relaxed(®->aenmailbox0); 9328c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0134, 9338c2ecf20Sopenharmony_ci "f/w returned mbx_intr_code: 0x%x, " 9348c2ecf20Sopenharmony_ci "rqstq_intr_code: 0x%x\n", 9358c2ecf20Sopenharmony_ci ha->mbx_intr_code, ha->rqstq_intr_code); 9368c2ecf20Sopenharmony_ci QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS); 9378c2ecf20Sopenharmony_ci rval = QLA_SUCCESS; 9388c2ecf20Sopenharmony_ci done = true; 9398c2ecf20Sopenharmony_ci break; 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci default: 9428c2ecf20Sopenharmony_ci if ((aenmbx & 0xFF00) == MBA_FW_INIT_INPROGRESS) 9438c2ecf20Sopenharmony_ci break; 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci /* If fw is apparently not ready. In order to continue, 9468c2ecf20Sopenharmony_ci * we might need to issue Mbox cmd, but the problem is 9478c2ecf20Sopenharmony_ci * that the DoorBell vector values that come with the 9488c2ecf20Sopenharmony_ci * 8060 AEN are most likely gone by now (and thus no 9498c2ecf20Sopenharmony_ci * bell would be rung on the fw side when mbox cmd is 9508c2ecf20Sopenharmony_ci * issued). We have to therefore grab the 8060 AEN 9518c2ecf20Sopenharmony_ci * shadow regs (filled in by FW when the last 8060 9528c2ecf20Sopenharmony_ci * AEN was being posted). 9538c2ecf20Sopenharmony_ci * Do the following to determine what is needed in 9548c2ecf20Sopenharmony_ci * order to get the FW ready: 9558c2ecf20Sopenharmony_ci * 1. reload the 8060 AEN values from the shadow regs 9568c2ecf20Sopenharmony_ci * 2. clear int status to get rid of possible pending 9578c2ecf20Sopenharmony_ci * interrupts 9588c2ecf20Sopenharmony_ci * 3. issue Get FW State Mbox cmd to determine fw state 9598c2ecf20Sopenharmony_ci * Set the mbx and rqstq intr code from Shadow Regs 9608c2ecf20Sopenharmony_ci */ 9618c2ecf20Sopenharmony_ci aenmbx7 = rd_reg_dword(®->initval7); 9628c2ecf20Sopenharmony_ci ha->mbx_intr_code = MSW(aenmbx7); 9638c2ecf20Sopenharmony_ci ha->rqstq_intr_code = LSW(aenmbx7); 9648c2ecf20Sopenharmony_ci ha->req_que_off = rd_reg_dword(®->initval1); 9658c2ecf20Sopenharmony_ci ha->rsp_que_off = rd_reg_dword(®->initval3); 9668c2ecf20Sopenharmony_ci ha->req_que_len = rd_reg_dword(®->initval5); 9678c2ecf20Sopenharmony_ci ha->rsp_que_len = rd_reg_dword(®->initval6); 9688c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0135, 9698c2ecf20Sopenharmony_ci "f/w returned mbx_intr_code: 0x%x, " 9708c2ecf20Sopenharmony_ci "rqstq_intr_code: 0x%x\n", 9718c2ecf20Sopenharmony_ci ha->mbx_intr_code, ha->rqstq_intr_code); 9728c2ecf20Sopenharmony_ci QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS); 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci /* Get the FW state */ 9758c2ecf20Sopenharmony_ci rval = qlafx00_get_firmware_state(vha, state); 9768c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 9778c2ecf20Sopenharmony_ci /* Retry if timer has not expired */ 9788c2ecf20Sopenharmony_ci break; 9798c2ecf20Sopenharmony_ci } 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci if (state[0] == FSTATE_FX00_CONFIG_WAIT) { 9828c2ecf20Sopenharmony_ci /* Firmware is waiting to be 9838c2ecf20Sopenharmony_ci * initialized by driver 9848c2ecf20Sopenharmony_ci */ 9858c2ecf20Sopenharmony_ci rval = QLA_SUCCESS; 9868c2ecf20Sopenharmony_ci done = true; 9878c2ecf20Sopenharmony_ci break; 9888c2ecf20Sopenharmony_ci } 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci /* Issue driver shutdown and wait until f/w recovers. 9918c2ecf20Sopenharmony_ci * Driver should continue to poll until 8060 AEN is 9928c2ecf20Sopenharmony_ci * received indicating firmware recovery. 9938c2ecf20Sopenharmony_ci */ 9948c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0136, 9958c2ecf20Sopenharmony_ci "Sending Driver shutdown fw_state 0x%x\n", 9968c2ecf20Sopenharmony_ci state[0]); 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci rval = qlafx00_driver_shutdown(vha, 10); 9998c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 10008c2ecf20Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 10018c2ecf20Sopenharmony_ci break; 10028c2ecf20Sopenharmony_ci } 10038c2ecf20Sopenharmony_ci msleep(500); 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci wtime = jiffies + (wait_time * HZ); 10068c2ecf20Sopenharmony_ci break; 10078c2ecf20Sopenharmony_ci } 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci if (!done) { 10108c2ecf20Sopenharmony_ci if (time_after_eq(jiffies, wtime)) { 10118c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0137, 10128c2ecf20Sopenharmony_ci "Init f/w failed: aen[7]: 0x%x\n", 10138c2ecf20Sopenharmony_ci rd_reg_dword(®->aenmailbox7)); 10148c2ecf20Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 10158c2ecf20Sopenharmony_ci done = true; 10168c2ecf20Sopenharmony_ci break; 10178c2ecf20Sopenharmony_ci } 10188c2ecf20Sopenharmony_ci /* Delay for a while */ 10198c2ecf20Sopenharmony_ci msleep(500); 10208c2ecf20Sopenharmony_ci } 10218c2ecf20Sopenharmony_ci } while (!done); 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci if (rval) 10248c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0138, 10258c2ecf20Sopenharmony_ci "%s **** FAILED ****.\n", __func__); 10268c2ecf20Sopenharmony_ci else 10278c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0139, 10288c2ecf20Sopenharmony_ci "%s **** SUCCESS ****.\n", __func__); 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci return rval; 10318c2ecf20Sopenharmony_ci} 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci/* 10348c2ecf20Sopenharmony_ci * qlafx00_fw_ready() - Waits for firmware ready. 10358c2ecf20Sopenharmony_ci * @ha: HA context 10368c2ecf20Sopenharmony_ci * 10378c2ecf20Sopenharmony_ci * Returns 0 on success. 10388c2ecf20Sopenharmony_ci */ 10398c2ecf20Sopenharmony_ciint 10408c2ecf20Sopenharmony_ciqlafx00_fw_ready(scsi_qla_host_t *vha) 10418c2ecf20Sopenharmony_ci{ 10428c2ecf20Sopenharmony_ci int rval; 10438c2ecf20Sopenharmony_ci unsigned long wtime; 10448c2ecf20Sopenharmony_ci uint16_t wait_time; /* Wait time if loop is coming ready */ 10458c2ecf20Sopenharmony_ci uint32_t state[5]; 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci rval = QLA_SUCCESS; 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci wait_time = 10; 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci /* wait time before firmware ready */ 10528c2ecf20Sopenharmony_ci wtime = jiffies + (wait_time * HZ); 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci /* Wait for ISP to finish init */ 10558c2ecf20Sopenharmony_ci if (!vha->flags.init_done) 10568c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x013a, 10578c2ecf20Sopenharmony_ci "Waiting for init to complete...\n"); 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci do { 10608c2ecf20Sopenharmony_ci rval = qlafx00_get_firmware_state(vha, state); 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci if (rval == QLA_SUCCESS) { 10638c2ecf20Sopenharmony_ci if (state[0] == FSTATE_FX00_INITIALIZED) { 10648c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x013b, 10658c2ecf20Sopenharmony_ci "fw_state=%x\n", state[0]); 10668c2ecf20Sopenharmony_ci rval = QLA_SUCCESS; 10678c2ecf20Sopenharmony_ci break; 10688c2ecf20Sopenharmony_ci } 10698c2ecf20Sopenharmony_ci } 10708c2ecf20Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci if (time_after_eq(jiffies, wtime)) 10738c2ecf20Sopenharmony_ci break; 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci /* Delay for a while */ 10768c2ecf20Sopenharmony_ci msleep(500); 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x013c, 10798c2ecf20Sopenharmony_ci "fw_state=%x curr time=%lx.\n", state[0], jiffies); 10808c2ecf20Sopenharmony_ci } while (1); 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci if (rval) 10848c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x013d, 10858c2ecf20Sopenharmony_ci "Firmware ready **** FAILED ****.\n"); 10868c2ecf20Sopenharmony_ci else 10878c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x013e, 10888c2ecf20Sopenharmony_ci "Firmware ready **** SUCCESS ****.\n"); 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci return rval; 10918c2ecf20Sopenharmony_ci} 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_cistatic int 10948c2ecf20Sopenharmony_ciqlafx00_find_all_targets(scsi_qla_host_t *vha, 10958c2ecf20Sopenharmony_ci struct list_head *new_fcports) 10968c2ecf20Sopenharmony_ci{ 10978c2ecf20Sopenharmony_ci int rval; 10988c2ecf20Sopenharmony_ci uint16_t tgt_id; 10998c2ecf20Sopenharmony_ci fc_port_t *fcport, *new_fcport; 11008c2ecf20Sopenharmony_ci int found; 11018c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci rval = QLA_SUCCESS; 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci if (!test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags)) 11068c2ecf20Sopenharmony_ci return QLA_FUNCTION_FAILED; 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci if ((atomic_read(&vha->loop_down_timer) || 11098c2ecf20Sopenharmony_ci STATE_TRANSITION(vha))) { 11108c2ecf20Sopenharmony_ci atomic_set(&vha->loop_down_timer, 0); 11118c2ecf20Sopenharmony_ci set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); 11128c2ecf20Sopenharmony_ci return QLA_FUNCTION_FAILED; 11138c2ecf20Sopenharmony_ci } 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc + ql_dbg_init, vha, 0x2088, 11168c2ecf20Sopenharmony_ci "Listing Target bit map...\n"); 11178c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_disc + ql_dbg_init, vha, 0x2089, 11188c2ecf20Sopenharmony_ci ha->gid_list, 32); 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci /* Allocate temporary rmtport for any new rmtports discovered. */ 11218c2ecf20Sopenharmony_ci new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); 11228c2ecf20Sopenharmony_ci if (new_fcport == NULL) 11238c2ecf20Sopenharmony_ci return QLA_MEMORY_ALLOC_FAILED; 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci for_each_set_bit(tgt_id, (void *)ha->gid_list, 11268c2ecf20Sopenharmony_ci QLAFX00_TGT_NODE_LIST_SIZE) { 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci /* Send get target node info */ 11298c2ecf20Sopenharmony_ci new_fcport->tgt_id = tgt_id; 11308c2ecf20Sopenharmony_ci rval = qlafx00_fx_disc(vha, new_fcport, 11318c2ecf20Sopenharmony_ci FXDISC_GET_TGT_NODE_INFO); 11328c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 11338c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x208a, 11348c2ecf20Sopenharmony_ci "Target info scan failed -- assuming zero-entry " 11358c2ecf20Sopenharmony_ci "result...\n"); 11368c2ecf20Sopenharmony_ci continue; 11378c2ecf20Sopenharmony_ci } 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci /* Locate matching device in database. */ 11408c2ecf20Sopenharmony_ci found = 0; 11418c2ecf20Sopenharmony_ci list_for_each_entry(fcport, &vha->vp_fcports, list) { 11428c2ecf20Sopenharmony_ci if (memcmp(new_fcport->port_name, 11438c2ecf20Sopenharmony_ci fcport->port_name, WWN_SIZE)) 11448c2ecf20Sopenharmony_ci continue; 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci found++; 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci /* 11498c2ecf20Sopenharmony_ci * If tgt_id is same and state FCS_ONLINE, nothing 11508c2ecf20Sopenharmony_ci * changed. 11518c2ecf20Sopenharmony_ci */ 11528c2ecf20Sopenharmony_ci if (fcport->tgt_id == new_fcport->tgt_id && 11538c2ecf20Sopenharmony_ci atomic_read(&fcport->state) == FCS_ONLINE) 11548c2ecf20Sopenharmony_ci break; 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci /* 11578c2ecf20Sopenharmony_ci * Tgt ID changed or device was marked to be updated. 11588c2ecf20Sopenharmony_ci */ 11598c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc + ql_dbg_init, vha, 0x208b, 11608c2ecf20Sopenharmony_ci "TGT-ID Change(%s): Present tgt id: " 11618c2ecf20Sopenharmony_ci "0x%x state: 0x%x " 11628c2ecf20Sopenharmony_ci "wwnn = %llx wwpn = %llx.\n", 11638c2ecf20Sopenharmony_ci __func__, fcport->tgt_id, 11648c2ecf20Sopenharmony_ci atomic_read(&fcport->state), 11658c2ecf20Sopenharmony_ci (unsigned long long)wwn_to_u64(fcport->node_name), 11668c2ecf20Sopenharmony_ci (unsigned long long)wwn_to_u64(fcport->port_name)); 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x208c, 11698c2ecf20Sopenharmony_ci "TGT-ID Announce(%s): Discovered tgt " 11708c2ecf20Sopenharmony_ci "id 0x%x wwnn = %llx " 11718c2ecf20Sopenharmony_ci "wwpn = %llx.\n", __func__, new_fcport->tgt_id, 11728c2ecf20Sopenharmony_ci (unsigned long long) 11738c2ecf20Sopenharmony_ci wwn_to_u64(new_fcport->node_name), 11748c2ecf20Sopenharmony_ci (unsigned long long) 11758c2ecf20Sopenharmony_ci wwn_to_u64(new_fcport->port_name)); 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci if (atomic_read(&fcport->state) != FCS_ONLINE) { 11788c2ecf20Sopenharmony_ci fcport->old_tgt_id = fcport->tgt_id; 11798c2ecf20Sopenharmony_ci fcport->tgt_id = new_fcport->tgt_id; 11808c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x208d, 11818c2ecf20Sopenharmony_ci "TGT-ID: New fcport Added: %p\n", fcport); 11828c2ecf20Sopenharmony_ci qla2x00_update_fcport(vha, fcport); 11838c2ecf20Sopenharmony_ci } else { 11848c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x208e, 11858c2ecf20Sopenharmony_ci " Existing TGT-ID %x did not get " 11868c2ecf20Sopenharmony_ci " offline event from firmware.\n", 11878c2ecf20Sopenharmony_ci fcport->old_tgt_id); 11888c2ecf20Sopenharmony_ci qla2x00_mark_device_lost(vha, fcport, 0); 11898c2ecf20Sopenharmony_ci set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); 11908c2ecf20Sopenharmony_ci qla2x00_free_fcport(new_fcport); 11918c2ecf20Sopenharmony_ci return rval; 11928c2ecf20Sopenharmony_ci } 11938c2ecf20Sopenharmony_ci break; 11948c2ecf20Sopenharmony_ci } 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci if (found) 11978c2ecf20Sopenharmony_ci continue; 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci /* If device was not in our fcports list, then add it. */ 12008c2ecf20Sopenharmony_ci list_add_tail(&new_fcport->list, new_fcports); 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci /* Allocate a new replacement fcport. */ 12038c2ecf20Sopenharmony_ci new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); 12048c2ecf20Sopenharmony_ci if (new_fcport == NULL) 12058c2ecf20Sopenharmony_ci return QLA_MEMORY_ALLOC_FAILED; 12068c2ecf20Sopenharmony_ci } 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci qla2x00_free_fcport(new_fcport); 12098c2ecf20Sopenharmony_ci return rval; 12108c2ecf20Sopenharmony_ci} 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci/* 12138c2ecf20Sopenharmony_ci * qlafx00_configure_all_targets 12148c2ecf20Sopenharmony_ci * Setup target devices with node ID's. 12158c2ecf20Sopenharmony_ci * 12168c2ecf20Sopenharmony_ci * Input: 12178c2ecf20Sopenharmony_ci * ha = adapter block pointer. 12188c2ecf20Sopenharmony_ci * 12198c2ecf20Sopenharmony_ci * Returns: 12208c2ecf20Sopenharmony_ci * 0 = success. 12218c2ecf20Sopenharmony_ci * BIT_0 = error 12228c2ecf20Sopenharmony_ci */ 12238c2ecf20Sopenharmony_cistatic int 12248c2ecf20Sopenharmony_ciqlafx00_configure_all_targets(scsi_qla_host_t *vha) 12258c2ecf20Sopenharmony_ci{ 12268c2ecf20Sopenharmony_ci int rval; 12278c2ecf20Sopenharmony_ci fc_port_t *fcport, *rmptemp; 12288c2ecf20Sopenharmony_ci LIST_HEAD(new_fcports); 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci rval = qlafx00_fx_disc(vha, &vha->hw->mr.fcport, 12318c2ecf20Sopenharmony_ci FXDISC_GET_TGT_NODE_LIST); 12328c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 12338c2ecf20Sopenharmony_ci set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); 12348c2ecf20Sopenharmony_ci return rval; 12358c2ecf20Sopenharmony_ci } 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci rval = qlafx00_find_all_targets(vha, &new_fcports); 12388c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 12398c2ecf20Sopenharmony_ci set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); 12408c2ecf20Sopenharmony_ci return rval; 12418c2ecf20Sopenharmony_ci } 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci /* 12448c2ecf20Sopenharmony_ci * Delete all previous devices marked lost. 12458c2ecf20Sopenharmony_ci */ 12468c2ecf20Sopenharmony_ci list_for_each_entry(fcport, &vha->vp_fcports, list) { 12478c2ecf20Sopenharmony_ci if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) 12488c2ecf20Sopenharmony_ci break; 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci if (atomic_read(&fcport->state) == FCS_DEVICE_LOST) { 12518c2ecf20Sopenharmony_ci if (fcport->port_type != FCT_INITIATOR) 12528c2ecf20Sopenharmony_ci qla2x00_mark_device_lost(vha, fcport, 0); 12538c2ecf20Sopenharmony_ci } 12548c2ecf20Sopenharmony_ci } 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci /* 12578c2ecf20Sopenharmony_ci * Add the new devices to our devices list. 12588c2ecf20Sopenharmony_ci */ 12598c2ecf20Sopenharmony_ci list_for_each_entry_safe(fcport, rmptemp, &new_fcports, list) { 12608c2ecf20Sopenharmony_ci if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) 12618c2ecf20Sopenharmony_ci break; 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci qla2x00_update_fcport(vha, fcport); 12648c2ecf20Sopenharmony_ci list_move_tail(&fcport->list, &vha->vp_fcports); 12658c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x208f, 12668c2ecf20Sopenharmony_ci "Attach new target id 0x%x wwnn = %llx " 12678c2ecf20Sopenharmony_ci "wwpn = %llx.\n", 12688c2ecf20Sopenharmony_ci fcport->tgt_id, 12698c2ecf20Sopenharmony_ci (unsigned long long)wwn_to_u64(fcport->node_name), 12708c2ecf20Sopenharmony_ci (unsigned long long)wwn_to_u64(fcport->port_name)); 12718c2ecf20Sopenharmony_ci } 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci /* Free all new device structures not processed. */ 12748c2ecf20Sopenharmony_ci list_for_each_entry_safe(fcport, rmptemp, &new_fcports, list) { 12758c2ecf20Sopenharmony_ci list_del(&fcport->list); 12768c2ecf20Sopenharmony_ci qla2x00_free_fcport(fcport); 12778c2ecf20Sopenharmony_ci } 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci return rval; 12808c2ecf20Sopenharmony_ci} 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_ci/* 12838c2ecf20Sopenharmony_ci * qlafx00_configure_devices 12848c2ecf20Sopenharmony_ci * Updates Fibre Channel Device Database with what is actually on loop. 12858c2ecf20Sopenharmony_ci * 12868c2ecf20Sopenharmony_ci * Input: 12878c2ecf20Sopenharmony_ci * ha = adapter block pointer. 12888c2ecf20Sopenharmony_ci * 12898c2ecf20Sopenharmony_ci * Returns: 12908c2ecf20Sopenharmony_ci * 0 = success. 12918c2ecf20Sopenharmony_ci * 1 = error. 12928c2ecf20Sopenharmony_ci * 2 = database was full and device was not configured. 12938c2ecf20Sopenharmony_ci */ 12948c2ecf20Sopenharmony_ciint 12958c2ecf20Sopenharmony_ciqlafx00_configure_devices(scsi_qla_host_t *vha) 12968c2ecf20Sopenharmony_ci{ 12978c2ecf20Sopenharmony_ci int rval; 12988c2ecf20Sopenharmony_ci unsigned long flags; 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci rval = QLA_SUCCESS; 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci flags = vha->dpc_flags; 13038c2ecf20Sopenharmony_ci 13048c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc, vha, 0x2090, 13058c2ecf20Sopenharmony_ci "Configure devices -- dpc flags =0x%lx\n", flags); 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci rval = qlafx00_configure_all_targets(vha); 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_ci if (rval == QLA_SUCCESS) { 13108c2ecf20Sopenharmony_ci if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) { 13118c2ecf20Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 13128c2ecf20Sopenharmony_ci } else { 13138c2ecf20Sopenharmony_ci atomic_set(&vha->loop_state, LOOP_READY); 13148c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x2091, 13158c2ecf20Sopenharmony_ci "Device Ready\n"); 13168c2ecf20Sopenharmony_ci } 13178c2ecf20Sopenharmony_ci } 13188c2ecf20Sopenharmony_ci 13198c2ecf20Sopenharmony_ci if (rval) { 13208c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc, vha, 0x2092, 13218c2ecf20Sopenharmony_ci "%s *** FAILED ***.\n", __func__); 13228c2ecf20Sopenharmony_ci } else { 13238c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc, vha, 0x2093, 13248c2ecf20Sopenharmony_ci "%s: exiting normally.\n", __func__); 13258c2ecf20Sopenharmony_ci } 13268c2ecf20Sopenharmony_ci return rval; 13278c2ecf20Sopenharmony_ci} 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_cistatic void 13308c2ecf20Sopenharmony_ciqlafx00_abort_isp_cleanup(scsi_qla_host_t *vha, bool critemp) 13318c2ecf20Sopenharmony_ci{ 13328c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 13338c2ecf20Sopenharmony_ci fc_port_t *fcport; 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci vha->flags.online = 0; 13368c2ecf20Sopenharmony_ci ha->mr.fw_hbt_en = 0; 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_ci if (!critemp) { 13398c2ecf20Sopenharmony_ci ha->flags.chip_reset_done = 0; 13408c2ecf20Sopenharmony_ci clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 13418c2ecf20Sopenharmony_ci vha->qla_stats.total_isp_aborts++; 13428c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x013f, 13438c2ecf20Sopenharmony_ci "Performing ISP error recovery - ha = %p.\n", ha); 13448c2ecf20Sopenharmony_ci ha->isp_ops->reset_chip(vha); 13458c2ecf20Sopenharmony_ci } 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci if (atomic_read(&vha->loop_state) != LOOP_DOWN) { 13488c2ecf20Sopenharmony_ci atomic_set(&vha->loop_state, LOOP_DOWN); 13498c2ecf20Sopenharmony_ci atomic_set(&vha->loop_down_timer, 13508c2ecf20Sopenharmony_ci QLAFX00_LOOP_DOWN_TIME); 13518c2ecf20Sopenharmony_ci } else { 13528c2ecf20Sopenharmony_ci if (!atomic_read(&vha->loop_down_timer)) 13538c2ecf20Sopenharmony_ci atomic_set(&vha->loop_down_timer, 13548c2ecf20Sopenharmony_ci QLAFX00_LOOP_DOWN_TIME); 13558c2ecf20Sopenharmony_ci } 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci /* Clear all async request states across all VPs. */ 13588c2ecf20Sopenharmony_ci list_for_each_entry(fcport, &vha->vp_fcports, list) { 13598c2ecf20Sopenharmony_ci fcport->flags = 0; 13608c2ecf20Sopenharmony_ci if (atomic_read(&fcport->state) == FCS_ONLINE) 13618c2ecf20Sopenharmony_ci qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST); 13628c2ecf20Sopenharmony_ci } 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci if (!ha->flags.eeh_busy) { 13658c2ecf20Sopenharmony_ci if (critemp) { 13668c2ecf20Sopenharmony_ci qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16); 13678c2ecf20Sopenharmony_ci } else { 13688c2ecf20Sopenharmony_ci /* Requeue all commands in outstanding command list. */ 13698c2ecf20Sopenharmony_ci qla2x00_abort_all_cmds(vha, DID_RESET << 16); 13708c2ecf20Sopenharmony_ci } 13718c2ecf20Sopenharmony_ci } 13728c2ecf20Sopenharmony_ci 13738c2ecf20Sopenharmony_ci qla2x00_free_irqs(vha); 13748c2ecf20Sopenharmony_ci if (critemp) 13758c2ecf20Sopenharmony_ci set_bit(FX00_CRITEMP_RECOVERY, &vha->dpc_flags); 13768c2ecf20Sopenharmony_ci else 13778c2ecf20Sopenharmony_ci set_bit(FX00_RESET_RECOVERY, &vha->dpc_flags); 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci /* Clear the Interrupts */ 13808c2ecf20Sopenharmony_ci QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS); 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x0140, 13838c2ecf20Sopenharmony_ci "%s Done done - ha=%p.\n", __func__, ha); 13848c2ecf20Sopenharmony_ci} 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_ci/** 13878c2ecf20Sopenharmony_ci * qlafx00_init_response_q_entries() - Initializes response queue entries. 13888c2ecf20Sopenharmony_ci * @rsp: response queue 13898c2ecf20Sopenharmony_ci * 13908c2ecf20Sopenharmony_ci * Beginning of request ring has initialization control block already built 13918c2ecf20Sopenharmony_ci * by nvram config routine. 13928c2ecf20Sopenharmony_ci * 13938c2ecf20Sopenharmony_ci * Returns 0 on success. 13948c2ecf20Sopenharmony_ci */ 13958c2ecf20Sopenharmony_civoid 13968c2ecf20Sopenharmony_ciqlafx00_init_response_q_entries(struct rsp_que *rsp) 13978c2ecf20Sopenharmony_ci{ 13988c2ecf20Sopenharmony_ci uint16_t cnt; 13998c2ecf20Sopenharmony_ci response_t *pkt; 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci rsp->ring_ptr = rsp->ring; 14028c2ecf20Sopenharmony_ci rsp->ring_index = 0; 14038c2ecf20Sopenharmony_ci rsp->status_srb = NULL; 14048c2ecf20Sopenharmony_ci pkt = rsp->ring_ptr; 14058c2ecf20Sopenharmony_ci for (cnt = 0; cnt < rsp->length; cnt++) { 14068c2ecf20Sopenharmony_ci pkt->signature = RESPONSE_PROCESSED; 14078c2ecf20Sopenharmony_ci wrt_reg_dword((void __force __iomem *)&pkt->signature, 14088c2ecf20Sopenharmony_ci RESPONSE_PROCESSED); 14098c2ecf20Sopenharmony_ci pkt++; 14108c2ecf20Sopenharmony_ci } 14118c2ecf20Sopenharmony_ci} 14128c2ecf20Sopenharmony_ci 14138c2ecf20Sopenharmony_ciint 14148c2ecf20Sopenharmony_ciqlafx00_rescan_isp(scsi_qla_host_t *vha) 14158c2ecf20Sopenharmony_ci{ 14168c2ecf20Sopenharmony_ci uint32_t status = QLA_FUNCTION_FAILED; 14178c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 14188c2ecf20Sopenharmony_ci struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00; 14198c2ecf20Sopenharmony_ci uint32_t aenmbx7; 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci qla2x00_request_irqs(ha, ha->rsp_q_map[0]); 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci aenmbx7 = rd_reg_dword(®->aenmailbox7); 14248c2ecf20Sopenharmony_ci ha->mbx_intr_code = MSW(aenmbx7); 14258c2ecf20Sopenharmony_ci ha->rqstq_intr_code = LSW(aenmbx7); 14268c2ecf20Sopenharmony_ci ha->req_que_off = rd_reg_dword(®->aenmailbox1); 14278c2ecf20Sopenharmony_ci ha->rsp_que_off = rd_reg_dword(®->aenmailbox3); 14288c2ecf20Sopenharmony_ci ha->req_que_len = rd_reg_dword(®->aenmailbox5); 14298c2ecf20Sopenharmony_ci ha->rsp_que_len = rd_reg_dword(®->aenmailbox6); 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc, vha, 0x2094, 14328c2ecf20Sopenharmony_ci "fw returned mbx_intr_code: 0x%x, rqstq_intr_code: 0x%x " 14338c2ecf20Sopenharmony_ci " Req que offset 0x%x Rsp que offset 0x%x\n", 14348c2ecf20Sopenharmony_ci ha->mbx_intr_code, ha->rqstq_intr_code, 14358c2ecf20Sopenharmony_ci ha->req_que_off, ha->rsp_que_len); 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci /* Clear the Interrupts */ 14388c2ecf20Sopenharmony_ci QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS); 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci status = qla2x00_init_rings(vha); 14418c2ecf20Sopenharmony_ci if (!status) { 14428c2ecf20Sopenharmony_ci vha->flags.online = 1; 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci /* if no cable then assume it's good */ 14458c2ecf20Sopenharmony_ci if ((vha->device_flags & DFLG_NO_CABLE)) 14468c2ecf20Sopenharmony_ci status = 0; 14478c2ecf20Sopenharmony_ci /* Register system information */ 14488c2ecf20Sopenharmony_ci if (qlafx00_fx_disc(vha, 14498c2ecf20Sopenharmony_ci &vha->hw->mr.fcport, FXDISC_REG_HOST_INFO)) 14508c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc, vha, 0x2095, 14518c2ecf20Sopenharmony_ci "failed to register host info\n"); 14528c2ecf20Sopenharmony_ci } 14538c2ecf20Sopenharmony_ci scsi_unblock_requests(vha->host); 14548c2ecf20Sopenharmony_ci return status; 14558c2ecf20Sopenharmony_ci} 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_civoid 14588c2ecf20Sopenharmony_ciqlafx00_timer_routine(scsi_qla_host_t *vha) 14598c2ecf20Sopenharmony_ci{ 14608c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 14618c2ecf20Sopenharmony_ci uint32_t fw_heart_beat; 14628c2ecf20Sopenharmony_ci uint32_t aenmbx0; 14638c2ecf20Sopenharmony_ci struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00; 14648c2ecf20Sopenharmony_ci uint32_t tempc; 14658c2ecf20Sopenharmony_ci 14668c2ecf20Sopenharmony_ci /* Check firmware health */ 14678c2ecf20Sopenharmony_ci if (ha->mr.fw_hbt_cnt) 14688c2ecf20Sopenharmony_ci ha->mr.fw_hbt_cnt--; 14698c2ecf20Sopenharmony_ci else { 14708c2ecf20Sopenharmony_ci if ((!ha->flags.mr_reset_hdlr_active) && 14718c2ecf20Sopenharmony_ci (!test_bit(UNLOADING, &vha->dpc_flags)) && 14728c2ecf20Sopenharmony_ci (!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) && 14738c2ecf20Sopenharmony_ci (ha->mr.fw_hbt_en)) { 14748c2ecf20Sopenharmony_ci fw_heart_beat = rd_reg_dword(®->fwheartbeat); 14758c2ecf20Sopenharmony_ci if (fw_heart_beat != ha->mr.old_fw_hbt_cnt) { 14768c2ecf20Sopenharmony_ci ha->mr.old_fw_hbt_cnt = fw_heart_beat; 14778c2ecf20Sopenharmony_ci ha->mr.fw_hbt_miss_cnt = 0; 14788c2ecf20Sopenharmony_ci } else { 14798c2ecf20Sopenharmony_ci ha->mr.fw_hbt_miss_cnt++; 14808c2ecf20Sopenharmony_ci if (ha->mr.fw_hbt_miss_cnt == 14818c2ecf20Sopenharmony_ci QLAFX00_HEARTBEAT_MISS_CNT) { 14828c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, 14838c2ecf20Sopenharmony_ci &vha->dpc_flags); 14848c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 14858c2ecf20Sopenharmony_ci ha->mr.fw_hbt_miss_cnt = 0; 14868c2ecf20Sopenharmony_ci } 14878c2ecf20Sopenharmony_ci } 14888c2ecf20Sopenharmony_ci } 14898c2ecf20Sopenharmony_ci ha->mr.fw_hbt_cnt = QLAFX00_HEARTBEAT_INTERVAL; 14908c2ecf20Sopenharmony_ci } 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci if (test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags)) { 14938c2ecf20Sopenharmony_ci /* Reset recovery to be performed in timer routine */ 14948c2ecf20Sopenharmony_ci aenmbx0 = rd_reg_dword(®->aenmailbox0); 14958c2ecf20Sopenharmony_ci if (ha->mr.fw_reset_timer_exp) { 14968c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 14978c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 14988c2ecf20Sopenharmony_ci ha->mr.fw_reset_timer_exp = 0; 14998c2ecf20Sopenharmony_ci } else if (aenmbx0 == MBA_FW_RESTART_CMPLT) { 15008c2ecf20Sopenharmony_ci /* Wake up DPC to rescan the targets */ 15018c2ecf20Sopenharmony_ci set_bit(FX00_TARGET_SCAN, &vha->dpc_flags); 15028c2ecf20Sopenharmony_ci clear_bit(FX00_RESET_RECOVERY, &vha->dpc_flags); 15038c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 15048c2ecf20Sopenharmony_ci ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL; 15058c2ecf20Sopenharmony_ci } else if ((aenmbx0 == MBA_FW_STARTING) && 15068c2ecf20Sopenharmony_ci (!ha->mr.fw_hbt_en)) { 15078c2ecf20Sopenharmony_ci ha->mr.fw_hbt_en = 1; 15088c2ecf20Sopenharmony_ci } else if (!ha->mr.fw_reset_timer_tick) { 15098c2ecf20Sopenharmony_ci if (aenmbx0 == ha->mr.old_aenmbx0_state) 15108c2ecf20Sopenharmony_ci ha->mr.fw_reset_timer_exp = 1; 15118c2ecf20Sopenharmony_ci ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL; 15128c2ecf20Sopenharmony_ci } else if (aenmbx0 == 0xFFFFFFFF) { 15138c2ecf20Sopenharmony_ci uint32_t data0, data1; 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci data0 = QLAFX00_RD_REG(ha, 15168c2ecf20Sopenharmony_ci QLAFX00_BAR1_BASE_ADDR_REG); 15178c2ecf20Sopenharmony_ci data1 = QLAFX00_RD_REG(ha, 15188c2ecf20Sopenharmony_ci QLAFX00_PEX0_WIN0_BASE_ADDR_REG); 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_ci data0 &= 0xffff0000; 15218c2ecf20Sopenharmony_ci data1 &= 0x0000ffff; 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_ci QLAFX00_WR_REG(ha, 15248c2ecf20Sopenharmony_ci QLAFX00_PEX0_WIN0_BASE_ADDR_REG, 15258c2ecf20Sopenharmony_ci (data0 | data1)); 15268c2ecf20Sopenharmony_ci } else if ((aenmbx0 & 0xFF00) == MBA_FW_POLL_STATE) { 15278c2ecf20Sopenharmony_ci ha->mr.fw_reset_timer_tick = 15288c2ecf20Sopenharmony_ci QLAFX00_MAX_RESET_INTERVAL; 15298c2ecf20Sopenharmony_ci } else if (aenmbx0 == MBA_FW_RESET_FCT) { 15308c2ecf20Sopenharmony_ci ha->mr.fw_reset_timer_tick = 15318c2ecf20Sopenharmony_ci QLAFX00_MAX_RESET_INTERVAL; 15328c2ecf20Sopenharmony_ci } 15338c2ecf20Sopenharmony_ci if (ha->mr.old_aenmbx0_state != aenmbx0) { 15348c2ecf20Sopenharmony_ci ha->mr.old_aenmbx0_state = aenmbx0; 15358c2ecf20Sopenharmony_ci ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL; 15368c2ecf20Sopenharmony_ci } 15378c2ecf20Sopenharmony_ci ha->mr.fw_reset_timer_tick--; 15388c2ecf20Sopenharmony_ci } 15398c2ecf20Sopenharmony_ci if (test_bit(FX00_CRITEMP_RECOVERY, &vha->dpc_flags)) { 15408c2ecf20Sopenharmony_ci /* 15418c2ecf20Sopenharmony_ci * Critical temperature recovery to be 15428c2ecf20Sopenharmony_ci * performed in timer routine 15438c2ecf20Sopenharmony_ci */ 15448c2ecf20Sopenharmony_ci if (ha->mr.fw_critemp_timer_tick == 0) { 15458c2ecf20Sopenharmony_ci tempc = QLAFX00_GET_TEMPERATURE(ha); 15468c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_timer, vha, 0x6012, 15478c2ecf20Sopenharmony_ci "ISPFx00(%s): Critical temp timer, " 15488c2ecf20Sopenharmony_ci "current SOC temperature: %d\n", 15498c2ecf20Sopenharmony_ci __func__, tempc); 15508c2ecf20Sopenharmony_ci if (tempc < ha->mr.critical_temperature) { 15518c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 15528c2ecf20Sopenharmony_ci clear_bit(FX00_CRITEMP_RECOVERY, 15538c2ecf20Sopenharmony_ci &vha->dpc_flags); 15548c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 15558c2ecf20Sopenharmony_ci } 15568c2ecf20Sopenharmony_ci ha->mr.fw_critemp_timer_tick = 15578c2ecf20Sopenharmony_ci QLAFX00_CRITEMP_INTERVAL; 15588c2ecf20Sopenharmony_ci } else { 15598c2ecf20Sopenharmony_ci ha->mr.fw_critemp_timer_tick--; 15608c2ecf20Sopenharmony_ci } 15618c2ecf20Sopenharmony_ci } 15628c2ecf20Sopenharmony_ci if (ha->mr.host_info_resend) { 15638c2ecf20Sopenharmony_ci /* 15648c2ecf20Sopenharmony_ci * Incomplete host info might be sent to firmware 15658c2ecf20Sopenharmony_ci * durinng system boot - info should be resend 15668c2ecf20Sopenharmony_ci */ 15678c2ecf20Sopenharmony_ci if (ha->mr.hinfo_resend_timer_tick == 0) { 15688c2ecf20Sopenharmony_ci ha->mr.host_info_resend = false; 15698c2ecf20Sopenharmony_ci set_bit(FX00_HOST_INFO_RESEND, &vha->dpc_flags); 15708c2ecf20Sopenharmony_ci ha->mr.hinfo_resend_timer_tick = 15718c2ecf20Sopenharmony_ci QLAFX00_HINFO_RESEND_INTERVAL; 15728c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 15738c2ecf20Sopenharmony_ci } else { 15748c2ecf20Sopenharmony_ci ha->mr.hinfo_resend_timer_tick--; 15758c2ecf20Sopenharmony_ci } 15768c2ecf20Sopenharmony_ci } 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci} 15798c2ecf20Sopenharmony_ci 15808c2ecf20Sopenharmony_ci/* 15818c2ecf20Sopenharmony_ci * qlfx00a_reset_initialize 15828c2ecf20Sopenharmony_ci * Re-initialize after a iSA device reset. 15838c2ecf20Sopenharmony_ci * 15848c2ecf20Sopenharmony_ci * Input: 15858c2ecf20Sopenharmony_ci * ha = adapter block pointer. 15868c2ecf20Sopenharmony_ci * 15878c2ecf20Sopenharmony_ci * Returns: 15888c2ecf20Sopenharmony_ci * 0 = success 15898c2ecf20Sopenharmony_ci */ 15908c2ecf20Sopenharmony_ciint 15918c2ecf20Sopenharmony_ciqlafx00_reset_initialize(scsi_qla_host_t *vha) 15928c2ecf20Sopenharmony_ci{ 15938c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_ci if (vha->device_flags & DFLG_DEV_FAILED) { 15968c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0142, 15978c2ecf20Sopenharmony_ci "Device in failed state\n"); 15988c2ecf20Sopenharmony_ci return QLA_SUCCESS; 15998c2ecf20Sopenharmony_ci } 16008c2ecf20Sopenharmony_ci 16018c2ecf20Sopenharmony_ci ha->flags.mr_reset_hdlr_active = 1; 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_ci if (vha->flags.online) { 16048c2ecf20Sopenharmony_ci scsi_block_requests(vha->host); 16058c2ecf20Sopenharmony_ci qlafx00_abort_isp_cleanup(vha, false); 16068c2ecf20Sopenharmony_ci } 16078c2ecf20Sopenharmony_ci 16088c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x0143, 16098c2ecf20Sopenharmony_ci "(%s): succeeded.\n", __func__); 16108c2ecf20Sopenharmony_ci ha->flags.mr_reset_hdlr_active = 0; 16118c2ecf20Sopenharmony_ci return QLA_SUCCESS; 16128c2ecf20Sopenharmony_ci} 16138c2ecf20Sopenharmony_ci 16148c2ecf20Sopenharmony_ci/* 16158c2ecf20Sopenharmony_ci * qlafx00_abort_isp 16168c2ecf20Sopenharmony_ci * Resets ISP and aborts all outstanding commands. 16178c2ecf20Sopenharmony_ci * 16188c2ecf20Sopenharmony_ci * Input: 16198c2ecf20Sopenharmony_ci * ha = adapter block pointer. 16208c2ecf20Sopenharmony_ci * 16218c2ecf20Sopenharmony_ci * Returns: 16228c2ecf20Sopenharmony_ci * 0 = success 16238c2ecf20Sopenharmony_ci */ 16248c2ecf20Sopenharmony_ciint 16258c2ecf20Sopenharmony_ciqlafx00_abort_isp(scsi_qla_host_t *vha) 16268c2ecf20Sopenharmony_ci{ 16278c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 16288c2ecf20Sopenharmony_ci 16298c2ecf20Sopenharmony_ci if (vha->flags.online) { 16308c2ecf20Sopenharmony_ci if (unlikely(pci_channel_offline(ha->pdev) && 16318c2ecf20Sopenharmony_ci ha->flags.pci_channel_io_perm_failure)) { 16328c2ecf20Sopenharmony_ci clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags); 16338c2ecf20Sopenharmony_ci return QLA_SUCCESS; 16348c2ecf20Sopenharmony_ci } 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_ci scsi_block_requests(vha->host); 16378c2ecf20Sopenharmony_ci qlafx00_abort_isp_cleanup(vha, false); 16388c2ecf20Sopenharmony_ci } else { 16398c2ecf20Sopenharmony_ci scsi_block_requests(vha->host); 16408c2ecf20Sopenharmony_ci clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 16418c2ecf20Sopenharmony_ci vha->qla_stats.total_isp_aborts++; 16428c2ecf20Sopenharmony_ci ha->isp_ops->reset_chip(vha); 16438c2ecf20Sopenharmony_ci set_bit(FX00_RESET_RECOVERY, &vha->dpc_flags); 16448c2ecf20Sopenharmony_ci /* Clear the Interrupts */ 16458c2ecf20Sopenharmony_ci QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS); 16468c2ecf20Sopenharmony_ci } 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x0145, 16498c2ecf20Sopenharmony_ci "(%s): succeeded.\n", __func__); 16508c2ecf20Sopenharmony_ci 16518c2ecf20Sopenharmony_ci return QLA_SUCCESS; 16528c2ecf20Sopenharmony_ci} 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_cistatic inline fc_port_t* 16558c2ecf20Sopenharmony_ciqlafx00_get_fcport(struct scsi_qla_host *vha, int tgt_id) 16568c2ecf20Sopenharmony_ci{ 16578c2ecf20Sopenharmony_ci fc_port_t *fcport; 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ci /* Check for matching device in remote port list. */ 16608c2ecf20Sopenharmony_ci list_for_each_entry(fcport, &vha->vp_fcports, list) { 16618c2ecf20Sopenharmony_ci if (fcport->tgt_id == tgt_id) { 16628c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x5072, 16638c2ecf20Sopenharmony_ci "Matching fcport(%p) found with TGT-ID: 0x%x " 16648c2ecf20Sopenharmony_ci "and Remote TGT_ID: 0x%x\n", 16658c2ecf20Sopenharmony_ci fcport, fcport->tgt_id, tgt_id); 16668c2ecf20Sopenharmony_ci return fcport; 16678c2ecf20Sopenharmony_ci } 16688c2ecf20Sopenharmony_ci } 16698c2ecf20Sopenharmony_ci return NULL; 16708c2ecf20Sopenharmony_ci} 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_cistatic void 16738c2ecf20Sopenharmony_ciqlafx00_tgt_detach(struct scsi_qla_host *vha, int tgt_id) 16748c2ecf20Sopenharmony_ci{ 16758c2ecf20Sopenharmony_ci fc_port_t *fcport; 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x5073, 16788c2ecf20Sopenharmony_ci "Detach TGT-ID: 0x%x\n", tgt_id); 16798c2ecf20Sopenharmony_ci 16808c2ecf20Sopenharmony_ci fcport = qlafx00_get_fcport(vha, tgt_id); 16818c2ecf20Sopenharmony_ci if (!fcport) 16828c2ecf20Sopenharmony_ci return; 16838c2ecf20Sopenharmony_ci 16848c2ecf20Sopenharmony_ci qla2x00_mark_device_lost(vha, fcport, 0); 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_ci return; 16878c2ecf20Sopenharmony_ci} 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_civoid 16908c2ecf20Sopenharmony_ciqlafx00_process_aen(struct scsi_qla_host *vha, struct qla_work_evt *evt) 16918c2ecf20Sopenharmony_ci{ 16928c2ecf20Sopenharmony_ci uint32_t aen_code, aen_data; 16938c2ecf20Sopenharmony_ci 16948c2ecf20Sopenharmony_ci aen_code = FCH_EVT_VENDOR_UNIQUE; 16958c2ecf20Sopenharmony_ci aen_data = evt->u.aenfx.evtcode; 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_ci switch (evt->u.aenfx.evtcode) { 16988c2ecf20Sopenharmony_ci case QLAFX00_MBA_PORT_UPDATE: /* Port database update */ 16998c2ecf20Sopenharmony_ci if (evt->u.aenfx.mbx[1] == 0) { 17008c2ecf20Sopenharmony_ci if (evt->u.aenfx.mbx[2] == 1) { 17018c2ecf20Sopenharmony_ci if (!vha->flags.fw_tgt_reported) 17028c2ecf20Sopenharmony_ci vha->flags.fw_tgt_reported = 1; 17038c2ecf20Sopenharmony_ci atomic_set(&vha->loop_down_timer, 0); 17048c2ecf20Sopenharmony_ci atomic_set(&vha->loop_state, LOOP_UP); 17058c2ecf20Sopenharmony_ci set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); 17068c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 17078c2ecf20Sopenharmony_ci } else if (evt->u.aenfx.mbx[2] == 2) { 17088c2ecf20Sopenharmony_ci qlafx00_tgt_detach(vha, evt->u.aenfx.mbx[3]); 17098c2ecf20Sopenharmony_ci } 17108c2ecf20Sopenharmony_ci } else if (evt->u.aenfx.mbx[1] == 0xffff) { 17118c2ecf20Sopenharmony_ci if (evt->u.aenfx.mbx[2] == 1) { 17128c2ecf20Sopenharmony_ci if (!vha->flags.fw_tgt_reported) 17138c2ecf20Sopenharmony_ci vha->flags.fw_tgt_reported = 1; 17148c2ecf20Sopenharmony_ci set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); 17158c2ecf20Sopenharmony_ci } else if (evt->u.aenfx.mbx[2] == 2) { 17168c2ecf20Sopenharmony_ci vha->device_flags |= DFLG_NO_CABLE; 17178c2ecf20Sopenharmony_ci qla2x00_mark_all_devices_lost(vha); 17188c2ecf20Sopenharmony_ci } 17198c2ecf20Sopenharmony_ci } 17208c2ecf20Sopenharmony_ci break; 17218c2ecf20Sopenharmony_ci case QLAFX00_MBA_LINK_UP: 17228c2ecf20Sopenharmony_ci aen_code = FCH_EVT_LINKUP; 17238c2ecf20Sopenharmony_ci aen_data = 0; 17248c2ecf20Sopenharmony_ci break; 17258c2ecf20Sopenharmony_ci case QLAFX00_MBA_LINK_DOWN: 17268c2ecf20Sopenharmony_ci aen_code = FCH_EVT_LINKDOWN; 17278c2ecf20Sopenharmony_ci aen_data = 0; 17288c2ecf20Sopenharmony_ci break; 17298c2ecf20Sopenharmony_ci case QLAFX00_MBA_TEMP_CRIT: /* Critical temperature event */ 17308c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x5082, 17318c2ecf20Sopenharmony_ci "Process critical temperature event " 17328c2ecf20Sopenharmony_ci "aenmb[0]: %x\n", 17338c2ecf20Sopenharmony_ci evt->u.aenfx.evtcode); 17348c2ecf20Sopenharmony_ci scsi_block_requests(vha->host); 17358c2ecf20Sopenharmony_ci qlafx00_abort_isp_cleanup(vha, true); 17368c2ecf20Sopenharmony_ci scsi_unblock_requests(vha->host); 17378c2ecf20Sopenharmony_ci break; 17388c2ecf20Sopenharmony_ci } 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci fc_host_post_event(vha->host, fc_get_event_number(), 17418c2ecf20Sopenharmony_ci aen_code, aen_data); 17428c2ecf20Sopenharmony_ci} 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_cistatic void 17458c2ecf20Sopenharmony_ciqlafx00_update_host_attr(scsi_qla_host_t *vha, struct port_info_data *pinfo) 17468c2ecf20Sopenharmony_ci{ 17478c2ecf20Sopenharmony_ci u64 port_name = 0, node_name = 0; 17488c2ecf20Sopenharmony_ci 17498c2ecf20Sopenharmony_ci port_name = (unsigned long long)wwn_to_u64(pinfo->port_name); 17508c2ecf20Sopenharmony_ci node_name = (unsigned long long)wwn_to_u64(pinfo->node_name); 17518c2ecf20Sopenharmony_ci 17528c2ecf20Sopenharmony_ci fc_host_node_name(vha->host) = node_name; 17538c2ecf20Sopenharmony_ci fc_host_port_name(vha->host) = port_name; 17548c2ecf20Sopenharmony_ci if (!pinfo->port_type) 17558c2ecf20Sopenharmony_ci vha->hw->current_topology = ISP_CFG_F; 17568c2ecf20Sopenharmony_ci if (pinfo->link_status == QLAFX00_LINK_STATUS_UP) 17578c2ecf20Sopenharmony_ci atomic_set(&vha->loop_state, LOOP_READY); 17588c2ecf20Sopenharmony_ci else if (pinfo->link_status == QLAFX00_LINK_STATUS_DOWN) 17598c2ecf20Sopenharmony_ci atomic_set(&vha->loop_state, LOOP_DOWN); 17608c2ecf20Sopenharmony_ci vha->hw->link_data_rate = (uint16_t)pinfo->link_config; 17618c2ecf20Sopenharmony_ci} 17628c2ecf20Sopenharmony_ci 17638c2ecf20Sopenharmony_cistatic void 17648c2ecf20Sopenharmony_ciqla2x00_fxdisc_iocb_timeout(void *data) 17658c2ecf20Sopenharmony_ci{ 17668c2ecf20Sopenharmony_ci srb_t *sp = data; 17678c2ecf20Sopenharmony_ci struct srb_iocb *lio = &sp->u.iocb_cmd; 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci complete(&lio->u.fxiocb.fxiocb_comp); 17708c2ecf20Sopenharmony_ci} 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_cistatic void qla2x00_fxdisc_sp_done(srb_t *sp, int res) 17738c2ecf20Sopenharmony_ci{ 17748c2ecf20Sopenharmony_ci struct srb_iocb *lio = &sp->u.iocb_cmd; 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci complete(&lio->u.fxiocb.fxiocb_comp); 17778c2ecf20Sopenharmony_ci} 17788c2ecf20Sopenharmony_ci 17798c2ecf20Sopenharmony_ciint 17808c2ecf20Sopenharmony_ciqlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) 17818c2ecf20Sopenharmony_ci{ 17828c2ecf20Sopenharmony_ci srb_t *sp; 17838c2ecf20Sopenharmony_ci struct srb_iocb *fdisc; 17848c2ecf20Sopenharmony_ci int rval = QLA_FUNCTION_FAILED; 17858c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 17868c2ecf20Sopenharmony_ci struct host_system_info *phost_info; 17878c2ecf20Sopenharmony_ci struct register_host_info *preg_hsi; 17888c2ecf20Sopenharmony_ci struct new_utsname *p_sysid = NULL; 17898c2ecf20Sopenharmony_ci 17908c2ecf20Sopenharmony_ci sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); 17918c2ecf20Sopenharmony_ci if (!sp) 17928c2ecf20Sopenharmony_ci goto done; 17938c2ecf20Sopenharmony_ci 17948c2ecf20Sopenharmony_ci sp->type = SRB_FXIOCB_DCMD; 17958c2ecf20Sopenharmony_ci sp->name = "fxdisc"; 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci fdisc = &sp->u.iocb_cmd; 17988c2ecf20Sopenharmony_ci fdisc->timeout = qla2x00_fxdisc_iocb_timeout; 17998c2ecf20Sopenharmony_ci qla2x00_init_timer(sp, FXDISC_TIMEOUT); 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ci switch (fx_type) { 18028c2ecf20Sopenharmony_ci case FXDISC_GET_CONFIG_INFO: 18038c2ecf20Sopenharmony_ci fdisc->u.fxiocb.flags = 18048c2ecf20Sopenharmony_ci SRB_FXDISC_RESP_DMA_VALID; 18058c2ecf20Sopenharmony_ci fdisc->u.fxiocb.rsp_len = sizeof(struct config_info_data); 18068c2ecf20Sopenharmony_ci break; 18078c2ecf20Sopenharmony_ci case FXDISC_GET_PORT_INFO: 18088c2ecf20Sopenharmony_ci fdisc->u.fxiocb.flags = 18098c2ecf20Sopenharmony_ci SRB_FXDISC_RESP_DMA_VALID | SRB_FXDISC_REQ_DWRD_VALID; 18108c2ecf20Sopenharmony_ci fdisc->u.fxiocb.rsp_len = QLAFX00_PORT_DATA_INFO; 18118c2ecf20Sopenharmony_ci fdisc->u.fxiocb.req_data = cpu_to_le32(fcport->port_id); 18128c2ecf20Sopenharmony_ci break; 18138c2ecf20Sopenharmony_ci case FXDISC_GET_TGT_NODE_INFO: 18148c2ecf20Sopenharmony_ci fdisc->u.fxiocb.flags = 18158c2ecf20Sopenharmony_ci SRB_FXDISC_RESP_DMA_VALID | SRB_FXDISC_REQ_DWRD_VALID; 18168c2ecf20Sopenharmony_ci fdisc->u.fxiocb.rsp_len = QLAFX00_TGT_NODE_INFO; 18178c2ecf20Sopenharmony_ci fdisc->u.fxiocb.req_data = cpu_to_le32(fcport->tgt_id); 18188c2ecf20Sopenharmony_ci break; 18198c2ecf20Sopenharmony_ci case FXDISC_GET_TGT_NODE_LIST: 18208c2ecf20Sopenharmony_ci fdisc->u.fxiocb.flags = 18218c2ecf20Sopenharmony_ci SRB_FXDISC_RESP_DMA_VALID | SRB_FXDISC_REQ_DWRD_VALID; 18228c2ecf20Sopenharmony_ci fdisc->u.fxiocb.rsp_len = QLAFX00_TGT_NODE_LIST_SIZE; 18238c2ecf20Sopenharmony_ci break; 18248c2ecf20Sopenharmony_ci case FXDISC_REG_HOST_INFO: 18258c2ecf20Sopenharmony_ci fdisc->u.fxiocb.flags = SRB_FXDISC_REQ_DMA_VALID; 18268c2ecf20Sopenharmony_ci fdisc->u.fxiocb.req_len = sizeof(struct register_host_info); 18278c2ecf20Sopenharmony_ci p_sysid = utsname(); 18288c2ecf20Sopenharmony_ci if (!p_sysid) { 18298c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x303c, 18308c2ecf20Sopenharmony_ci "Not able to get the system information\n"); 18318c2ecf20Sopenharmony_ci goto done_free_sp; 18328c2ecf20Sopenharmony_ci } 18338c2ecf20Sopenharmony_ci break; 18348c2ecf20Sopenharmony_ci case FXDISC_ABORT_IOCTL: 18358c2ecf20Sopenharmony_ci default: 18368c2ecf20Sopenharmony_ci break; 18378c2ecf20Sopenharmony_ci } 18388c2ecf20Sopenharmony_ci 18398c2ecf20Sopenharmony_ci if (fdisc->u.fxiocb.flags & SRB_FXDISC_REQ_DMA_VALID) { 18408c2ecf20Sopenharmony_ci fdisc->u.fxiocb.req_addr = dma_alloc_coherent(&ha->pdev->dev, 18418c2ecf20Sopenharmony_ci fdisc->u.fxiocb.req_len, 18428c2ecf20Sopenharmony_ci &fdisc->u.fxiocb.req_dma_handle, GFP_KERNEL); 18438c2ecf20Sopenharmony_ci if (!fdisc->u.fxiocb.req_addr) 18448c2ecf20Sopenharmony_ci goto done_free_sp; 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_ci if (fx_type == FXDISC_REG_HOST_INFO) { 18478c2ecf20Sopenharmony_ci preg_hsi = (struct register_host_info *) 18488c2ecf20Sopenharmony_ci fdisc->u.fxiocb.req_addr; 18498c2ecf20Sopenharmony_ci phost_info = &preg_hsi->hsi; 18508c2ecf20Sopenharmony_ci memset(preg_hsi, 0, sizeof(struct register_host_info)); 18518c2ecf20Sopenharmony_ci phost_info->os_type = OS_TYPE_LINUX; 18528c2ecf20Sopenharmony_ci strlcpy(phost_info->sysname, p_sysid->sysname, 18538c2ecf20Sopenharmony_ci sizeof(phost_info->sysname)); 18548c2ecf20Sopenharmony_ci strlcpy(phost_info->nodename, p_sysid->nodename, 18558c2ecf20Sopenharmony_ci sizeof(phost_info->nodename)); 18568c2ecf20Sopenharmony_ci if (!strcmp(phost_info->nodename, "(none)")) 18578c2ecf20Sopenharmony_ci ha->mr.host_info_resend = true; 18588c2ecf20Sopenharmony_ci strlcpy(phost_info->release, p_sysid->release, 18598c2ecf20Sopenharmony_ci sizeof(phost_info->release)); 18608c2ecf20Sopenharmony_ci strlcpy(phost_info->version, p_sysid->version, 18618c2ecf20Sopenharmony_ci sizeof(phost_info->version)); 18628c2ecf20Sopenharmony_ci strlcpy(phost_info->machine, p_sysid->machine, 18638c2ecf20Sopenharmony_ci sizeof(phost_info->machine)); 18648c2ecf20Sopenharmony_ci strlcpy(phost_info->domainname, p_sysid->domainname, 18658c2ecf20Sopenharmony_ci sizeof(phost_info->domainname)); 18668c2ecf20Sopenharmony_ci strlcpy(phost_info->hostdriver, QLA2XXX_VERSION, 18678c2ecf20Sopenharmony_ci sizeof(phost_info->hostdriver)); 18688c2ecf20Sopenharmony_ci preg_hsi->utc = (uint64_t)ktime_get_real_seconds(); 18698c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0149, 18708c2ecf20Sopenharmony_ci "ISP%04X: Host registration with firmware\n", 18718c2ecf20Sopenharmony_ci ha->pdev->device); 18728c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x014a, 18738c2ecf20Sopenharmony_ci "os_type = '%d', sysname = '%s', nodname = '%s'\n", 18748c2ecf20Sopenharmony_ci phost_info->os_type, 18758c2ecf20Sopenharmony_ci phost_info->sysname, 18768c2ecf20Sopenharmony_ci phost_info->nodename); 18778c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x014b, 18788c2ecf20Sopenharmony_ci "release = '%s', version = '%s'\n", 18798c2ecf20Sopenharmony_ci phost_info->release, 18808c2ecf20Sopenharmony_ci phost_info->version); 18818c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x014c, 18828c2ecf20Sopenharmony_ci "machine = '%s' " 18838c2ecf20Sopenharmony_ci "domainname = '%s', hostdriver = '%s'\n", 18848c2ecf20Sopenharmony_ci phost_info->machine, 18858c2ecf20Sopenharmony_ci phost_info->domainname, 18868c2ecf20Sopenharmony_ci phost_info->hostdriver); 18878c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_init + ql_dbg_disc, vha, 0x014d, 18888c2ecf20Sopenharmony_ci phost_info, sizeof(*phost_info)); 18898c2ecf20Sopenharmony_ci } 18908c2ecf20Sopenharmony_ci } 18918c2ecf20Sopenharmony_ci 18928c2ecf20Sopenharmony_ci if (fdisc->u.fxiocb.flags & SRB_FXDISC_RESP_DMA_VALID) { 18938c2ecf20Sopenharmony_ci fdisc->u.fxiocb.rsp_addr = dma_alloc_coherent(&ha->pdev->dev, 18948c2ecf20Sopenharmony_ci fdisc->u.fxiocb.rsp_len, 18958c2ecf20Sopenharmony_ci &fdisc->u.fxiocb.rsp_dma_handle, GFP_KERNEL); 18968c2ecf20Sopenharmony_ci if (!fdisc->u.fxiocb.rsp_addr) 18978c2ecf20Sopenharmony_ci goto done_unmap_req; 18988c2ecf20Sopenharmony_ci } 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_ci fdisc->u.fxiocb.req_func_type = cpu_to_le16(fx_type); 19018c2ecf20Sopenharmony_ci sp->done = qla2x00_fxdisc_sp_done; 19028c2ecf20Sopenharmony_ci 19038c2ecf20Sopenharmony_ci rval = qla2x00_start_sp(sp); 19048c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 19058c2ecf20Sopenharmony_ci goto done_unmap_dma; 19068c2ecf20Sopenharmony_ci 19078c2ecf20Sopenharmony_ci wait_for_completion(&fdisc->u.fxiocb.fxiocb_comp); 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci if (fx_type == FXDISC_GET_CONFIG_INFO) { 19108c2ecf20Sopenharmony_ci struct config_info_data *pinfo = 19118c2ecf20Sopenharmony_ci (struct config_info_data *) fdisc->u.fxiocb.rsp_addr; 19128c2ecf20Sopenharmony_ci strlcpy(vha->hw->model_number, pinfo->model_num, 19138c2ecf20Sopenharmony_ci ARRAY_SIZE(vha->hw->model_number)); 19148c2ecf20Sopenharmony_ci strlcpy(vha->hw->model_desc, pinfo->model_description, 19158c2ecf20Sopenharmony_ci ARRAY_SIZE(vha->hw->model_desc)); 19168c2ecf20Sopenharmony_ci memcpy(&vha->hw->mr.symbolic_name, pinfo->symbolic_name, 19178c2ecf20Sopenharmony_ci sizeof(vha->hw->mr.symbolic_name)); 19188c2ecf20Sopenharmony_ci memcpy(&vha->hw->mr.serial_num, pinfo->serial_num, 19198c2ecf20Sopenharmony_ci sizeof(vha->hw->mr.serial_num)); 19208c2ecf20Sopenharmony_ci memcpy(&vha->hw->mr.hw_version, pinfo->hw_version, 19218c2ecf20Sopenharmony_ci sizeof(vha->hw->mr.hw_version)); 19228c2ecf20Sopenharmony_ci memcpy(&vha->hw->mr.fw_version, pinfo->fw_version, 19238c2ecf20Sopenharmony_ci sizeof(vha->hw->mr.fw_version)); 19248c2ecf20Sopenharmony_ci strim(vha->hw->mr.fw_version); 19258c2ecf20Sopenharmony_ci memcpy(&vha->hw->mr.uboot_version, pinfo->uboot_version, 19268c2ecf20Sopenharmony_ci sizeof(vha->hw->mr.uboot_version)); 19278c2ecf20Sopenharmony_ci memcpy(&vha->hw->mr.fru_serial_num, pinfo->fru_serial_num, 19288c2ecf20Sopenharmony_ci sizeof(vha->hw->mr.fru_serial_num)); 19298c2ecf20Sopenharmony_ci vha->hw->mr.critical_temperature = 19308c2ecf20Sopenharmony_ci (pinfo->nominal_temp_value) ? 19318c2ecf20Sopenharmony_ci pinfo->nominal_temp_value : QLAFX00_CRITEMP_THRSHLD; 19328c2ecf20Sopenharmony_ci ha->mr.extended_io_enabled = (pinfo->enabled_capabilities & 19338c2ecf20Sopenharmony_ci QLAFX00_EXTENDED_IO_EN_MASK) != 0; 19348c2ecf20Sopenharmony_ci } else if (fx_type == FXDISC_GET_PORT_INFO) { 19358c2ecf20Sopenharmony_ci struct port_info_data *pinfo = 19368c2ecf20Sopenharmony_ci (struct port_info_data *) fdisc->u.fxiocb.rsp_addr; 19378c2ecf20Sopenharmony_ci memcpy(vha->node_name, pinfo->node_name, WWN_SIZE); 19388c2ecf20Sopenharmony_ci memcpy(vha->port_name, pinfo->port_name, WWN_SIZE); 19398c2ecf20Sopenharmony_ci vha->d_id.b.domain = pinfo->port_id[0]; 19408c2ecf20Sopenharmony_ci vha->d_id.b.area = pinfo->port_id[1]; 19418c2ecf20Sopenharmony_ci vha->d_id.b.al_pa = pinfo->port_id[2]; 19428c2ecf20Sopenharmony_ci qlafx00_update_host_attr(vha, pinfo); 19438c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0141, 19448c2ecf20Sopenharmony_ci pinfo, 16); 19458c2ecf20Sopenharmony_ci } else if (fx_type == FXDISC_GET_TGT_NODE_INFO) { 19468c2ecf20Sopenharmony_ci struct qlafx00_tgt_node_info *pinfo = 19478c2ecf20Sopenharmony_ci (struct qlafx00_tgt_node_info *) fdisc->u.fxiocb.rsp_addr; 19488c2ecf20Sopenharmony_ci memcpy(fcport->node_name, pinfo->tgt_node_wwnn, WWN_SIZE); 19498c2ecf20Sopenharmony_ci memcpy(fcport->port_name, pinfo->tgt_node_wwpn, WWN_SIZE); 19508c2ecf20Sopenharmony_ci fcport->port_type = FCT_TARGET; 19518c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0144, 19528c2ecf20Sopenharmony_ci pinfo, 16); 19538c2ecf20Sopenharmony_ci } else if (fx_type == FXDISC_GET_TGT_NODE_LIST) { 19548c2ecf20Sopenharmony_ci struct qlafx00_tgt_node_info *pinfo = 19558c2ecf20Sopenharmony_ci (struct qlafx00_tgt_node_info *) fdisc->u.fxiocb.rsp_addr; 19568c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0146, 19578c2ecf20Sopenharmony_ci pinfo, 16); 19588c2ecf20Sopenharmony_ci memcpy(vha->hw->gid_list, pinfo, QLAFX00_TGT_NODE_LIST_SIZE); 19598c2ecf20Sopenharmony_ci } else if (fx_type == FXDISC_ABORT_IOCTL) 19608c2ecf20Sopenharmony_ci fdisc->u.fxiocb.result = 19618c2ecf20Sopenharmony_ci (fdisc->u.fxiocb.result == 19628c2ecf20Sopenharmony_ci cpu_to_le32(QLAFX00_IOCTL_ICOB_ABORT_SUCCESS)) ? 19638c2ecf20Sopenharmony_ci cpu_to_le32(QLA_SUCCESS) : cpu_to_le32(QLA_FUNCTION_FAILED); 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci rval = le32_to_cpu(fdisc->u.fxiocb.result); 19668c2ecf20Sopenharmony_ci 19678c2ecf20Sopenharmony_cidone_unmap_dma: 19688c2ecf20Sopenharmony_ci if (fdisc->u.fxiocb.rsp_addr) 19698c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, fdisc->u.fxiocb.rsp_len, 19708c2ecf20Sopenharmony_ci fdisc->u.fxiocb.rsp_addr, fdisc->u.fxiocb.rsp_dma_handle); 19718c2ecf20Sopenharmony_ci 19728c2ecf20Sopenharmony_cidone_unmap_req: 19738c2ecf20Sopenharmony_ci if (fdisc->u.fxiocb.req_addr) 19748c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, fdisc->u.fxiocb.req_len, 19758c2ecf20Sopenharmony_ci fdisc->u.fxiocb.req_addr, fdisc->u.fxiocb.req_dma_handle); 19768c2ecf20Sopenharmony_cidone_free_sp: 19778c2ecf20Sopenharmony_ci sp->free(sp); 19788c2ecf20Sopenharmony_cidone: 19798c2ecf20Sopenharmony_ci return rval; 19808c2ecf20Sopenharmony_ci} 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_ci/* 19838c2ecf20Sopenharmony_ci * qlafx00_initialize_adapter 19848c2ecf20Sopenharmony_ci * Initialize board. 19858c2ecf20Sopenharmony_ci * 19868c2ecf20Sopenharmony_ci * Input: 19878c2ecf20Sopenharmony_ci * ha = adapter block pointer. 19888c2ecf20Sopenharmony_ci * 19898c2ecf20Sopenharmony_ci * Returns: 19908c2ecf20Sopenharmony_ci * 0 = success 19918c2ecf20Sopenharmony_ci */ 19928c2ecf20Sopenharmony_ciint 19938c2ecf20Sopenharmony_ciqlafx00_initialize_adapter(scsi_qla_host_t *vha) 19948c2ecf20Sopenharmony_ci{ 19958c2ecf20Sopenharmony_ci int rval; 19968c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 19978c2ecf20Sopenharmony_ci uint32_t tempc; 19988c2ecf20Sopenharmony_ci 19998c2ecf20Sopenharmony_ci /* Clear adapter flags. */ 20008c2ecf20Sopenharmony_ci vha->flags.online = 0; 20018c2ecf20Sopenharmony_ci ha->flags.chip_reset_done = 0; 20028c2ecf20Sopenharmony_ci vha->flags.reset_active = 0; 20038c2ecf20Sopenharmony_ci ha->flags.pci_channel_io_perm_failure = 0; 20048c2ecf20Sopenharmony_ci ha->flags.eeh_busy = 0; 20058c2ecf20Sopenharmony_ci atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); 20068c2ecf20Sopenharmony_ci atomic_set(&vha->loop_state, LOOP_DOWN); 20078c2ecf20Sopenharmony_ci vha->device_flags = DFLG_NO_CABLE; 20088c2ecf20Sopenharmony_ci vha->dpc_flags = 0; 20098c2ecf20Sopenharmony_ci vha->flags.management_server_logged_in = 0; 20108c2ecf20Sopenharmony_ci ha->isp_abort_cnt = 0; 20118c2ecf20Sopenharmony_ci ha->beacon_blink_led = 0; 20128c2ecf20Sopenharmony_ci 20138c2ecf20Sopenharmony_ci set_bit(0, ha->req_qid_map); 20148c2ecf20Sopenharmony_ci set_bit(0, ha->rsp_qid_map); 20158c2ecf20Sopenharmony_ci 20168c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0147, 20178c2ecf20Sopenharmony_ci "Configuring PCI space...\n"); 20188c2ecf20Sopenharmony_ci 20198c2ecf20Sopenharmony_ci rval = ha->isp_ops->pci_config(vha); 20208c2ecf20Sopenharmony_ci if (rval) { 20218c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x0148, 20228c2ecf20Sopenharmony_ci "Unable to configure PCI space.\n"); 20238c2ecf20Sopenharmony_ci return rval; 20248c2ecf20Sopenharmony_ci } 20258c2ecf20Sopenharmony_ci 20268c2ecf20Sopenharmony_ci rval = qlafx00_init_fw_ready(vha); 20278c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 20288c2ecf20Sopenharmony_ci return rval; 20298c2ecf20Sopenharmony_ci 20308c2ecf20Sopenharmony_ci qlafx00_save_queue_ptrs(vha); 20318c2ecf20Sopenharmony_ci 20328c2ecf20Sopenharmony_ci rval = qlafx00_config_queues(vha); 20338c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 20348c2ecf20Sopenharmony_ci return rval; 20358c2ecf20Sopenharmony_ci 20368c2ecf20Sopenharmony_ci /* 20378c2ecf20Sopenharmony_ci * Allocate the array of outstanding commands 20388c2ecf20Sopenharmony_ci * now that we know the firmware resources. 20398c2ecf20Sopenharmony_ci */ 20408c2ecf20Sopenharmony_ci rval = qla2x00_alloc_outstanding_cmds(ha, vha->req); 20418c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 20428c2ecf20Sopenharmony_ci return rval; 20438c2ecf20Sopenharmony_ci 20448c2ecf20Sopenharmony_ci rval = qla2x00_init_rings(vha); 20458c2ecf20Sopenharmony_ci ha->flags.chip_reset_done = 1; 20468c2ecf20Sopenharmony_ci 20478c2ecf20Sopenharmony_ci tempc = QLAFX00_GET_TEMPERATURE(ha); 20488c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0152, 20498c2ecf20Sopenharmony_ci "ISPFx00(%s): Critical temp timer, current SOC temperature: 0x%x\n", 20508c2ecf20Sopenharmony_ci __func__, tempc); 20518c2ecf20Sopenharmony_ci 20528c2ecf20Sopenharmony_ci return rval; 20538c2ecf20Sopenharmony_ci} 20548c2ecf20Sopenharmony_ci 20558c2ecf20Sopenharmony_ciuint32_t 20568c2ecf20Sopenharmony_ciqlafx00_fw_state_show(struct device *dev, struct device_attribute *attr, 20578c2ecf20Sopenharmony_ci char *buf) 20588c2ecf20Sopenharmony_ci{ 20598c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 20608c2ecf20Sopenharmony_ci int rval = QLA_FUNCTION_FAILED; 20618c2ecf20Sopenharmony_ci uint32_t state[1]; 20628c2ecf20Sopenharmony_ci 20638c2ecf20Sopenharmony_ci if (qla2x00_reset_active(vha)) 20648c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x70ce, 20658c2ecf20Sopenharmony_ci "ISP reset active.\n"); 20668c2ecf20Sopenharmony_ci else if (!vha->hw->flags.eeh_busy) { 20678c2ecf20Sopenharmony_ci rval = qlafx00_get_firmware_state(vha, state); 20688c2ecf20Sopenharmony_ci } 20698c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 20708c2ecf20Sopenharmony_ci memset(state, -1, sizeof(state)); 20718c2ecf20Sopenharmony_ci 20728c2ecf20Sopenharmony_ci return state[0]; 20738c2ecf20Sopenharmony_ci} 20748c2ecf20Sopenharmony_ci 20758c2ecf20Sopenharmony_civoid 20768c2ecf20Sopenharmony_ciqlafx00_get_host_speed(struct Scsi_Host *shost) 20778c2ecf20Sopenharmony_ci{ 20788c2ecf20Sopenharmony_ci struct qla_hw_data *ha = ((struct scsi_qla_host *) 20798c2ecf20Sopenharmony_ci (shost_priv(shost)))->hw; 20808c2ecf20Sopenharmony_ci u32 speed = FC_PORTSPEED_UNKNOWN; 20818c2ecf20Sopenharmony_ci 20828c2ecf20Sopenharmony_ci switch (ha->link_data_rate) { 20838c2ecf20Sopenharmony_ci case QLAFX00_PORT_SPEED_2G: 20848c2ecf20Sopenharmony_ci speed = FC_PORTSPEED_2GBIT; 20858c2ecf20Sopenharmony_ci break; 20868c2ecf20Sopenharmony_ci case QLAFX00_PORT_SPEED_4G: 20878c2ecf20Sopenharmony_ci speed = FC_PORTSPEED_4GBIT; 20888c2ecf20Sopenharmony_ci break; 20898c2ecf20Sopenharmony_ci case QLAFX00_PORT_SPEED_8G: 20908c2ecf20Sopenharmony_ci speed = FC_PORTSPEED_8GBIT; 20918c2ecf20Sopenharmony_ci break; 20928c2ecf20Sopenharmony_ci case QLAFX00_PORT_SPEED_10G: 20938c2ecf20Sopenharmony_ci speed = FC_PORTSPEED_10GBIT; 20948c2ecf20Sopenharmony_ci break; 20958c2ecf20Sopenharmony_ci } 20968c2ecf20Sopenharmony_ci fc_host_speed(shost) = speed; 20978c2ecf20Sopenharmony_ci} 20988c2ecf20Sopenharmony_ci 20998c2ecf20Sopenharmony_ci/** QLAFX00 specific ISR implementation functions */ 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_cistatic inline void 21028c2ecf20Sopenharmony_ciqlafx00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len, 21038c2ecf20Sopenharmony_ci uint32_t sense_len, struct rsp_que *rsp, int res) 21048c2ecf20Sopenharmony_ci{ 21058c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = sp->vha; 21068c2ecf20Sopenharmony_ci struct scsi_cmnd *cp = GET_CMD_SP(sp); 21078c2ecf20Sopenharmony_ci uint32_t track_sense_len; 21088c2ecf20Sopenharmony_ci 21098c2ecf20Sopenharmony_ci SET_FW_SENSE_LEN(sp, sense_len); 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci if (sense_len >= SCSI_SENSE_BUFFERSIZE) 21128c2ecf20Sopenharmony_ci sense_len = SCSI_SENSE_BUFFERSIZE; 21138c2ecf20Sopenharmony_ci 21148c2ecf20Sopenharmony_ci SET_CMD_SENSE_LEN(sp, sense_len); 21158c2ecf20Sopenharmony_ci SET_CMD_SENSE_PTR(sp, cp->sense_buffer); 21168c2ecf20Sopenharmony_ci track_sense_len = sense_len; 21178c2ecf20Sopenharmony_ci 21188c2ecf20Sopenharmony_ci if (sense_len > par_sense_len) 21198c2ecf20Sopenharmony_ci sense_len = par_sense_len; 21208c2ecf20Sopenharmony_ci 21218c2ecf20Sopenharmony_ci memcpy(cp->sense_buffer, sense_data, sense_len); 21228c2ecf20Sopenharmony_ci 21238c2ecf20Sopenharmony_ci SET_FW_SENSE_LEN(sp, GET_FW_SENSE_LEN(sp) - sense_len); 21248c2ecf20Sopenharmony_ci 21258c2ecf20Sopenharmony_ci SET_CMD_SENSE_PTR(sp, cp->sense_buffer + sense_len); 21268c2ecf20Sopenharmony_ci track_sense_len -= sense_len; 21278c2ecf20Sopenharmony_ci SET_CMD_SENSE_LEN(sp, track_sense_len); 21288c2ecf20Sopenharmony_ci 21298c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, vha, 0x304d, 21308c2ecf20Sopenharmony_ci "sense_len=0x%x par_sense_len=0x%x track_sense_len=0x%x.\n", 21318c2ecf20Sopenharmony_ci sense_len, par_sense_len, track_sense_len); 21328c2ecf20Sopenharmony_ci if (GET_FW_SENSE_LEN(sp) > 0) { 21338c2ecf20Sopenharmony_ci rsp->status_srb = sp; 21348c2ecf20Sopenharmony_ci cp->result = res; 21358c2ecf20Sopenharmony_ci } 21368c2ecf20Sopenharmony_ci 21378c2ecf20Sopenharmony_ci if (sense_len) { 21388c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3039, 21398c2ecf20Sopenharmony_ci "Check condition Sense data, nexus%ld:%d:%llu cmd=%p.\n", 21408c2ecf20Sopenharmony_ci sp->vha->host_no, cp->device->id, cp->device->lun, 21418c2ecf20Sopenharmony_ci cp); 21428c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x3049, 21438c2ecf20Sopenharmony_ci cp->sense_buffer, sense_len); 21448c2ecf20Sopenharmony_ci } 21458c2ecf20Sopenharmony_ci} 21468c2ecf20Sopenharmony_ci 21478c2ecf20Sopenharmony_cistatic void 21488c2ecf20Sopenharmony_ciqlafx00_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, 21498c2ecf20Sopenharmony_ci struct tsk_mgmt_entry_fx00 *pkt, srb_t *sp, 21508c2ecf20Sopenharmony_ci __le16 sstatus, __le16 cpstatus) 21518c2ecf20Sopenharmony_ci{ 21528c2ecf20Sopenharmony_ci struct srb_iocb *tmf; 21538c2ecf20Sopenharmony_ci 21548c2ecf20Sopenharmony_ci tmf = &sp->u.iocb_cmd; 21558c2ecf20Sopenharmony_ci if (cpstatus != cpu_to_le16((uint16_t)CS_COMPLETE) || 21568c2ecf20Sopenharmony_ci (sstatus & cpu_to_le16((uint16_t)SS_RESPONSE_INFO_LEN_VALID))) 21578c2ecf20Sopenharmony_ci cpstatus = cpu_to_le16((uint16_t)CS_INCOMPLETE); 21588c2ecf20Sopenharmony_ci tmf->u.tmf.comp_status = cpstatus; 21598c2ecf20Sopenharmony_ci sp->done(sp, 0); 21608c2ecf20Sopenharmony_ci} 21618c2ecf20Sopenharmony_ci 21628c2ecf20Sopenharmony_cistatic void 21638c2ecf20Sopenharmony_ciqlafx00_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, 21648c2ecf20Sopenharmony_ci struct abort_iocb_entry_fx00 *pkt) 21658c2ecf20Sopenharmony_ci{ 21668c2ecf20Sopenharmony_ci const char func[] = "ABT_IOCB"; 21678c2ecf20Sopenharmony_ci srb_t *sp; 21688c2ecf20Sopenharmony_ci struct srb_iocb *abt; 21698c2ecf20Sopenharmony_ci 21708c2ecf20Sopenharmony_ci sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); 21718c2ecf20Sopenharmony_ci if (!sp) 21728c2ecf20Sopenharmony_ci return; 21738c2ecf20Sopenharmony_ci 21748c2ecf20Sopenharmony_ci abt = &sp->u.iocb_cmd; 21758c2ecf20Sopenharmony_ci abt->u.abt.comp_status = pkt->tgt_id_sts; 21768c2ecf20Sopenharmony_ci sp->done(sp, 0); 21778c2ecf20Sopenharmony_ci} 21788c2ecf20Sopenharmony_ci 21798c2ecf20Sopenharmony_cistatic void 21808c2ecf20Sopenharmony_ciqlafx00_ioctl_iosb_entry(scsi_qla_host_t *vha, struct req_que *req, 21818c2ecf20Sopenharmony_ci struct ioctl_iocb_entry_fx00 *pkt) 21828c2ecf20Sopenharmony_ci{ 21838c2ecf20Sopenharmony_ci const char func[] = "IOSB_IOCB"; 21848c2ecf20Sopenharmony_ci srb_t *sp; 21858c2ecf20Sopenharmony_ci struct bsg_job *bsg_job; 21868c2ecf20Sopenharmony_ci struct fc_bsg_reply *bsg_reply; 21878c2ecf20Sopenharmony_ci struct srb_iocb *iocb_job; 21888c2ecf20Sopenharmony_ci int res = 0; 21898c2ecf20Sopenharmony_ci struct qla_mt_iocb_rsp_fx00 fstatus; 21908c2ecf20Sopenharmony_ci uint8_t *fw_sts_ptr; 21918c2ecf20Sopenharmony_ci 21928c2ecf20Sopenharmony_ci sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); 21938c2ecf20Sopenharmony_ci if (!sp) 21948c2ecf20Sopenharmony_ci return; 21958c2ecf20Sopenharmony_ci 21968c2ecf20Sopenharmony_ci if (sp->type == SRB_FXIOCB_DCMD) { 21978c2ecf20Sopenharmony_ci iocb_job = &sp->u.iocb_cmd; 21988c2ecf20Sopenharmony_ci iocb_job->u.fxiocb.seq_number = pkt->seq_no; 21998c2ecf20Sopenharmony_ci iocb_job->u.fxiocb.fw_flags = pkt->fw_iotcl_flags; 22008c2ecf20Sopenharmony_ci iocb_job->u.fxiocb.result = pkt->status; 22018c2ecf20Sopenharmony_ci if (iocb_job->u.fxiocb.flags & SRB_FXDISC_RSP_DWRD_VALID) 22028c2ecf20Sopenharmony_ci iocb_job->u.fxiocb.req_data = 22038c2ecf20Sopenharmony_ci pkt->dataword_r; 22048c2ecf20Sopenharmony_ci } else { 22058c2ecf20Sopenharmony_ci bsg_job = sp->u.bsg_job; 22068c2ecf20Sopenharmony_ci bsg_reply = bsg_job->reply; 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_ci memset(&fstatus, 0, sizeof(struct qla_mt_iocb_rsp_fx00)); 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_ci fstatus.reserved_1 = pkt->reserved_0; 22118c2ecf20Sopenharmony_ci fstatus.func_type = pkt->comp_func_num; 22128c2ecf20Sopenharmony_ci fstatus.ioctl_flags = pkt->fw_iotcl_flags; 22138c2ecf20Sopenharmony_ci fstatus.ioctl_data = pkt->dataword_r; 22148c2ecf20Sopenharmony_ci fstatus.adapid = pkt->adapid; 22158c2ecf20Sopenharmony_ci fstatus.reserved_2 = pkt->dataword_r_extra; 22168c2ecf20Sopenharmony_ci fstatus.res_count = pkt->residuallen; 22178c2ecf20Sopenharmony_ci fstatus.status = pkt->status; 22188c2ecf20Sopenharmony_ci fstatus.seq_number = pkt->seq_no; 22198c2ecf20Sopenharmony_ci memcpy(fstatus.reserved_3, 22208c2ecf20Sopenharmony_ci pkt->reserved_2, 20 * sizeof(uint8_t)); 22218c2ecf20Sopenharmony_ci 22228c2ecf20Sopenharmony_ci fw_sts_ptr = bsg_job->reply + sizeof(struct fc_bsg_reply); 22238c2ecf20Sopenharmony_ci 22248c2ecf20Sopenharmony_ci memcpy(fw_sts_ptr, &fstatus, sizeof(fstatus)); 22258c2ecf20Sopenharmony_ci bsg_job->reply_len = sizeof(struct fc_bsg_reply) + 22268c2ecf20Sopenharmony_ci sizeof(struct qla_mt_iocb_rsp_fx00) + sizeof(uint8_t); 22278c2ecf20Sopenharmony_ci 22288c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, 22298c2ecf20Sopenharmony_ci sp->vha, 0x5080, pkt, sizeof(*pkt)); 22308c2ecf20Sopenharmony_ci 22318c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, 22328c2ecf20Sopenharmony_ci sp->vha, 0x5074, 22338c2ecf20Sopenharmony_ci fw_sts_ptr, sizeof(fstatus)); 22348c2ecf20Sopenharmony_ci 22358c2ecf20Sopenharmony_ci res = bsg_reply->result = DID_OK << 16; 22368c2ecf20Sopenharmony_ci bsg_reply->reply_payload_rcv_len = 22378c2ecf20Sopenharmony_ci bsg_job->reply_payload.payload_len; 22388c2ecf20Sopenharmony_ci } 22398c2ecf20Sopenharmony_ci sp->done(sp, res); 22408c2ecf20Sopenharmony_ci} 22418c2ecf20Sopenharmony_ci 22428c2ecf20Sopenharmony_ci/** 22438c2ecf20Sopenharmony_ci * qlafx00_status_entry() - Process a Status IOCB entry. 22448c2ecf20Sopenharmony_ci * @vha: SCSI driver HA context 22458c2ecf20Sopenharmony_ci * @rsp: response queue 22468c2ecf20Sopenharmony_ci * @pkt: Entry pointer 22478c2ecf20Sopenharmony_ci */ 22488c2ecf20Sopenharmony_cistatic void 22498c2ecf20Sopenharmony_ciqlafx00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) 22508c2ecf20Sopenharmony_ci{ 22518c2ecf20Sopenharmony_ci srb_t *sp; 22528c2ecf20Sopenharmony_ci fc_port_t *fcport; 22538c2ecf20Sopenharmony_ci struct scsi_cmnd *cp; 22548c2ecf20Sopenharmony_ci struct sts_entry_fx00 *sts; 22558c2ecf20Sopenharmony_ci __le16 comp_status; 22568c2ecf20Sopenharmony_ci __le16 scsi_status; 22578c2ecf20Sopenharmony_ci __le16 lscsi_status; 22588c2ecf20Sopenharmony_ci int32_t resid; 22598c2ecf20Sopenharmony_ci uint32_t sense_len, par_sense_len, rsp_info_len, resid_len, 22608c2ecf20Sopenharmony_ci fw_resid_len; 22618c2ecf20Sopenharmony_ci uint8_t *rsp_info = NULL, *sense_data = NULL; 22628c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 22638c2ecf20Sopenharmony_ci uint32_t hindex, handle; 22648c2ecf20Sopenharmony_ci uint16_t que; 22658c2ecf20Sopenharmony_ci struct req_que *req; 22668c2ecf20Sopenharmony_ci int logit = 1; 22678c2ecf20Sopenharmony_ci int res = 0; 22688c2ecf20Sopenharmony_ci 22698c2ecf20Sopenharmony_ci sts = (struct sts_entry_fx00 *) pkt; 22708c2ecf20Sopenharmony_ci 22718c2ecf20Sopenharmony_ci comp_status = sts->comp_status; 22728c2ecf20Sopenharmony_ci scsi_status = sts->scsi_status & cpu_to_le16((uint16_t)SS_MASK); 22738c2ecf20Sopenharmony_ci hindex = sts->handle; 22748c2ecf20Sopenharmony_ci handle = LSW(hindex); 22758c2ecf20Sopenharmony_ci 22768c2ecf20Sopenharmony_ci que = MSW(hindex); 22778c2ecf20Sopenharmony_ci req = ha->req_q_map[que]; 22788c2ecf20Sopenharmony_ci 22798c2ecf20Sopenharmony_ci /* Validate handle. */ 22808c2ecf20Sopenharmony_ci if (handle < req->num_outstanding_cmds) 22818c2ecf20Sopenharmony_ci sp = req->outstanding_cmds[handle]; 22828c2ecf20Sopenharmony_ci else 22838c2ecf20Sopenharmony_ci sp = NULL; 22848c2ecf20Sopenharmony_ci 22858c2ecf20Sopenharmony_ci if (sp == NULL) { 22868c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, vha, 0x3034, 22878c2ecf20Sopenharmony_ci "Invalid status handle (0x%x).\n", handle); 22888c2ecf20Sopenharmony_ci 22898c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 22908c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 22918c2ecf20Sopenharmony_ci return; 22928c2ecf20Sopenharmony_ci } 22938c2ecf20Sopenharmony_ci 22948c2ecf20Sopenharmony_ci if (sp->type == SRB_TM_CMD) { 22958c2ecf20Sopenharmony_ci req->outstanding_cmds[handle] = NULL; 22968c2ecf20Sopenharmony_ci qlafx00_tm_iocb_entry(vha, req, pkt, sp, 22978c2ecf20Sopenharmony_ci scsi_status, comp_status); 22988c2ecf20Sopenharmony_ci return; 22998c2ecf20Sopenharmony_ci } 23008c2ecf20Sopenharmony_ci 23018c2ecf20Sopenharmony_ci /* Fast path completion. */ 23028c2ecf20Sopenharmony_ci if (comp_status == CS_COMPLETE && scsi_status == 0) { 23038c2ecf20Sopenharmony_ci qla2x00_process_completed_request(vha, req, handle); 23048c2ecf20Sopenharmony_ci return; 23058c2ecf20Sopenharmony_ci } 23068c2ecf20Sopenharmony_ci 23078c2ecf20Sopenharmony_ci req->outstanding_cmds[handle] = NULL; 23088c2ecf20Sopenharmony_ci cp = GET_CMD_SP(sp); 23098c2ecf20Sopenharmony_ci if (cp == NULL) { 23108c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, vha, 0x3048, 23118c2ecf20Sopenharmony_ci "Command already returned (0x%x/%p).\n", 23128c2ecf20Sopenharmony_ci handle, sp); 23138c2ecf20Sopenharmony_ci 23148c2ecf20Sopenharmony_ci return; 23158c2ecf20Sopenharmony_ci } 23168c2ecf20Sopenharmony_ci 23178c2ecf20Sopenharmony_ci lscsi_status = scsi_status & cpu_to_le16((uint16_t)STATUS_MASK); 23188c2ecf20Sopenharmony_ci 23198c2ecf20Sopenharmony_ci fcport = sp->fcport; 23208c2ecf20Sopenharmony_ci 23218c2ecf20Sopenharmony_ci sense_len = par_sense_len = rsp_info_len = resid_len = 23228c2ecf20Sopenharmony_ci fw_resid_len = 0; 23238c2ecf20Sopenharmony_ci if (scsi_status & cpu_to_le16((uint16_t)SS_SENSE_LEN_VALID)) 23248c2ecf20Sopenharmony_ci sense_len = sts->sense_len; 23258c2ecf20Sopenharmony_ci if (scsi_status & cpu_to_le16(((uint16_t)SS_RESIDUAL_UNDER 23268c2ecf20Sopenharmony_ci | (uint16_t)SS_RESIDUAL_OVER))) 23278c2ecf20Sopenharmony_ci resid_len = le32_to_cpu(sts->residual_len); 23288c2ecf20Sopenharmony_ci if (comp_status == cpu_to_le16((uint16_t)CS_DATA_UNDERRUN)) 23298c2ecf20Sopenharmony_ci fw_resid_len = le32_to_cpu(sts->residual_len); 23308c2ecf20Sopenharmony_ci rsp_info = sense_data = sts->data; 23318c2ecf20Sopenharmony_ci par_sense_len = sizeof(sts->data); 23328c2ecf20Sopenharmony_ci 23338c2ecf20Sopenharmony_ci /* Check for overrun. */ 23348c2ecf20Sopenharmony_ci if (comp_status == CS_COMPLETE && 23358c2ecf20Sopenharmony_ci scsi_status & cpu_to_le16((uint16_t)SS_RESIDUAL_OVER)) 23368c2ecf20Sopenharmony_ci comp_status = cpu_to_le16((uint16_t)CS_DATA_OVERRUN); 23378c2ecf20Sopenharmony_ci 23388c2ecf20Sopenharmony_ci /* 23398c2ecf20Sopenharmony_ci * Based on Host and scsi status generate status code for Linux 23408c2ecf20Sopenharmony_ci */ 23418c2ecf20Sopenharmony_ci switch (le16_to_cpu(comp_status)) { 23428c2ecf20Sopenharmony_ci case CS_COMPLETE: 23438c2ecf20Sopenharmony_ci case CS_QUEUE_FULL: 23448c2ecf20Sopenharmony_ci if (scsi_status == 0) { 23458c2ecf20Sopenharmony_ci res = DID_OK << 16; 23468c2ecf20Sopenharmony_ci break; 23478c2ecf20Sopenharmony_ci } 23488c2ecf20Sopenharmony_ci if (scsi_status & cpu_to_le16(((uint16_t)SS_RESIDUAL_UNDER 23498c2ecf20Sopenharmony_ci | (uint16_t)SS_RESIDUAL_OVER))) { 23508c2ecf20Sopenharmony_ci resid = resid_len; 23518c2ecf20Sopenharmony_ci scsi_set_resid(cp, resid); 23528c2ecf20Sopenharmony_ci 23538c2ecf20Sopenharmony_ci if (!lscsi_status && 23548c2ecf20Sopenharmony_ci ((unsigned)(scsi_bufflen(cp) - resid) < 23558c2ecf20Sopenharmony_ci cp->underflow)) { 23568c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, fcport->vha, 0x3050, 23578c2ecf20Sopenharmony_ci "Mid-layer underflow " 23588c2ecf20Sopenharmony_ci "detected (0x%x of 0x%x bytes).\n", 23598c2ecf20Sopenharmony_ci resid, scsi_bufflen(cp)); 23608c2ecf20Sopenharmony_ci 23618c2ecf20Sopenharmony_ci res = DID_ERROR << 16; 23628c2ecf20Sopenharmony_ci break; 23638c2ecf20Sopenharmony_ci } 23648c2ecf20Sopenharmony_ci } 23658c2ecf20Sopenharmony_ci res = DID_OK << 16 | le16_to_cpu(lscsi_status); 23668c2ecf20Sopenharmony_ci 23678c2ecf20Sopenharmony_ci if (lscsi_status == 23688c2ecf20Sopenharmony_ci cpu_to_le16((uint16_t)SAM_STAT_TASK_SET_FULL)) { 23698c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, fcport->vha, 0x3051, 23708c2ecf20Sopenharmony_ci "QUEUE FULL detected.\n"); 23718c2ecf20Sopenharmony_ci break; 23728c2ecf20Sopenharmony_ci } 23738c2ecf20Sopenharmony_ci logit = 0; 23748c2ecf20Sopenharmony_ci if (lscsi_status != cpu_to_le16((uint16_t)SS_CHECK_CONDITION)) 23758c2ecf20Sopenharmony_ci break; 23768c2ecf20Sopenharmony_ci 23778c2ecf20Sopenharmony_ci memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); 23788c2ecf20Sopenharmony_ci if (!(scsi_status & cpu_to_le16((uint16_t)SS_SENSE_LEN_VALID))) 23798c2ecf20Sopenharmony_ci break; 23808c2ecf20Sopenharmony_ci 23818c2ecf20Sopenharmony_ci qlafx00_handle_sense(sp, sense_data, par_sense_len, sense_len, 23828c2ecf20Sopenharmony_ci rsp, res); 23838c2ecf20Sopenharmony_ci break; 23848c2ecf20Sopenharmony_ci 23858c2ecf20Sopenharmony_ci case CS_DATA_UNDERRUN: 23868c2ecf20Sopenharmony_ci /* Use F/W calculated residual length. */ 23878c2ecf20Sopenharmony_ci if (IS_FWI2_CAPABLE(ha) || IS_QLAFX00(ha)) 23888c2ecf20Sopenharmony_ci resid = fw_resid_len; 23898c2ecf20Sopenharmony_ci else 23908c2ecf20Sopenharmony_ci resid = resid_len; 23918c2ecf20Sopenharmony_ci scsi_set_resid(cp, resid); 23928c2ecf20Sopenharmony_ci if (scsi_status & cpu_to_le16((uint16_t)SS_RESIDUAL_UNDER)) { 23938c2ecf20Sopenharmony_ci if ((IS_FWI2_CAPABLE(ha) || IS_QLAFX00(ha)) 23948c2ecf20Sopenharmony_ci && fw_resid_len != resid_len) { 23958c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, fcport->vha, 0x3052, 23968c2ecf20Sopenharmony_ci "Dropped frame(s) detected " 23978c2ecf20Sopenharmony_ci "(0x%x of 0x%x bytes).\n", 23988c2ecf20Sopenharmony_ci resid, scsi_bufflen(cp)); 23998c2ecf20Sopenharmony_ci 24008c2ecf20Sopenharmony_ci res = DID_ERROR << 16 | 24018c2ecf20Sopenharmony_ci le16_to_cpu(lscsi_status); 24028c2ecf20Sopenharmony_ci goto check_scsi_status; 24038c2ecf20Sopenharmony_ci } 24048c2ecf20Sopenharmony_ci 24058c2ecf20Sopenharmony_ci if (!lscsi_status && 24068c2ecf20Sopenharmony_ci ((unsigned)(scsi_bufflen(cp) - resid) < 24078c2ecf20Sopenharmony_ci cp->underflow)) { 24088c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, fcport->vha, 0x3053, 24098c2ecf20Sopenharmony_ci "Mid-layer underflow " 24108c2ecf20Sopenharmony_ci "detected (0x%x of 0x%x bytes, " 24118c2ecf20Sopenharmony_ci "cp->underflow: 0x%x).\n", 24128c2ecf20Sopenharmony_ci resid, scsi_bufflen(cp), cp->underflow); 24138c2ecf20Sopenharmony_ci 24148c2ecf20Sopenharmony_ci res = DID_ERROR << 16; 24158c2ecf20Sopenharmony_ci break; 24168c2ecf20Sopenharmony_ci } 24178c2ecf20Sopenharmony_ci } else if (lscsi_status != 24188c2ecf20Sopenharmony_ci cpu_to_le16((uint16_t)SAM_STAT_TASK_SET_FULL) && 24198c2ecf20Sopenharmony_ci lscsi_status != cpu_to_le16((uint16_t)SAM_STAT_BUSY)) { 24208c2ecf20Sopenharmony_ci /* 24218c2ecf20Sopenharmony_ci * scsi status of task set and busy are considered 24228c2ecf20Sopenharmony_ci * to be task not completed. 24238c2ecf20Sopenharmony_ci */ 24248c2ecf20Sopenharmony_ci 24258c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, fcport->vha, 0x3054, 24268c2ecf20Sopenharmony_ci "Dropped frame(s) detected (0x%x " 24278c2ecf20Sopenharmony_ci "of 0x%x bytes).\n", resid, 24288c2ecf20Sopenharmony_ci scsi_bufflen(cp)); 24298c2ecf20Sopenharmony_ci 24308c2ecf20Sopenharmony_ci res = DID_ERROR << 16 | le16_to_cpu(lscsi_status); 24318c2ecf20Sopenharmony_ci goto check_scsi_status; 24328c2ecf20Sopenharmony_ci } else { 24338c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, fcport->vha, 0x3055, 24348c2ecf20Sopenharmony_ci "scsi_status: 0x%x, lscsi_status: 0x%x\n", 24358c2ecf20Sopenharmony_ci scsi_status, lscsi_status); 24368c2ecf20Sopenharmony_ci } 24378c2ecf20Sopenharmony_ci 24388c2ecf20Sopenharmony_ci res = DID_OK << 16 | le16_to_cpu(lscsi_status); 24398c2ecf20Sopenharmony_ci logit = 0; 24408c2ecf20Sopenharmony_ci 24418c2ecf20Sopenharmony_cicheck_scsi_status: 24428c2ecf20Sopenharmony_ci /* 24438c2ecf20Sopenharmony_ci * Check to see if SCSI Status is non zero. If so report SCSI 24448c2ecf20Sopenharmony_ci * Status. 24458c2ecf20Sopenharmony_ci */ 24468c2ecf20Sopenharmony_ci if (lscsi_status != 0) { 24478c2ecf20Sopenharmony_ci if (lscsi_status == 24488c2ecf20Sopenharmony_ci cpu_to_le16((uint16_t)SAM_STAT_TASK_SET_FULL)) { 24498c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, fcport->vha, 0x3056, 24508c2ecf20Sopenharmony_ci "QUEUE FULL detected.\n"); 24518c2ecf20Sopenharmony_ci logit = 1; 24528c2ecf20Sopenharmony_ci break; 24538c2ecf20Sopenharmony_ci } 24548c2ecf20Sopenharmony_ci if (lscsi_status != 24558c2ecf20Sopenharmony_ci cpu_to_le16((uint16_t)SS_CHECK_CONDITION)) 24568c2ecf20Sopenharmony_ci break; 24578c2ecf20Sopenharmony_ci 24588c2ecf20Sopenharmony_ci memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); 24598c2ecf20Sopenharmony_ci if (!(scsi_status & 24608c2ecf20Sopenharmony_ci cpu_to_le16((uint16_t)SS_SENSE_LEN_VALID))) 24618c2ecf20Sopenharmony_ci break; 24628c2ecf20Sopenharmony_ci 24638c2ecf20Sopenharmony_ci qlafx00_handle_sense(sp, sense_data, par_sense_len, 24648c2ecf20Sopenharmony_ci sense_len, rsp, res); 24658c2ecf20Sopenharmony_ci } 24668c2ecf20Sopenharmony_ci break; 24678c2ecf20Sopenharmony_ci 24688c2ecf20Sopenharmony_ci case CS_PORT_LOGGED_OUT: 24698c2ecf20Sopenharmony_ci case CS_PORT_CONFIG_CHG: 24708c2ecf20Sopenharmony_ci case CS_PORT_BUSY: 24718c2ecf20Sopenharmony_ci case CS_INCOMPLETE: 24728c2ecf20Sopenharmony_ci case CS_PORT_UNAVAILABLE: 24738c2ecf20Sopenharmony_ci case CS_TIMEOUT: 24748c2ecf20Sopenharmony_ci case CS_RESET: 24758c2ecf20Sopenharmony_ci 24768c2ecf20Sopenharmony_ci /* 24778c2ecf20Sopenharmony_ci * We are going to have the fc class block the rport 24788c2ecf20Sopenharmony_ci * while we try to recover so instruct the mid layer 24798c2ecf20Sopenharmony_ci * to requeue until the class decides how to handle this. 24808c2ecf20Sopenharmony_ci */ 24818c2ecf20Sopenharmony_ci res = DID_TRANSPORT_DISRUPTED << 16; 24828c2ecf20Sopenharmony_ci 24838c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, fcport->vha, 0x3057, 24848c2ecf20Sopenharmony_ci "Port down status: port-state=0x%x.\n", 24858c2ecf20Sopenharmony_ci atomic_read(&fcport->state)); 24868c2ecf20Sopenharmony_ci 24878c2ecf20Sopenharmony_ci if (atomic_read(&fcport->state) == FCS_ONLINE) 24888c2ecf20Sopenharmony_ci qla2x00_mark_device_lost(fcport->vha, fcport, 1); 24898c2ecf20Sopenharmony_ci break; 24908c2ecf20Sopenharmony_ci 24918c2ecf20Sopenharmony_ci case CS_ABORTED: 24928c2ecf20Sopenharmony_ci res = DID_RESET << 16; 24938c2ecf20Sopenharmony_ci break; 24948c2ecf20Sopenharmony_ci 24958c2ecf20Sopenharmony_ci default: 24968c2ecf20Sopenharmony_ci res = DID_ERROR << 16; 24978c2ecf20Sopenharmony_ci break; 24988c2ecf20Sopenharmony_ci } 24998c2ecf20Sopenharmony_ci 25008c2ecf20Sopenharmony_ci if (logit) 25018c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, fcport->vha, 0x3058, 25028c2ecf20Sopenharmony_ci "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu " 25038c2ecf20Sopenharmony_ci "tgt_id: 0x%x lscsi_status: 0x%x cdb=%10phN len=0x%x " 25048c2ecf20Sopenharmony_ci "rsp_info=%p resid=0x%x fw_resid=0x%x sense_len=0x%x, " 25058c2ecf20Sopenharmony_ci "par_sense_len=0x%x, rsp_info_len=0x%x\n", 25068c2ecf20Sopenharmony_ci comp_status, scsi_status, res, vha->host_no, 25078c2ecf20Sopenharmony_ci cp->device->id, cp->device->lun, fcport->tgt_id, 25088c2ecf20Sopenharmony_ci lscsi_status, cp->cmnd, scsi_bufflen(cp), 25098c2ecf20Sopenharmony_ci rsp_info, resid_len, fw_resid_len, sense_len, 25108c2ecf20Sopenharmony_ci par_sense_len, rsp_info_len); 25118c2ecf20Sopenharmony_ci 25128c2ecf20Sopenharmony_ci if (rsp->status_srb == NULL) 25138c2ecf20Sopenharmony_ci sp->done(sp, res); 25148c2ecf20Sopenharmony_ci else 25158c2ecf20Sopenharmony_ci WARN_ON_ONCE(true); 25168c2ecf20Sopenharmony_ci} 25178c2ecf20Sopenharmony_ci 25188c2ecf20Sopenharmony_ci/** 25198c2ecf20Sopenharmony_ci * qlafx00_status_cont_entry() - Process a Status Continuations entry. 25208c2ecf20Sopenharmony_ci * @rsp: response queue 25218c2ecf20Sopenharmony_ci * @pkt: Entry pointer 25228c2ecf20Sopenharmony_ci * 25238c2ecf20Sopenharmony_ci * Extended sense data. 25248c2ecf20Sopenharmony_ci */ 25258c2ecf20Sopenharmony_cistatic void 25268c2ecf20Sopenharmony_ciqlafx00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt) 25278c2ecf20Sopenharmony_ci{ 25288c2ecf20Sopenharmony_ci uint8_t sense_sz = 0; 25298c2ecf20Sopenharmony_ci struct qla_hw_data *ha = rsp->hw; 25308c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = pci_get_drvdata(ha->pdev); 25318c2ecf20Sopenharmony_ci srb_t *sp = rsp->status_srb; 25328c2ecf20Sopenharmony_ci struct scsi_cmnd *cp; 25338c2ecf20Sopenharmony_ci uint32_t sense_len; 25348c2ecf20Sopenharmony_ci uint8_t *sense_ptr; 25358c2ecf20Sopenharmony_ci 25368c2ecf20Sopenharmony_ci if (!sp) { 25378c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, vha, 0x3037, 25388c2ecf20Sopenharmony_ci "no SP, sp = %p\n", sp); 25398c2ecf20Sopenharmony_ci return; 25408c2ecf20Sopenharmony_ci } 25418c2ecf20Sopenharmony_ci 25428c2ecf20Sopenharmony_ci if (!GET_FW_SENSE_LEN(sp)) { 25438c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, vha, 0x304b, 25448c2ecf20Sopenharmony_ci "no fw sense data, sp = %p\n", sp); 25458c2ecf20Sopenharmony_ci return; 25468c2ecf20Sopenharmony_ci } 25478c2ecf20Sopenharmony_ci cp = GET_CMD_SP(sp); 25488c2ecf20Sopenharmony_ci if (cp == NULL) { 25498c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x303b, 25508c2ecf20Sopenharmony_ci "cmd is NULL: already returned to OS (sp=%p).\n", sp); 25518c2ecf20Sopenharmony_ci 25528c2ecf20Sopenharmony_ci rsp->status_srb = NULL; 25538c2ecf20Sopenharmony_ci return; 25548c2ecf20Sopenharmony_ci } 25558c2ecf20Sopenharmony_ci 25568c2ecf20Sopenharmony_ci if (!GET_CMD_SENSE_LEN(sp)) { 25578c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, vha, 0x304c, 25588c2ecf20Sopenharmony_ci "no sense data, sp = %p\n", sp); 25598c2ecf20Sopenharmony_ci } else { 25608c2ecf20Sopenharmony_ci sense_len = GET_CMD_SENSE_LEN(sp); 25618c2ecf20Sopenharmony_ci sense_ptr = GET_CMD_SENSE_PTR(sp); 25628c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, vha, 0x304f, 25638c2ecf20Sopenharmony_ci "sp=%p sense_len=0x%x sense_ptr=%p.\n", 25648c2ecf20Sopenharmony_ci sp, sense_len, sense_ptr); 25658c2ecf20Sopenharmony_ci 25668c2ecf20Sopenharmony_ci if (sense_len > sizeof(pkt->data)) 25678c2ecf20Sopenharmony_ci sense_sz = sizeof(pkt->data); 25688c2ecf20Sopenharmony_ci else 25698c2ecf20Sopenharmony_ci sense_sz = sense_len; 25708c2ecf20Sopenharmony_ci 25718c2ecf20Sopenharmony_ci /* Move sense data. */ 25728c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x304e, 25738c2ecf20Sopenharmony_ci pkt, sizeof(*pkt)); 25748c2ecf20Sopenharmony_ci memcpy(sense_ptr, pkt->data, sense_sz); 25758c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x304a, 25768c2ecf20Sopenharmony_ci sense_ptr, sense_sz); 25778c2ecf20Sopenharmony_ci 25788c2ecf20Sopenharmony_ci sense_len -= sense_sz; 25798c2ecf20Sopenharmony_ci sense_ptr += sense_sz; 25808c2ecf20Sopenharmony_ci 25818c2ecf20Sopenharmony_ci SET_CMD_SENSE_PTR(sp, sense_ptr); 25828c2ecf20Sopenharmony_ci SET_CMD_SENSE_LEN(sp, sense_len); 25838c2ecf20Sopenharmony_ci } 25848c2ecf20Sopenharmony_ci sense_len = GET_FW_SENSE_LEN(sp); 25858c2ecf20Sopenharmony_ci sense_len = (sense_len > sizeof(pkt->data)) ? 25868c2ecf20Sopenharmony_ci (sense_len - sizeof(pkt->data)) : 0; 25878c2ecf20Sopenharmony_ci SET_FW_SENSE_LEN(sp, sense_len); 25888c2ecf20Sopenharmony_ci 25898c2ecf20Sopenharmony_ci /* Place command on done queue. */ 25908c2ecf20Sopenharmony_ci if (sense_len == 0) { 25918c2ecf20Sopenharmony_ci rsp->status_srb = NULL; 25928c2ecf20Sopenharmony_ci sp->done(sp, cp->result); 25938c2ecf20Sopenharmony_ci } else { 25948c2ecf20Sopenharmony_ci WARN_ON_ONCE(true); 25958c2ecf20Sopenharmony_ci } 25968c2ecf20Sopenharmony_ci} 25978c2ecf20Sopenharmony_ci 25988c2ecf20Sopenharmony_ci/** 25998c2ecf20Sopenharmony_ci * qlafx00_multistatus_entry() - Process Multi response queue entries. 26008c2ecf20Sopenharmony_ci * @vha: SCSI driver HA context 26018c2ecf20Sopenharmony_ci * @rsp: response queue 26028c2ecf20Sopenharmony_ci * @pkt: received packet 26038c2ecf20Sopenharmony_ci */ 26048c2ecf20Sopenharmony_cistatic void 26058c2ecf20Sopenharmony_ciqlafx00_multistatus_entry(struct scsi_qla_host *vha, 26068c2ecf20Sopenharmony_ci struct rsp_que *rsp, void *pkt) 26078c2ecf20Sopenharmony_ci{ 26088c2ecf20Sopenharmony_ci srb_t *sp; 26098c2ecf20Sopenharmony_ci struct multi_sts_entry_fx00 *stsmfx; 26108c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 26118c2ecf20Sopenharmony_ci uint32_t handle, hindex, handle_count, i; 26128c2ecf20Sopenharmony_ci uint16_t que; 26138c2ecf20Sopenharmony_ci struct req_que *req; 26148c2ecf20Sopenharmony_ci __le32 *handle_ptr; 26158c2ecf20Sopenharmony_ci 26168c2ecf20Sopenharmony_ci stsmfx = (struct multi_sts_entry_fx00 *) pkt; 26178c2ecf20Sopenharmony_ci 26188c2ecf20Sopenharmony_ci handle_count = stsmfx->handle_count; 26198c2ecf20Sopenharmony_ci 26208c2ecf20Sopenharmony_ci if (handle_count > MAX_HANDLE_COUNT) { 26218c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, vha, 0x3035, 26228c2ecf20Sopenharmony_ci "Invalid handle count (0x%x).\n", handle_count); 26238c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 26248c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 26258c2ecf20Sopenharmony_ci return; 26268c2ecf20Sopenharmony_ci } 26278c2ecf20Sopenharmony_ci 26288c2ecf20Sopenharmony_ci handle_ptr = &stsmfx->handles[0]; 26298c2ecf20Sopenharmony_ci 26308c2ecf20Sopenharmony_ci for (i = 0; i < handle_count; i++) { 26318c2ecf20Sopenharmony_ci hindex = le32_to_cpu(*handle_ptr); 26328c2ecf20Sopenharmony_ci handle = LSW(hindex); 26338c2ecf20Sopenharmony_ci que = MSW(hindex); 26348c2ecf20Sopenharmony_ci req = ha->req_q_map[que]; 26358c2ecf20Sopenharmony_ci 26368c2ecf20Sopenharmony_ci /* Validate handle. */ 26378c2ecf20Sopenharmony_ci if (handle < req->num_outstanding_cmds) 26388c2ecf20Sopenharmony_ci sp = req->outstanding_cmds[handle]; 26398c2ecf20Sopenharmony_ci else 26408c2ecf20Sopenharmony_ci sp = NULL; 26418c2ecf20Sopenharmony_ci 26428c2ecf20Sopenharmony_ci if (sp == NULL) { 26438c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, vha, 0x3044, 26448c2ecf20Sopenharmony_ci "Invalid status handle (0x%x).\n", handle); 26458c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 26468c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 26478c2ecf20Sopenharmony_ci return; 26488c2ecf20Sopenharmony_ci } 26498c2ecf20Sopenharmony_ci qla2x00_process_completed_request(vha, req, handle); 26508c2ecf20Sopenharmony_ci handle_ptr++; 26518c2ecf20Sopenharmony_ci } 26528c2ecf20Sopenharmony_ci} 26538c2ecf20Sopenharmony_ci 26548c2ecf20Sopenharmony_ci/** 26558c2ecf20Sopenharmony_ci * qlafx00_error_entry() - Process an error entry. 26568c2ecf20Sopenharmony_ci * @vha: SCSI driver HA context 26578c2ecf20Sopenharmony_ci * @rsp: response queue 26588c2ecf20Sopenharmony_ci * @pkt: Entry pointer 26598c2ecf20Sopenharmony_ci */ 26608c2ecf20Sopenharmony_cistatic void 26618c2ecf20Sopenharmony_ciqlafx00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, 26628c2ecf20Sopenharmony_ci struct sts_entry_fx00 *pkt) 26638c2ecf20Sopenharmony_ci{ 26648c2ecf20Sopenharmony_ci srb_t *sp; 26658c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 26668c2ecf20Sopenharmony_ci const char func[] = "ERROR-IOCB"; 26678c2ecf20Sopenharmony_ci uint16_t que = 0; 26688c2ecf20Sopenharmony_ci struct req_que *req = NULL; 26698c2ecf20Sopenharmony_ci int res = DID_ERROR << 16; 26708c2ecf20Sopenharmony_ci 26718c2ecf20Sopenharmony_ci req = ha->req_q_map[que]; 26728c2ecf20Sopenharmony_ci 26738c2ecf20Sopenharmony_ci sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); 26748c2ecf20Sopenharmony_ci if (sp) { 26758c2ecf20Sopenharmony_ci sp->done(sp, res); 26768c2ecf20Sopenharmony_ci return; 26778c2ecf20Sopenharmony_ci } 26788c2ecf20Sopenharmony_ci 26798c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 26808c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 26818c2ecf20Sopenharmony_ci} 26828c2ecf20Sopenharmony_ci 26838c2ecf20Sopenharmony_ci/** 26848c2ecf20Sopenharmony_ci * qlafx00_process_response_queue() - Process response queue entries. 26858c2ecf20Sopenharmony_ci * @vha: SCSI driver HA context 26868c2ecf20Sopenharmony_ci * @rsp: response queue 26878c2ecf20Sopenharmony_ci */ 26888c2ecf20Sopenharmony_cistatic void 26898c2ecf20Sopenharmony_ciqlafx00_process_response_queue(struct scsi_qla_host *vha, 26908c2ecf20Sopenharmony_ci struct rsp_que *rsp) 26918c2ecf20Sopenharmony_ci{ 26928c2ecf20Sopenharmony_ci struct sts_entry_fx00 *pkt; 26938c2ecf20Sopenharmony_ci response_t *lptr; 26948c2ecf20Sopenharmony_ci uint16_t lreq_q_in = 0; 26958c2ecf20Sopenharmony_ci uint16_t lreq_q_out = 0; 26968c2ecf20Sopenharmony_ci 26978c2ecf20Sopenharmony_ci lreq_q_in = rd_reg_dword(rsp->rsp_q_in); 26988c2ecf20Sopenharmony_ci lreq_q_out = rsp->ring_index; 26998c2ecf20Sopenharmony_ci 27008c2ecf20Sopenharmony_ci while (lreq_q_in != lreq_q_out) { 27018c2ecf20Sopenharmony_ci lptr = rsp->ring_ptr; 27028c2ecf20Sopenharmony_ci memcpy_fromio(rsp->rsp_pkt, (void __iomem *)lptr, 27038c2ecf20Sopenharmony_ci sizeof(rsp->rsp_pkt)); 27048c2ecf20Sopenharmony_ci pkt = (struct sts_entry_fx00 *)rsp->rsp_pkt; 27058c2ecf20Sopenharmony_ci 27068c2ecf20Sopenharmony_ci rsp->ring_index++; 27078c2ecf20Sopenharmony_ci lreq_q_out++; 27088c2ecf20Sopenharmony_ci if (rsp->ring_index == rsp->length) { 27098c2ecf20Sopenharmony_ci lreq_q_out = 0; 27108c2ecf20Sopenharmony_ci rsp->ring_index = 0; 27118c2ecf20Sopenharmony_ci rsp->ring_ptr = rsp->ring; 27128c2ecf20Sopenharmony_ci } else { 27138c2ecf20Sopenharmony_ci rsp->ring_ptr++; 27148c2ecf20Sopenharmony_ci } 27158c2ecf20Sopenharmony_ci 27168c2ecf20Sopenharmony_ci if (pkt->entry_status != 0 && 27178c2ecf20Sopenharmony_ci pkt->entry_type != IOCTL_IOSB_TYPE_FX00) { 27188c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x507f, 27198c2ecf20Sopenharmony_ci "type of error status in response: 0x%x\n", 27208c2ecf20Sopenharmony_ci pkt->entry_status); 27218c2ecf20Sopenharmony_ci qlafx00_error_entry(vha, rsp, 27228c2ecf20Sopenharmony_ci (struct sts_entry_fx00 *)pkt); 27238c2ecf20Sopenharmony_ci continue; 27248c2ecf20Sopenharmony_ci } 27258c2ecf20Sopenharmony_ci 27268c2ecf20Sopenharmony_ci switch (pkt->entry_type) { 27278c2ecf20Sopenharmony_ci case STATUS_TYPE_FX00: 27288c2ecf20Sopenharmony_ci qlafx00_status_entry(vha, rsp, pkt); 27298c2ecf20Sopenharmony_ci break; 27308c2ecf20Sopenharmony_ci 27318c2ecf20Sopenharmony_ci case STATUS_CONT_TYPE_FX00: 27328c2ecf20Sopenharmony_ci qlafx00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt); 27338c2ecf20Sopenharmony_ci break; 27348c2ecf20Sopenharmony_ci 27358c2ecf20Sopenharmony_ci case MULTI_STATUS_TYPE_FX00: 27368c2ecf20Sopenharmony_ci qlafx00_multistatus_entry(vha, rsp, pkt); 27378c2ecf20Sopenharmony_ci break; 27388c2ecf20Sopenharmony_ci 27398c2ecf20Sopenharmony_ci case ABORT_IOCB_TYPE_FX00: 27408c2ecf20Sopenharmony_ci qlafx00_abort_iocb_entry(vha, rsp->req, 27418c2ecf20Sopenharmony_ci (struct abort_iocb_entry_fx00 *)pkt); 27428c2ecf20Sopenharmony_ci break; 27438c2ecf20Sopenharmony_ci 27448c2ecf20Sopenharmony_ci case IOCTL_IOSB_TYPE_FX00: 27458c2ecf20Sopenharmony_ci qlafx00_ioctl_iosb_entry(vha, rsp->req, 27468c2ecf20Sopenharmony_ci (struct ioctl_iocb_entry_fx00 *)pkt); 27478c2ecf20Sopenharmony_ci break; 27488c2ecf20Sopenharmony_ci default: 27498c2ecf20Sopenharmony_ci /* Type Not Supported. */ 27508c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x5081, 27518c2ecf20Sopenharmony_ci "Received unknown response pkt type %x " 27528c2ecf20Sopenharmony_ci "entry status=%x.\n", 27538c2ecf20Sopenharmony_ci pkt->entry_type, pkt->entry_status); 27548c2ecf20Sopenharmony_ci break; 27558c2ecf20Sopenharmony_ci } 27568c2ecf20Sopenharmony_ci } 27578c2ecf20Sopenharmony_ci 27588c2ecf20Sopenharmony_ci /* Adjust ring index */ 27598c2ecf20Sopenharmony_ci wrt_reg_dword(rsp->rsp_q_out, rsp->ring_index); 27608c2ecf20Sopenharmony_ci} 27618c2ecf20Sopenharmony_ci 27628c2ecf20Sopenharmony_ci/** 27638c2ecf20Sopenharmony_ci * qlafx00_async_event() - Process aynchronous events. 27648c2ecf20Sopenharmony_ci * @vha: SCSI driver HA context 27658c2ecf20Sopenharmony_ci */ 27668c2ecf20Sopenharmony_cistatic void 27678c2ecf20Sopenharmony_ciqlafx00_async_event(scsi_qla_host_t *vha) 27688c2ecf20Sopenharmony_ci{ 27698c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 27708c2ecf20Sopenharmony_ci struct device_reg_fx00 __iomem *reg; 27718c2ecf20Sopenharmony_ci int data_size = 1; 27728c2ecf20Sopenharmony_ci 27738c2ecf20Sopenharmony_ci reg = &ha->iobase->ispfx00; 27748c2ecf20Sopenharmony_ci /* Setup to process RIO completion. */ 27758c2ecf20Sopenharmony_ci switch (ha->aenmb[0]) { 27768c2ecf20Sopenharmony_ci case QLAFX00_MBA_SYSTEM_ERR: /* System Error */ 27778c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x5079, 27788c2ecf20Sopenharmony_ci "ISP System Error - mbx1=%x\n", ha->aenmb[0]); 27798c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 27808c2ecf20Sopenharmony_ci break; 27818c2ecf20Sopenharmony_ci 27828c2ecf20Sopenharmony_ci case QLAFX00_MBA_SHUTDOWN_RQSTD: /* Shutdown requested */ 27838c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x5076, 27848c2ecf20Sopenharmony_ci "Asynchronous FW shutdown requested.\n"); 27858c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 27868c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 27878c2ecf20Sopenharmony_ci break; 27888c2ecf20Sopenharmony_ci 27898c2ecf20Sopenharmony_ci case QLAFX00_MBA_PORT_UPDATE: /* Port database update */ 27908c2ecf20Sopenharmony_ci ha->aenmb[1] = rd_reg_dword(®->aenmailbox1); 27918c2ecf20Sopenharmony_ci ha->aenmb[2] = rd_reg_dword(®->aenmailbox2); 27928c2ecf20Sopenharmony_ci ha->aenmb[3] = rd_reg_dword(®->aenmailbox3); 27938c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x5077, 27948c2ecf20Sopenharmony_ci "Asynchronous port Update received " 27958c2ecf20Sopenharmony_ci "aenmb[0]: %x, aenmb[1]: %x, aenmb[2]: %x, aenmb[3]: %x\n", 27968c2ecf20Sopenharmony_ci ha->aenmb[0], ha->aenmb[1], ha->aenmb[2], ha->aenmb[3]); 27978c2ecf20Sopenharmony_ci data_size = 4; 27988c2ecf20Sopenharmony_ci break; 27998c2ecf20Sopenharmony_ci 28008c2ecf20Sopenharmony_ci case QLAFX00_MBA_TEMP_OVER: /* Over temperature event */ 28018c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x5085, 28028c2ecf20Sopenharmony_ci "Asynchronous over temperature event received " 28038c2ecf20Sopenharmony_ci "aenmb[0]: %x\n", 28048c2ecf20Sopenharmony_ci ha->aenmb[0]); 28058c2ecf20Sopenharmony_ci break; 28068c2ecf20Sopenharmony_ci 28078c2ecf20Sopenharmony_ci case QLAFX00_MBA_TEMP_NORM: /* Normal temperature event */ 28088c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x5086, 28098c2ecf20Sopenharmony_ci "Asynchronous normal temperature event received " 28108c2ecf20Sopenharmony_ci "aenmb[0]: %x\n", 28118c2ecf20Sopenharmony_ci ha->aenmb[0]); 28128c2ecf20Sopenharmony_ci break; 28138c2ecf20Sopenharmony_ci 28148c2ecf20Sopenharmony_ci case QLAFX00_MBA_TEMP_CRIT: /* Critical temperature event */ 28158c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x5083, 28168c2ecf20Sopenharmony_ci "Asynchronous critical temperature event received " 28178c2ecf20Sopenharmony_ci "aenmb[0]: %x\n", 28188c2ecf20Sopenharmony_ci ha->aenmb[0]); 28198c2ecf20Sopenharmony_ci break; 28208c2ecf20Sopenharmony_ci 28218c2ecf20Sopenharmony_ci default: 28228c2ecf20Sopenharmony_ci ha->aenmb[1] = rd_reg_dword(®->aenmailbox1); 28238c2ecf20Sopenharmony_ci ha->aenmb[2] = rd_reg_dword(®->aenmailbox2); 28248c2ecf20Sopenharmony_ci ha->aenmb[3] = rd_reg_dword(®->aenmailbox3); 28258c2ecf20Sopenharmony_ci ha->aenmb[4] = rd_reg_dword(®->aenmailbox4); 28268c2ecf20Sopenharmony_ci ha->aenmb[5] = rd_reg_dword(®->aenmailbox5); 28278c2ecf20Sopenharmony_ci ha->aenmb[6] = rd_reg_dword(®->aenmailbox6); 28288c2ecf20Sopenharmony_ci ha->aenmb[7] = rd_reg_dword(®->aenmailbox7); 28298c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x5078, 28308c2ecf20Sopenharmony_ci "AEN:%04x %04x %04x %04x :%04x %04x %04x %04x\n", 28318c2ecf20Sopenharmony_ci ha->aenmb[0], ha->aenmb[1], ha->aenmb[2], ha->aenmb[3], 28328c2ecf20Sopenharmony_ci ha->aenmb[4], ha->aenmb[5], ha->aenmb[6], ha->aenmb[7]); 28338c2ecf20Sopenharmony_ci break; 28348c2ecf20Sopenharmony_ci } 28358c2ecf20Sopenharmony_ci qlafx00_post_aenfx_work(vha, ha->aenmb[0], 28368c2ecf20Sopenharmony_ci (uint32_t *)ha->aenmb, data_size); 28378c2ecf20Sopenharmony_ci} 28388c2ecf20Sopenharmony_ci 28398c2ecf20Sopenharmony_ci/** 28408c2ecf20Sopenharmony_ci * qlafx00x_mbx_completion() - Process mailbox command completions. 28418c2ecf20Sopenharmony_ci * @vha: SCSI driver HA context 28428c2ecf20Sopenharmony_ci * @mb0: value to be written into mailbox register 0 28438c2ecf20Sopenharmony_ci */ 28448c2ecf20Sopenharmony_cistatic void 28458c2ecf20Sopenharmony_ciqlafx00_mbx_completion(scsi_qla_host_t *vha, uint32_t mb0) 28468c2ecf20Sopenharmony_ci{ 28478c2ecf20Sopenharmony_ci uint16_t cnt; 28488c2ecf20Sopenharmony_ci __le32 __iomem *wptr; 28498c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 28508c2ecf20Sopenharmony_ci struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00; 28518c2ecf20Sopenharmony_ci 28528c2ecf20Sopenharmony_ci if (!ha->mcp32) 28538c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_async, vha, 0x507e, "MBX pointer ERROR.\n"); 28548c2ecf20Sopenharmony_ci 28558c2ecf20Sopenharmony_ci /* Load return mailbox registers. */ 28568c2ecf20Sopenharmony_ci ha->flags.mbox_int = 1; 28578c2ecf20Sopenharmony_ci ha->mailbox_out32[0] = mb0; 28588c2ecf20Sopenharmony_ci wptr = ®->mailbox17; 28598c2ecf20Sopenharmony_ci 28608c2ecf20Sopenharmony_ci for (cnt = 1; cnt < ha->mbx_count; cnt++) { 28618c2ecf20Sopenharmony_ci ha->mailbox_out32[cnt] = rd_reg_dword(wptr); 28628c2ecf20Sopenharmony_ci wptr++; 28638c2ecf20Sopenharmony_ci } 28648c2ecf20Sopenharmony_ci} 28658c2ecf20Sopenharmony_ci 28668c2ecf20Sopenharmony_ci/** 28678c2ecf20Sopenharmony_ci * qlafx00_intr_handler() - Process interrupts for the ISPFX00. 28688c2ecf20Sopenharmony_ci * @irq: interrupt number 28698c2ecf20Sopenharmony_ci * @dev_id: SCSI driver HA context 28708c2ecf20Sopenharmony_ci * 28718c2ecf20Sopenharmony_ci * Called by system whenever the host adapter generates an interrupt. 28728c2ecf20Sopenharmony_ci * 28738c2ecf20Sopenharmony_ci * Returns handled flag. 28748c2ecf20Sopenharmony_ci */ 28758c2ecf20Sopenharmony_ciirqreturn_t 28768c2ecf20Sopenharmony_ciqlafx00_intr_handler(int irq, void *dev_id) 28778c2ecf20Sopenharmony_ci{ 28788c2ecf20Sopenharmony_ci scsi_qla_host_t *vha; 28798c2ecf20Sopenharmony_ci struct qla_hw_data *ha; 28808c2ecf20Sopenharmony_ci struct device_reg_fx00 __iomem *reg; 28818c2ecf20Sopenharmony_ci int status; 28828c2ecf20Sopenharmony_ci unsigned long iter; 28838c2ecf20Sopenharmony_ci uint32_t stat; 28848c2ecf20Sopenharmony_ci uint32_t mb[8]; 28858c2ecf20Sopenharmony_ci struct rsp_que *rsp; 28868c2ecf20Sopenharmony_ci unsigned long flags; 28878c2ecf20Sopenharmony_ci uint32_t clr_intr = 0; 28888c2ecf20Sopenharmony_ci uint32_t intr_stat = 0; 28898c2ecf20Sopenharmony_ci 28908c2ecf20Sopenharmony_ci rsp = (struct rsp_que *) dev_id; 28918c2ecf20Sopenharmony_ci if (!rsp) { 28928c2ecf20Sopenharmony_ci ql_log(ql_log_info, NULL, 0x507d, 28938c2ecf20Sopenharmony_ci "%s: NULL response queue pointer.\n", __func__); 28948c2ecf20Sopenharmony_ci return IRQ_NONE; 28958c2ecf20Sopenharmony_ci } 28968c2ecf20Sopenharmony_ci 28978c2ecf20Sopenharmony_ci ha = rsp->hw; 28988c2ecf20Sopenharmony_ci reg = &ha->iobase->ispfx00; 28998c2ecf20Sopenharmony_ci status = 0; 29008c2ecf20Sopenharmony_ci 29018c2ecf20Sopenharmony_ci if (unlikely(pci_channel_offline(ha->pdev))) 29028c2ecf20Sopenharmony_ci return IRQ_HANDLED; 29038c2ecf20Sopenharmony_ci 29048c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 29058c2ecf20Sopenharmony_ci vha = pci_get_drvdata(ha->pdev); 29068c2ecf20Sopenharmony_ci for (iter = 50; iter--; clr_intr = 0) { 29078c2ecf20Sopenharmony_ci stat = QLAFX00_RD_INTR_REG(ha); 29088c2ecf20Sopenharmony_ci if (qla2x00_check_reg32_for_disconnect(vha, stat)) 29098c2ecf20Sopenharmony_ci break; 29108c2ecf20Sopenharmony_ci intr_stat = stat & QLAFX00_HST_INT_STS_BITS; 29118c2ecf20Sopenharmony_ci if (!intr_stat) 29128c2ecf20Sopenharmony_ci break; 29138c2ecf20Sopenharmony_ci 29148c2ecf20Sopenharmony_ci if (stat & QLAFX00_INTR_MB_CMPLT) { 29158c2ecf20Sopenharmony_ci mb[0] = rd_reg_dword(®->mailbox16); 29168c2ecf20Sopenharmony_ci qlafx00_mbx_completion(vha, mb[0]); 29178c2ecf20Sopenharmony_ci status |= MBX_INTERRUPT; 29188c2ecf20Sopenharmony_ci clr_intr |= QLAFX00_INTR_MB_CMPLT; 29198c2ecf20Sopenharmony_ci } 29208c2ecf20Sopenharmony_ci if (intr_stat & QLAFX00_INTR_ASYNC_CMPLT) { 29218c2ecf20Sopenharmony_ci ha->aenmb[0] = rd_reg_dword(®->aenmailbox0); 29228c2ecf20Sopenharmony_ci qlafx00_async_event(vha); 29238c2ecf20Sopenharmony_ci clr_intr |= QLAFX00_INTR_ASYNC_CMPLT; 29248c2ecf20Sopenharmony_ci } 29258c2ecf20Sopenharmony_ci if (intr_stat & QLAFX00_INTR_RSP_CMPLT) { 29268c2ecf20Sopenharmony_ci qlafx00_process_response_queue(vha, rsp); 29278c2ecf20Sopenharmony_ci clr_intr |= QLAFX00_INTR_RSP_CMPLT; 29288c2ecf20Sopenharmony_ci } 29298c2ecf20Sopenharmony_ci 29308c2ecf20Sopenharmony_ci QLAFX00_CLR_INTR_REG(ha, clr_intr); 29318c2ecf20Sopenharmony_ci QLAFX00_RD_INTR_REG(ha); 29328c2ecf20Sopenharmony_ci } 29338c2ecf20Sopenharmony_ci 29348c2ecf20Sopenharmony_ci qla2x00_handle_mbx_completion(ha, status); 29358c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 29368c2ecf20Sopenharmony_ci 29378c2ecf20Sopenharmony_ci return IRQ_HANDLED; 29388c2ecf20Sopenharmony_ci} 29398c2ecf20Sopenharmony_ci 29408c2ecf20Sopenharmony_ci/** QLAFX00 specific IOCB implementation functions */ 29418c2ecf20Sopenharmony_ci 29428c2ecf20Sopenharmony_cistatic inline cont_a64_entry_t * 29438c2ecf20Sopenharmony_ciqlafx00_prep_cont_type1_iocb(struct req_que *req, 29448c2ecf20Sopenharmony_ci cont_a64_entry_t *lcont_pkt) 29458c2ecf20Sopenharmony_ci{ 29468c2ecf20Sopenharmony_ci cont_a64_entry_t *cont_pkt; 29478c2ecf20Sopenharmony_ci 29488c2ecf20Sopenharmony_ci /* Adjust ring index. */ 29498c2ecf20Sopenharmony_ci req->ring_index++; 29508c2ecf20Sopenharmony_ci if (req->ring_index == req->length) { 29518c2ecf20Sopenharmony_ci req->ring_index = 0; 29528c2ecf20Sopenharmony_ci req->ring_ptr = req->ring; 29538c2ecf20Sopenharmony_ci } else { 29548c2ecf20Sopenharmony_ci req->ring_ptr++; 29558c2ecf20Sopenharmony_ci } 29568c2ecf20Sopenharmony_ci 29578c2ecf20Sopenharmony_ci cont_pkt = (cont_a64_entry_t *)req->ring_ptr; 29588c2ecf20Sopenharmony_ci 29598c2ecf20Sopenharmony_ci /* Load packet defaults. */ 29608c2ecf20Sopenharmony_ci lcont_pkt->entry_type = CONTINUE_A64_TYPE_FX00; 29618c2ecf20Sopenharmony_ci 29628c2ecf20Sopenharmony_ci return cont_pkt; 29638c2ecf20Sopenharmony_ci} 29648c2ecf20Sopenharmony_ci 29658c2ecf20Sopenharmony_cistatic inline void 29668c2ecf20Sopenharmony_ciqlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt, 29678c2ecf20Sopenharmony_ci uint16_t tot_dsds, struct cmd_type_7_fx00 *lcmd_pkt) 29688c2ecf20Sopenharmony_ci{ 29698c2ecf20Sopenharmony_ci uint16_t avail_dsds; 29708c2ecf20Sopenharmony_ci struct dsd64 *cur_dsd; 29718c2ecf20Sopenharmony_ci scsi_qla_host_t *vha; 29728c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd; 29738c2ecf20Sopenharmony_ci struct scatterlist *sg; 29748c2ecf20Sopenharmony_ci int i, cont; 29758c2ecf20Sopenharmony_ci struct req_que *req; 29768c2ecf20Sopenharmony_ci cont_a64_entry_t lcont_pkt; 29778c2ecf20Sopenharmony_ci cont_a64_entry_t *cont_pkt; 29788c2ecf20Sopenharmony_ci 29798c2ecf20Sopenharmony_ci vha = sp->vha; 29808c2ecf20Sopenharmony_ci req = vha->req; 29818c2ecf20Sopenharmony_ci 29828c2ecf20Sopenharmony_ci cmd = GET_CMD_SP(sp); 29838c2ecf20Sopenharmony_ci cont = 0; 29848c2ecf20Sopenharmony_ci cont_pkt = NULL; 29858c2ecf20Sopenharmony_ci 29868c2ecf20Sopenharmony_ci /* Update entry type to indicate Command Type 3 IOCB */ 29878c2ecf20Sopenharmony_ci lcmd_pkt->entry_type = FX00_COMMAND_TYPE_7; 29888c2ecf20Sopenharmony_ci 29898c2ecf20Sopenharmony_ci /* No data transfer */ 29908c2ecf20Sopenharmony_ci if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { 29918c2ecf20Sopenharmony_ci lcmd_pkt->byte_count = cpu_to_le32(0); 29928c2ecf20Sopenharmony_ci return; 29938c2ecf20Sopenharmony_ci } 29948c2ecf20Sopenharmony_ci 29958c2ecf20Sopenharmony_ci /* Set transfer direction */ 29968c2ecf20Sopenharmony_ci if (cmd->sc_data_direction == DMA_TO_DEVICE) { 29978c2ecf20Sopenharmony_ci lcmd_pkt->cntrl_flags = TMF_WRITE_DATA; 29988c2ecf20Sopenharmony_ci vha->qla_stats.output_bytes += scsi_bufflen(cmd); 29998c2ecf20Sopenharmony_ci } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { 30008c2ecf20Sopenharmony_ci lcmd_pkt->cntrl_flags = TMF_READ_DATA; 30018c2ecf20Sopenharmony_ci vha->qla_stats.input_bytes += scsi_bufflen(cmd); 30028c2ecf20Sopenharmony_ci } 30038c2ecf20Sopenharmony_ci 30048c2ecf20Sopenharmony_ci /* One DSD is available in the Command Type 3 IOCB */ 30058c2ecf20Sopenharmony_ci avail_dsds = 1; 30068c2ecf20Sopenharmony_ci cur_dsd = &lcmd_pkt->dsd; 30078c2ecf20Sopenharmony_ci 30088c2ecf20Sopenharmony_ci /* Load data segments */ 30098c2ecf20Sopenharmony_ci scsi_for_each_sg(cmd, sg, tot_dsds, i) { 30108c2ecf20Sopenharmony_ci /* Allocate additional continuation packets? */ 30118c2ecf20Sopenharmony_ci if (avail_dsds == 0) { 30128c2ecf20Sopenharmony_ci /* 30138c2ecf20Sopenharmony_ci * Five DSDs are available in the Continuation 30148c2ecf20Sopenharmony_ci * Type 1 IOCB. 30158c2ecf20Sopenharmony_ci */ 30168c2ecf20Sopenharmony_ci memset(&lcont_pkt, 0, REQUEST_ENTRY_SIZE); 30178c2ecf20Sopenharmony_ci cont_pkt = 30188c2ecf20Sopenharmony_ci qlafx00_prep_cont_type1_iocb(req, &lcont_pkt); 30198c2ecf20Sopenharmony_ci cur_dsd = lcont_pkt.dsd; 30208c2ecf20Sopenharmony_ci avail_dsds = 5; 30218c2ecf20Sopenharmony_ci cont = 1; 30228c2ecf20Sopenharmony_ci } 30238c2ecf20Sopenharmony_ci 30248c2ecf20Sopenharmony_ci append_dsd64(&cur_dsd, sg); 30258c2ecf20Sopenharmony_ci avail_dsds--; 30268c2ecf20Sopenharmony_ci if (avail_dsds == 0 && cont == 1) { 30278c2ecf20Sopenharmony_ci cont = 0; 30288c2ecf20Sopenharmony_ci memcpy_toio((void __iomem *)cont_pkt, &lcont_pkt, 30298c2ecf20Sopenharmony_ci sizeof(lcont_pkt)); 30308c2ecf20Sopenharmony_ci } 30318c2ecf20Sopenharmony_ci 30328c2ecf20Sopenharmony_ci } 30338c2ecf20Sopenharmony_ci if (avail_dsds != 0 && cont == 1) { 30348c2ecf20Sopenharmony_ci memcpy_toio((void __iomem *)cont_pkt, &lcont_pkt, 30358c2ecf20Sopenharmony_ci sizeof(lcont_pkt)); 30368c2ecf20Sopenharmony_ci } 30378c2ecf20Sopenharmony_ci} 30388c2ecf20Sopenharmony_ci 30398c2ecf20Sopenharmony_ci/** 30408c2ecf20Sopenharmony_ci * qlafx00_start_scsi() - Send a SCSI command to the ISP 30418c2ecf20Sopenharmony_ci * @sp: command to send to the ISP 30428c2ecf20Sopenharmony_ci * 30438c2ecf20Sopenharmony_ci * Returns non-zero if a failure occurred, else zero. 30448c2ecf20Sopenharmony_ci */ 30458c2ecf20Sopenharmony_ciint 30468c2ecf20Sopenharmony_ciqlafx00_start_scsi(srb_t *sp) 30478c2ecf20Sopenharmony_ci{ 30488c2ecf20Sopenharmony_ci int nseg; 30498c2ecf20Sopenharmony_ci unsigned long flags; 30508c2ecf20Sopenharmony_ci uint32_t handle; 30518c2ecf20Sopenharmony_ci uint16_t cnt; 30528c2ecf20Sopenharmony_ci uint16_t req_cnt; 30538c2ecf20Sopenharmony_ci uint16_t tot_dsds; 30548c2ecf20Sopenharmony_ci struct req_que *req = NULL; 30558c2ecf20Sopenharmony_ci struct rsp_que *rsp = NULL; 30568c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd = GET_CMD_SP(sp); 30578c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = sp->vha; 30588c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 30598c2ecf20Sopenharmony_ci struct cmd_type_7_fx00 *cmd_pkt; 30608c2ecf20Sopenharmony_ci struct cmd_type_7_fx00 lcmd_pkt; 30618c2ecf20Sopenharmony_ci struct scsi_lun llun; 30628c2ecf20Sopenharmony_ci 30638c2ecf20Sopenharmony_ci /* Setup device pointers. */ 30648c2ecf20Sopenharmony_ci rsp = ha->rsp_q_map[0]; 30658c2ecf20Sopenharmony_ci req = vha->req; 30668c2ecf20Sopenharmony_ci 30678c2ecf20Sopenharmony_ci /* So we know we haven't pci_map'ed anything yet */ 30688c2ecf20Sopenharmony_ci tot_dsds = 0; 30698c2ecf20Sopenharmony_ci 30708c2ecf20Sopenharmony_ci /* Acquire ring specific lock */ 30718c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 30728c2ecf20Sopenharmony_ci 30738c2ecf20Sopenharmony_ci handle = qla2xxx_get_next_handle(req); 30748c2ecf20Sopenharmony_ci if (handle == 0) 30758c2ecf20Sopenharmony_ci goto queuing_error; 30768c2ecf20Sopenharmony_ci 30778c2ecf20Sopenharmony_ci /* Map the sg table so we have an accurate count of sg entries needed */ 30788c2ecf20Sopenharmony_ci if (scsi_sg_count(cmd)) { 30798c2ecf20Sopenharmony_ci nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd), 30808c2ecf20Sopenharmony_ci scsi_sg_count(cmd), cmd->sc_data_direction); 30818c2ecf20Sopenharmony_ci if (unlikely(!nseg)) 30828c2ecf20Sopenharmony_ci goto queuing_error; 30838c2ecf20Sopenharmony_ci } else 30848c2ecf20Sopenharmony_ci nseg = 0; 30858c2ecf20Sopenharmony_ci 30868c2ecf20Sopenharmony_ci tot_dsds = nseg; 30878c2ecf20Sopenharmony_ci req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); 30888c2ecf20Sopenharmony_ci if (req->cnt < (req_cnt + 2)) { 30898c2ecf20Sopenharmony_ci cnt = rd_reg_dword_relaxed(req->req_q_out); 30908c2ecf20Sopenharmony_ci 30918c2ecf20Sopenharmony_ci if (req->ring_index < cnt) 30928c2ecf20Sopenharmony_ci req->cnt = cnt - req->ring_index; 30938c2ecf20Sopenharmony_ci else 30948c2ecf20Sopenharmony_ci req->cnt = req->length - 30958c2ecf20Sopenharmony_ci (req->ring_index - cnt); 30968c2ecf20Sopenharmony_ci if (req->cnt < (req_cnt + 2)) 30978c2ecf20Sopenharmony_ci goto queuing_error; 30988c2ecf20Sopenharmony_ci } 30998c2ecf20Sopenharmony_ci 31008c2ecf20Sopenharmony_ci /* Build command packet. */ 31018c2ecf20Sopenharmony_ci req->current_outstanding_cmd = handle; 31028c2ecf20Sopenharmony_ci req->outstanding_cmds[handle] = sp; 31038c2ecf20Sopenharmony_ci sp->handle = handle; 31048c2ecf20Sopenharmony_ci cmd->host_scribble = (unsigned char *)(unsigned long)handle; 31058c2ecf20Sopenharmony_ci req->cnt -= req_cnt; 31068c2ecf20Sopenharmony_ci 31078c2ecf20Sopenharmony_ci cmd_pkt = (struct cmd_type_7_fx00 *)req->ring_ptr; 31088c2ecf20Sopenharmony_ci 31098c2ecf20Sopenharmony_ci memset(&lcmd_pkt, 0, REQUEST_ENTRY_SIZE); 31108c2ecf20Sopenharmony_ci 31118c2ecf20Sopenharmony_ci lcmd_pkt.handle = make_handle(req->id, sp->handle); 31128c2ecf20Sopenharmony_ci lcmd_pkt.reserved_0 = 0; 31138c2ecf20Sopenharmony_ci lcmd_pkt.port_path_ctrl = 0; 31148c2ecf20Sopenharmony_ci lcmd_pkt.reserved_1 = 0; 31158c2ecf20Sopenharmony_ci lcmd_pkt.dseg_count = cpu_to_le16(tot_dsds); 31168c2ecf20Sopenharmony_ci lcmd_pkt.tgt_idx = cpu_to_le16(sp->fcport->tgt_id); 31178c2ecf20Sopenharmony_ci 31188c2ecf20Sopenharmony_ci int_to_scsilun(cmd->device->lun, &llun); 31198c2ecf20Sopenharmony_ci host_to_adap((uint8_t *)&llun, (uint8_t *)&lcmd_pkt.lun, 31208c2ecf20Sopenharmony_ci sizeof(lcmd_pkt.lun)); 31218c2ecf20Sopenharmony_ci 31228c2ecf20Sopenharmony_ci /* Load SCSI command packet. */ 31238c2ecf20Sopenharmony_ci host_to_adap(cmd->cmnd, lcmd_pkt.fcp_cdb, sizeof(lcmd_pkt.fcp_cdb)); 31248c2ecf20Sopenharmony_ci lcmd_pkt.byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd)); 31258c2ecf20Sopenharmony_ci 31268c2ecf20Sopenharmony_ci /* Build IOCB segments */ 31278c2ecf20Sopenharmony_ci qlafx00_build_scsi_iocbs(sp, cmd_pkt, tot_dsds, &lcmd_pkt); 31288c2ecf20Sopenharmony_ci 31298c2ecf20Sopenharmony_ci /* Set total data segment count. */ 31308c2ecf20Sopenharmony_ci lcmd_pkt.entry_count = (uint8_t)req_cnt; 31318c2ecf20Sopenharmony_ci 31328c2ecf20Sopenharmony_ci /* Specify response queue number where completion should happen */ 31338c2ecf20Sopenharmony_ci lcmd_pkt.entry_status = (uint8_t) rsp->id; 31348c2ecf20Sopenharmony_ci 31358c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302e, 31368c2ecf20Sopenharmony_ci cmd->cmnd, cmd->cmd_len); 31378c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x3032, 31388c2ecf20Sopenharmony_ci &lcmd_pkt, sizeof(lcmd_pkt)); 31398c2ecf20Sopenharmony_ci 31408c2ecf20Sopenharmony_ci memcpy_toio((void __iomem *)cmd_pkt, &lcmd_pkt, REQUEST_ENTRY_SIZE); 31418c2ecf20Sopenharmony_ci wmb(); 31428c2ecf20Sopenharmony_ci 31438c2ecf20Sopenharmony_ci /* Adjust ring index. */ 31448c2ecf20Sopenharmony_ci req->ring_index++; 31458c2ecf20Sopenharmony_ci if (req->ring_index == req->length) { 31468c2ecf20Sopenharmony_ci req->ring_index = 0; 31478c2ecf20Sopenharmony_ci req->ring_ptr = req->ring; 31488c2ecf20Sopenharmony_ci } else 31498c2ecf20Sopenharmony_ci req->ring_ptr++; 31508c2ecf20Sopenharmony_ci 31518c2ecf20Sopenharmony_ci sp->flags |= SRB_DMA_VALID; 31528c2ecf20Sopenharmony_ci 31538c2ecf20Sopenharmony_ci /* Set chip new ring index. */ 31548c2ecf20Sopenharmony_ci wrt_reg_dword(req->req_q_in, req->ring_index); 31558c2ecf20Sopenharmony_ci QLAFX00_SET_HST_INTR(ha, ha->rqstq_intr_code); 31568c2ecf20Sopenharmony_ci 31578c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 31588c2ecf20Sopenharmony_ci return QLA_SUCCESS; 31598c2ecf20Sopenharmony_ci 31608c2ecf20Sopenharmony_ciqueuing_error: 31618c2ecf20Sopenharmony_ci if (tot_dsds) 31628c2ecf20Sopenharmony_ci scsi_dma_unmap(cmd); 31638c2ecf20Sopenharmony_ci 31648c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 31658c2ecf20Sopenharmony_ci 31668c2ecf20Sopenharmony_ci return QLA_FUNCTION_FAILED; 31678c2ecf20Sopenharmony_ci} 31688c2ecf20Sopenharmony_ci 31698c2ecf20Sopenharmony_civoid 31708c2ecf20Sopenharmony_ciqlafx00_tm_iocb(srb_t *sp, struct tsk_mgmt_entry_fx00 *ptm_iocb) 31718c2ecf20Sopenharmony_ci{ 31728c2ecf20Sopenharmony_ci struct srb_iocb *fxio = &sp->u.iocb_cmd; 31738c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = sp->vha; 31748c2ecf20Sopenharmony_ci struct req_que *req = vha->req; 31758c2ecf20Sopenharmony_ci struct tsk_mgmt_entry_fx00 tm_iocb; 31768c2ecf20Sopenharmony_ci struct scsi_lun llun; 31778c2ecf20Sopenharmony_ci 31788c2ecf20Sopenharmony_ci memset(&tm_iocb, 0, sizeof(struct tsk_mgmt_entry_fx00)); 31798c2ecf20Sopenharmony_ci tm_iocb.entry_type = TSK_MGMT_IOCB_TYPE_FX00; 31808c2ecf20Sopenharmony_ci tm_iocb.entry_count = 1; 31818c2ecf20Sopenharmony_ci tm_iocb.handle = make_handle(req->id, sp->handle); 31828c2ecf20Sopenharmony_ci tm_iocb.reserved_0 = 0; 31838c2ecf20Sopenharmony_ci tm_iocb.tgt_id = cpu_to_le16(sp->fcport->tgt_id); 31848c2ecf20Sopenharmony_ci tm_iocb.control_flags = cpu_to_le32(fxio->u.tmf.flags); 31858c2ecf20Sopenharmony_ci if (tm_iocb.control_flags == cpu_to_le32((uint32_t)TCF_LUN_RESET)) { 31868c2ecf20Sopenharmony_ci int_to_scsilun(fxio->u.tmf.lun, &llun); 31878c2ecf20Sopenharmony_ci host_to_adap((uint8_t *)&llun, (uint8_t *)&tm_iocb.lun, 31888c2ecf20Sopenharmony_ci sizeof(struct scsi_lun)); 31898c2ecf20Sopenharmony_ci } 31908c2ecf20Sopenharmony_ci 31918c2ecf20Sopenharmony_ci memcpy(ptm_iocb, &tm_iocb, 31928c2ecf20Sopenharmony_ci sizeof(struct tsk_mgmt_entry_fx00)); 31938c2ecf20Sopenharmony_ci wmb(); 31948c2ecf20Sopenharmony_ci} 31958c2ecf20Sopenharmony_ci 31968c2ecf20Sopenharmony_civoid 31978c2ecf20Sopenharmony_ciqlafx00_abort_iocb(srb_t *sp, struct abort_iocb_entry_fx00 *pabt_iocb) 31988c2ecf20Sopenharmony_ci{ 31998c2ecf20Sopenharmony_ci struct srb_iocb *fxio = &sp->u.iocb_cmd; 32008c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = sp->vha; 32018c2ecf20Sopenharmony_ci struct req_que *req = vha->req; 32028c2ecf20Sopenharmony_ci struct abort_iocb_entry_fx00 abt_iocb; 32038c2ecf20Sopenharmony_ci 32048c2ecf20Sopenharmony_ci memset(&abt_iocb, 0, sizeof(struct abort_iocb_entry_fx00)); 32058c2ecf20Sopenharmony_ci abt_iocb.entry_type = ABORT_IOCB_TYPE_FX00; 32068c2ecf20Sopenharmony_ci abt_iocb.entry_count = 1; 32078c2ecf20Sopenharmony_ci abt_iocb.handle = make_handle(req->id, sp->handle); 32088c2ecf20Sopenharmony_ci abt_iocb.abort_handle = make_handle(req->id, fxio->u.abt.cmd_hndl); 32098c2ecf20Sopenharmony_ci abt_iocb.tgt_id_sts = cpu_to_le16(sp->fcport->tgt_id); 32108c2ecf20Sopenharmony_ci abt_iocb.req_que_no = cpu_to_le16(req->id); 32118c2ecf20Sopenharmony_ci 32128c2ecf20Sopenharmony_ci memcpy(pabt_iocb, &abt_iocb, 32138c2ecf20Sopenharmony_ci sizeof(struct abort_iocb_entry_fx00)); 32148c2ecf20Sopenharmony_ci wmb(); 32158c2ecf20Sopenharmony_ci} 32168c2ecf20Sopenharmony_ci 32178c2ecf20Sopenharmony_civoid 32188c2ecf20Sopenharmony_ciqlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) 32198c2ecf20Sopenharmony_ci{ 32208c2ecf20Sopenharmony_ci struct srb_iocb *fxio = &sp->u.iocb_cmd; 32218c2ecf20Sopenharmony_ci struct qla_mt_iocb_rqst_fx00 *piocb_rqst; 32228c2ecf20Sopenharmony_ci struct bsg_job *bsg_job; 32238c2ecf20Sopenharmony_ci struct fc_bsg_request *bsg_request; 32248c2ecf20Sopenharmony_ci struct fxdisc_entry_fx00 fx_iocb; 32258c2ecf20Sopenharmony_ci uint8_t entry_cnt = 1; 32268c2ecf20Sopenharmony_ci 32278c2ecf20Sopenharmony_ci memset(&fx_iocb, 0, sizeof(struct fxdisc_entry_fx00)); 32288c2ecf20Sopenharmony_ci fx_iocb.entry_type = FX00_IOCB_TYPE; 32298c2ecf20Sopenharmony_ci fx_iocb.handle = sp->handle; 32308c2ecf20Sopenharmony_ci fx_iocb.entry_count = entry_cnt; 32318c2ecf20Sopenharmony_ci 32328c2ecf20Sopenharmony_ci if (sp->type == SRB_FXIOCB_DCMD) { 32338c2ecf20Sopenharmony_ci fx_iocb.func_num = 32348c2ecf20Sopenharmony_ci sp->u.iocb_cmd.u.fxiocb.req_func_type; 32358c2ecf20Sopenharmony_ci fx_iocb.adapid = fxio->u.fxiocb.adapter_id; 32368c2ecf20Sopenharmony_ci fx_iocb.adapid_hi = fxio->u.fxiocb.adapter_id_hi; 32378c2ecf20Sopenharmony_ci fx_iocb.reserved_0 = fxio->u.fxiocb.reserved_0; 32388c2ecf20Sopenharmony_ci fx_iocb.reserved_1 = fxio->u.fxiocb.reserved_1; 32398c2ecf20Sopenharmony_ci fx_iocb.dataword_extra = fxio->u.fxiocb.req_data_extra; 32408c2ecf20Sopenharmony_ci 32418c2ecf20Sopenharmony_ci if (fxio->u.fxiocb.flags & SRB_FXDISC_REQ_DMA_VALID) { 32428c2ecf20Sopenharmony_ci fx_iocb.req_dsdcnt = cpu_to_le16(1); 32438c2ecf20Sopenharmony_ci fx_iocb.req_xfrcnt = 32448c2ecf20Sopenharmony_ci cpu_to_le16(fxio->u.fxiocb.req_len); 32458c2ecf20Sopenharmony_ci put_unaligned_le64(fxio->u.fxiocb.req_dma_handle, 32468c2ecf20Sopenharmony_ci &fx_iocb.dseg_rq.address); 32478c2ecf20Sopenharmony_ci fx_iocb.dseg_rq.length = 32488c2ecf20Sopenharmony_ci cpu_to_le32(fxio->u.fxiocb.req_len); 32498c2ecf20Sopenharmony_ci } 32508c2ecf20Sopenharmony_ci 32518c2ecf20Sopenharmony_ci if (fxio->u.fxiocb.flags & SRB_FXDISC_RESP_DMA_VALID) { 32528c2ecf20Sopenharmony_ci fx_iocb.rsp_dsdcnt = cpu_to_le16(1); 32538c2ecf20Sopenharmony_ci fx_iocb.rsp_xfrcnt = 32548c2ecf20Sopenharmony_ci cpu_to_le16(fxio->u.fxiocb.rsp_len); 32558c2ecf20Sopenharmony_ci put_unaligned_le64(fxio->u.fxiocb.rsp_dma_handle, 32568c2ecf20Sopenharmony_ci &fx_iocb.dseg_rsp.address); 32578c2ecf20Sopenharmony_ci fx_iocb.dseg_rsp.length = 32588c2ecf20Sopenharmony_ci cpu_to_le32(fxio->u.fxiocb.rsp_len); 32598c2ecf20Sopenharmony_ci } 32608c2ecf20Sopenharmony_ci 32618c2ecf20Sopenharmony_ci if (fxio->u.fxiocb.flags & SRB_FXDISC_REQ_DWRD_VALID) { 32628c2ecf20Sopenharmony_ci fx_iocb.dataword = fxio->u.fxiocb.req_data; 32638c2ecf20Sopenharmony_ci } 32648c2ecf20Sopenharmony_ci fx_iocb.flags = fxio->u.fxiocb.flags; 32658c2ecf20Sopenharmony_ci } else { 32668c2ecf20Sopenharmony_ci struct scatterlist *sg; 32678c2ecf20Sopenharmony_ci 32688c2ecf20Sopenharmony_ci bsg_job = sp->u.bsg_job; 32698c2ecf20Sopenharmony_ci bsg_request = bsg_job->request; 32708c2ecf20Sopenharmony_ci piocb_rqst = (struct qla_mt_iocb_rqst_fx00 *) 32718c2ecf20Sopenharmony_ci &bsg_request->rqst_data.h_vendor.vendor_cmd[1]; 32728c2ecf20Sopenharmony_ci 32738c2ecf20Sopenharmony_ci fx_iocb.func_num = piocb_rqst->func_type; 32748c2ecf20Sopenharmony_ci fx_iocb.adapid = piocb_rqst->adapid; 32758c2ecf20Sopenharmony_ci fx_iocb.adapid_hi = piocb_rqst->adapid_hi; 32768c2ecf20Sopenharmony_ci fx_iocb.reserved_0 = piocb_rqst->reserved_0; 32778c2ecf20Sopenharmony_ci fx_iocb.reserved_1 = piocb_rqst->reserved_1; 32788c2ecf20Sopenharmony_ci fx_iocb.dataword_extra = piocb_rqst->dataword_extra; 32798c2ecf20Sopenharmony_ci fx_iocb.dataword = piocb_rqst->dataword; 32808c2ecf20Sopenharmony_ci fx_iocb.req_xfrcnt = piocb_rqst->req_len; 32818c2ecf20Sopenharmony_ci fx_iocb.rsp_xfrcnt = piocb_rqst->rsp_len; 32828c2ecf20Sopenharmony_ci 32838c2ecf20Sopenharmony_ci if (piocb_rqst->flags & SRB_FXDISC_REQ_DMA_VALID) { 32848c2ecf20Sopenharmony_ci int avail_dsds, tot_dsds; 32858c2ecf20Sopenharmony_ci cont_a64_entry_t lcont_pkt; 32868c2ecf20Sopenharmony_ci cont_a64_entry_t *cont_pkt = NULL; 32878c2ecf20Sopenharmony_ci struct dsd64 *cur_dsd; 32888c2ecf20Sopenharmony_ci int index = 0, cont = 0; 32898c2ecf20Sopenharmony_ci 32908c2ecf20Sopenharmony_ci fx_iocb.req_dsdcnt = 32918c2ecf20Sopenharmony_ci cpu_to_le16(bsg_job->request_payload.sg_cnt); 32928c2ecf20Sopenharmony_ci tot_dsds = 32938c2ecf20Sopenharmony_ci bsg_job->request_payload.sg_cnt; 32948c2ecf20Sopenharmony_ci cur_dsd = &fx_iocb.dseg_rq; 32958c2ecf20Sopenharmony_ci avail_dsds = 1; 32968c2ecf20Sopenharmony_ci for_each_sg(bsg_job->request_payload.sg_list, sg, 32978c2ecf20Sopenharmony_ci tot_dsds, index) { 32988c2ecf20Sopenharmony_ci /* Allocate additional continuation packets? */ 32998c2ecf20Sopenharmony_ci if (avail_dsds == 0) { 33008c2ecf20Sopenharmony_ci /* 33018c2ecf20Sopenharmony_ci * Five DSDs are available in the Cont. 33028c2ecf20Sopenharmony_ci * Type 1 IOCB. 33038c2ecf20Sopenharmony_ci */ 33048c2ecf20Sopenharmony_ci memset(&lcont_pkt, 0, 33058c2ecf20Sopenharmony_ci REQUEST_ENTRY_SIZE); 33068c2ecf20Sopenharmony_ci cont_pkt = 33078c2ecf20Sopenharmony_ci qlafx00_prep_cont_type1_iocb( 33088c2ecf20Sopenharmony_ci sp->vha->req, &lcont_pkt); 33098c2ecf20Sopenharmony_ci cur_dsd = lcont_pkt.dsd; 33108c2ecf20Sopenharmony_ci avail_dsds = 5; 33118c2ecf20Sopenharmony_ci cont = 1; 33128c2ecf20Sopenharmony_ci entry_cnt++; 33138c2ecf20Sopenharmony_ci } 33148c2ecf20Sopenharmony_ci 33158c2ecf20Sopenharmony_ci append_dsd64(&cur_dsd, sg); 33168c2ecf20Sopenharmony_ci avail_dsds--; 33178c2ecf20Sopenharmony_ci 33188c2ecf20Sopenharmony_ci if (avail_dsds == 0 && cont == 1) { 33198c2ecf20Sopenharmony_ci cont = 0; 33208c2ecf20Sopenharmony_ci memcpy_toio( 33218c2ecf20Sopenharmony_ci (void __iomem *)cont_pkt, 33228c2ecf20Sopenharmony_ci &lcont_pkt, REQUEST_ENTRY_SIZE); 33238c2ecf20Sopenharmony_ci ql_dump_buffer( 33248c2ecf20Sopenharmony_ci ql_dbg_user + ql_dbg_verbose, 33258c2ecf20Sopenharmony_ci sp->vha, 0x3042, 33268c2ecf20Sopenharmony_ci (uint8_t *)&lcont_pkt, 33278c2ecf20Sopenharmony_ci REQUEST_ENTRY_SIZE); 33288c2ecf20Sopenharmony_ci } 33298c2ecf20Sopenharmony_ci } 33308c2ecf20Sopenharmony_ci if (avail_dsds != 0 && cont == 1) { 33318c2ecf20Sopenharmony_ci memcpy_toio((void __iomem *)cont_pkt, 33328c2ecf20Sopenharmony_ci &lcont_pkt, REQUEST_ENTRY_SIZE); 33338c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, 33348c2ecf20Sopenharmony_ci sp->vha, 0x3043, 33358c2ecf20Sopenharmony_ci (uint8_t *)&lcont_pkt, REQUEST_ENTRY_SIZE); 33368c2ecf20Sopenharmony_ci } 33378c2ecf20Sopenharmony_ci } 33388c2ecf20Sopenharmony_ci 33398c2ecf20Sopenharmony_ci if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID) { 33408c2ecf20Sopenharmony_ci int avail_dsds, tot_dsds; 33418c2ecf20Sopenharmony_ci cont_a64_entry_t lcont_pkt; 33428c2ecf20Sopenharmony_ci cont_a64_entry_t *cont_pkt = NULL; 33438c2ecf20Sopenharmony_ci struct dsd64 *cur_dsd; 33448c2ecf20Sopenharmony_ci int index = 0, cont = 0; 33458c2ecf20Sopenharmony_ci 33468c2ecf20Sopenharmony_ci fx_iocb.rsp_dsdcnt = 33478c2ecf20Sopenharmony_ci cpu_to_le16(bsg_job->reply_payload.sg_cnt); 33488c2ecf20Sopenharmony_ci tot_dsds = bsg_job->reply_payload.sg_cnt; 33498c2ecf20Sopenharmony_ci cur_dsd = &fx_iocb.dseg_rsp; 33508c2ecf20Sopenharmony_ci avail_dsds = 1; 33518c2ecf20Sopenharmony_ci 33528c2ecf20Sopenharmony_ci for_each_sg(bsg_job->reply_payload.sg_list, sg, 33538c2ecf20Sopenharmony_ci tot_dsds, index) { 33548c2ecf20Sopenharmony_ci /* Allocate additional continuation packets? */ 33558c2ecf20Sopenharmony_ci if (avail_dsds == 0) { 33568c2ecf20Sopenharmony_ci /* 33578c2ecf20Sopenharmony_ci * Five DSDs are available in the Cont. 33588c2ecf20Sopenharmony_ci * Type 1 IOCB. 33598c2ecf20Sopenharmony_ci */ 33608c2ecf20Sopenharmony_ci memset(&lcont_pkt, 0, 33618c2ecf20Sopenharmony_ci REQUEST_ENTRY_SIZE); 33628c2ecf20Sopenharmony_ci cont_pkt = 33638c2ecf20Sopenharmony_ci qlafx00_prep_cont_type1_iocb( 33648c2ecf20Sopenharmony_ci sp->vha->req, &lcont_pkt); 33658c2ecf20Sopenharmony_ci cur_dsd = lcont_pkt.dsd; 33668c2ecf20Sopenharmony_ci avail_dsds = 5; 33678c2ecf20Sopenharmony_ci cont = 1; 33688c2ecf20Sopenharmony_ci entry_cnt++; 33698c2ecf20Sopenharmony_ci } 33708c2ecf20Sopenharmony_ci 33718c2ecf20Sopenharmony_ci append_dsd64(&cur_dsd, sg); 33728c2ecf20Sopenharmony_ci avail_dsds--; 33738c2ecf20Sopenharmony_ci 33748c2ecf20Sopenharmony_ci if (avail_dsds == 0 && cont == 1) { 33758c2ecf20Sopenharmony_ci cont = 0; 33768c2ecf20Sopenharmony_ci memcpy_toio((void __iomem *)cont_pkt, 33778c2ecf20Sopenharmony_ci &lcont_pkt, 33788c2ecf20Sopenharmony_ci REQUEST_ENTRY_SIZE); 33798c2ecf20Sopenharmony_ci ql_dump_buffer( 33808c2ecf20Sopenharmony_ci ql_dbg_user + ql_dbg_verbose, 33818c2ecf20Sopenharmony_ci sp->vha, 0x3045, 33828c2ecf20Sopenharmony_ci (uint8_t *)&lcont_pkt, 33838c2ecf20Sopenharmony_ci REQUEST_ENTRY_SIZE); 33848c2ecf20Sopenharmony_ci } 33858c2ecf20Sopenharmony_ci } 33868c2ecf20Sopenharmony_ci if (avail_dsds != 0 && cont == 1) { 33878c2ecf20Sopenharmony_ci memcpy_toio((void __iomem *)cont_pkt, 33888c2ecf20Sopenharmony_ci &lcont_pkt, REQUEST_ENTRY_SIZE); 33898c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, 33908c2ecf20Sopenharmony_ci sp->vha, 0x3046, 33918c2ecf20Sopenharmony_ci (uint8_t *)&lcont_pkt, REQUEST_ENTRY_SIZE); 33928c2ecf20Sopenharmony_ci } 33938c2ecf20Sopenharmony_ci } 33948c2ecf20Sopenharmony_ci 33958c2ecf20Sopenharmony_ci if (piocb_rqst->flags & SRB_FXDISC_REQ_DWRD_VALID) 33968c2ecf20Sopenharmony_ci fx_iocb.dataword = piocb_rqst->dataword; 33978c2ecf20Sopenharmony_ci fx_iocb.flags = piocb_rqst->flags; 33988c2ecf20Sopenharmony_ci fx_iocb.entry_count = entry_cnt; 33998c2ecf20Sopenharmony_ci } 34008c2ecf20Sopenharmony_ci 34018c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, 34028c2ecf20Sopenharmony_ci sp->vha, 0x3047, &fx_iocb, sizeof(fx_iocb)); 34038c2ecf20Sopenharmony_ci 34048c2ecf20Sopenharmony_ci memcpy_toio((void __iomem *)pfxiocb, &fx_iocb, sizeof(fx_iocb)); 34058c2ecf20Sopenharmony_ci wmb(); 34068c2ecf20Sopenharmony_ci} 3407