177adf3f0SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
28ae6d9c7SGiridhar Malavali /*
38ae6d9c7SGiridhar Malavali * QLogic Fibre Channel HBA Driver
4bd21eaf9SArmen Baloyan * Copyright (c) 2003-2014 QLogic Corporation
58ae6d9c7SGiridhar Malavali */
68ae6d9c7SGiridhar Malavali #include "qla_def.h"
78ae6d9c7SGiridhar Malavali #include <linux/delay.h>
85ea33eb5STina Ruchandani #include <linux/ktime.h>
98ae6d9c7SGiridhar Malavali #include <linux/pci.h>
108ae6d9c7SGiridhar Malavali #include <linux/ratelimit.h>
118ae6d9c7SGiridhar Malavali #include <linux/vmalloc.h>
128ae6d9c7SGiridhar Malavali #include <scsi/scsi_tcq.h>
138ae6d9c7SGiridhar Malavali #include <linux/utsname.h>
148ae6d9c7SGiridhar Malavali
158ae6d9c7SGiridhar Malavali
168ae6d9c7SGiridhar Malavali /* QLAFX00 specific Mailbox implementation functions */
178ae6d9c7SGiridhar Malavali
188ae6d9c7SGiridhar Malavali /*
198ae6d9c7SGiridhar Malavali * qlafx00_mailbox_command
208ae6d9c7SGiridhar Malavali * Issue mailbox command and waits for completion.
218ae6d9c7SGiridhar Malavali *
228ae6d9c7SGiridhar Malavali * Input:
238ae6d9c7SGiridhar Malavali * ha = adapter block pointer.
248ae6d9c7SGiridhar Malavali * mcp = driver internal mbx struct pointer.
258ae6d9c7SGiridhar Malavali *
268ae6d9c7SGiridhar Malavali * Output:
278ae6d9c7SGiridhar Malavali * mb[MAX_MAILBOX_REGISTER_COUNT] = returned mailbox data.
288ae6d9c7SGiridhar Malavali *
298ae6d9c7SGiridhar Malavali * Returns:
308ae6d9c7SGiridhar Malavali * 0 : QLA_SUCCESS = cmd performed success
318ae6d9c7SGiridhar Malavali * 1 : QLA_FUNCTION_FAILED (error encountered)
328ae6d9c7SGiridhar Malavali * 6 : QLA_FUNCTION_TIMEOUT (timeout condition encountered)
338ae6d9c7SGiridhar Malavali *
348ae6d9c7SGiridhar Malavali * Context:
358ae6d9c7SGiridhar Malavali * Kernel context.
368ae6d9c7SGiridhar Malavali */
378ae6d9c7SGiridhar Malavali static int
qlafx00_mailbox_command(scsi_qla_host_t * vha,struct mbx_cmd_32 * mcp)388ae6d9c7SGiridhar Malavali qlafx00_mailbox_command(scsi_qla_host_t *vha, struct mbx_cmd_32 *mcp)
398ae6d9c7SGiridhar Malavali
408ae6d9c7SGiridhar Malavali {
418ae6d9c7SGiridhar Malavali int rval;
428ae6d9c7SGiridhar Malavali unsigned long flags = 0;
43f73cb695SChad Dupuis device_reg_t *reg;
448ae6d9c7SGiridhar Malavali uint8_t abort_active;
458ae6d9c7SGiridhar Malavali uint8_t io_lock_on;
468ae6d9c7SGiridhar Malavali uint16_t command = 0;
478ae6d9c7SGiridhar Malavali uint32_t *iptr;
4837139da1SBart Van Assche __le32 __iomem *optr;
498ae6d9c7SGiridhar Malavali uint32_t cnt;
508ae6d9c7SGiridhar Malavali uint32_t mboxes;
518ae6d9c7SGiridhar Malavali unsigned long wait_time;
528ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
538ae6d9c7SGiridhar Malavali scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
548ae6d9c7SGiridhar Malavali
55471298caSBart Van Assche if (ha->pdev->error_state == pci_channel_io_perm_failure) {
568ae6d9c7SGiridhar Malavali ql_log(ql_log_warn, vha, 0x115c,
57471298caSBart Van Assche "PCI channel failed permanently, exiting.\n");
588ae6d9c7SGiridhar Malavali return QLA_FUNCTION_TIMEOUT;
598ae6d9c7SGiridhar Malavali }
608ae6d9c7SGiridhar Malavali
618ae6d9c7SGiridhar Malavali if (vha->device_flags & DFLG_DEV_FAILED) {
628ae6d9c7SGiridhar Malavali ql_log(ql_log_warn, vha, 0x115f,
638ae6d9c7SGiridhar Malavali "Device in failed state, exiting.\n");
648ae6d9c7SGiridhar Malavali return QLA_FUNCTION_TIMEOUT;
658ae6d9c7SGiridhar Malavali }
668ae6d9c7SGiridhar Malavali
678ae6d9c7SGiridhar Malavali reg = ha->iobase;
688ae6d9c7SGiridhar Malavali io_lock_on = base_vha->flags.init_done;
698ae6d9c7SGiridhar Malavali
708ae6d9c7SGiridhar Malavali rval = QLA_SUCCESS;
718ae6d9c7SGiridhar Malavali abort_active = test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
728ae6d9c7SGiridhar Malavali
738ae6d9c7SGiridhar Malavali if (ha->flags.pci_channel_io_perm_failure) {
748ae6d9c7SGiridhar Malavali ql_log(ql_log_warn, vha, 0x1175,
758ae6d9c7SGiridhar Malavali "Perm failure on EEH timeout MBX, exiting.\n");
768ae6d9c7SGiridhar Malavali return QLA_FUNCTION_TIMEOUT;
778ae6d9c7SGiridhar Malavali }
788ae6d9c7SGiridhar Malavali
798ae6d9c7SGiridhar Malavali if (ha->flags.isp82xx_fw_hung) {
808ae6d9c7SGiridhar Malavali /* Setting Link-Down error */
818ae6d9c7SGiridhar Malavali mcp->mb[0] = MBS_LINK_DOWN_ERROR;
828ae6d9c7SGiridhar Malavali ql_log(ql_log_warn, vha, 0x1176,
838ae6d9c7SGiridhar Malavali "FW hung = %d.\n", ha->flags.isp82xx_fw_hung);
848ae6d9c7SGiridhar Malavali rval = QLA_FUNCTION_FAILED;
858ae6d9c7SGiridhar Malavali goto premature_exit;
868ae6d9c7SGiridhar Malavali }
878ae6d9c7SGiridhar Malavali
888ae6d9c7SGiridhar Malavali /*
898ae6d9c7SGiridhar Malavali * Wait for active mailbox commands to finish by waiting at most tov
908ae6d9c7SGiridhar Malavali * seconds. This is to serialize actual issuing of mailbox cmds during
918ae6d9c7SGiridhar Malavali * non ISP abort time.
928ae6d9c7SGiridhar Malavali */
938ae6d9c7SGiridhar Malavali if (!wait_for_completion_timeout(&ha->mbx_cmd_comp, mcp->tov * HZ)) {
948ae6d9c7SGiridhar Malavali /* Timeout occurred. Return error. */
958ae6d9c7SGiridhar Malavali ql_log(ql_log_warn, vha, 0x1177,
968ae6d9c7SGiridhar Malavali "Cmd access timeout, cmd=0x%x, Exiting.\n",
978ae6d9c7SGiridhar Malavali mcp->mb[0]);
988ae6d9c7SGiridhar Malavali return QLA_FUNCTION_TIMEOUT;
998ae6d9c7SGiridhar Malavali }
1008ae6d9c7SGiridhar Malavali
1018ae6d9c7SGiridhar Malavali ha->flags.mbox_busy = 1;
1028ae6d9c7SGiridhar Malavali /* Save mailbox command for debug */
1038ae6d9c7SGiridhar Malavali ha->mcp32 = mcp;
1048ae6d9c7SGiridhar Malavali
1058ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx, vha, 0x1178,
1068ae6d9c7SGiridhar Malavali "Prepare to issue mbox cmd=0x%x.\n", mcp->mb[0]);
1078ae6d9c7SGiridhar Malavali
1088ae6d9c7SGiridhar Malavali spin_lock_irqsave(&ha->hardware_lock, flags);
1098ae6d9c7SGiridhar Malavali
1108ae6d9c7SGiridhar Malavali /* Load mailbox registers. */
11137139da1SBart Van Assche optr = ®->ispfx00.mailbox0;
1128ae6d9c7SGiridhar Malavali
1138ae6d9c7SGiridhar Malavali iptr = mcp->mb;
1148ae6d9c7SGiridhar Malavali command = mcp->mb[0];
1158ae6d9c7SGiridhar Malavali mboxes = mcp->out_mb;
1168ae6d9c7SGiridhar Malavali
1178ae6d9c7SGiridhar Malavali for (cnt = 0; cnt < ha->mbx_count; cnt++) {
1188ae6d9c7SGiridhar Malavali if (mboxes & BIT_0)
11904474d3aSBart Van Assche wrt_reg_dword(optr, *iptr);
1208ae6d9c7SGiridhar Malavali
1218ae6d9c7SGiridhar Malavali mboxes >>= 1;
1228ae6d9c7SGiridhar Malavali optr++;
1238ae6d9c7SGiridhar Malavali iptr++;
1248ae6d9c7SGiridhar Malavali }
1258ae6d9c7SGiridhar Malavali
1268ae6d9c7SGiridhar Malavali /* Issue set host interrupt command to send cmd out. */
1278ae6d9c7SGiridhar Malavali ha->flags.mbox_int = 0;
1288ae6d9c7SGiridhar Malavali clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
1298ae6d9c7SGiridhar Malavali
1308ae6d9c7SGiridhar Malavali ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1172,
1318ae6d9c7SGiridhar Malavali (uint8_t *)mcp->mb, 16);
1328ae6d9c7SGiridhar Malavali ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1173,
1338ae6d9c7SGiridhar Malavali ((uint8_t *)mcp->mb + 0x10), 16);
1348ae6d9c7SGiridhar Malavali ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1174,
1358ae6d9c7SGiridhar Malavali ((uint8_t *)mcp->mb + 0x20), 8);
1368ae6d9c7SGiridhar Malavali
1378ae6d9c7SGiridhar Malavali /* Unlock mbx registers and wait for interrupt */
1388ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx, vha, 0x1179,
1398ae6d9c7SGiridhar Malavali "Going to unlock irq & waiting for interrupts. "
1408ae6d9c7SGiridhar Malavali "jiffies=%lx.\n", jiffies);
1418ae6d9c7SGiridhar Malavali
1428ae6d9c7SGiridhar Malavali /* Wait for mbx cmd completion until timeout */
1438ae6d9c7SGiridhar Malavali if ((!abort_active && io_lock_on) || IS_NOPOLLING_TYPE(ha)) {
1448ae6d9c7SGiridhar Malavali set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
1458ae6d9c7SGiridhar Malavali
1468ae6d9c7SGiridhar Malavali QLAFX00_SET_HST_INTR(ha, ha->mbx_intr_code);
1478ae6d9c7SGiridhar Malavali spin_unlock_irqrestore(&ha->hardware_lock, flags);
1488ae6d9c7SGiridhar Malavali
14958e060e1SBart Van Assche WARN_ON_ONCE(wait_for_completion_timeout(&ha->mbx_intr_comp,
15058e060e1SBart Van Assche mcp->tov * HZ) != 0);
1518ae6d9c7SGiridhar Malavali } else {
1528ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx, vha, 0x112c,
1538ae6d9c7SGiridhar Malavali "Cmd=%x Polling Mode.\n", command);
1548ae6d9c7SGiridhar Malavali
1558ae6d9c7SGiridhar Malavali QLAFX00_SET_HST_INTR(ha, ha->mbx_intr_code);
1568ae6d9c7SGiridhar Malavali spin_unlock_irqrestore(&ha->hardware_lock, flags);
1578ae6d9c7SGiridhar Malavali
1588ae6d9c7SGiridhar Malavali wait_time = jiffies + mcp->tov * HZ; /* wait at most tov secs */
1598ae6d9c7SGiridhar Malavali while (!ha->flags.mbox_int) {
1608ae6d9c7SGiridhar Malavali if (time_after(jiffies, wait_time))
1618ae6d9c7SGiridhar Malavali break;
1628ae6d9c7SGiridhar Malavali
1638ae6d9c7SGiridhar Malavali /* Check for pending interrupts. */
1648ae6d9c7SGiridhar Malavali qla2x00_poll(ha->rsp_q_map[0]);
1658ae6d9c7SGiridhar Malavali
1668ae6d9c7SGiridhar Malavali if (!ha->flags.mbox_int &&
1678ae6d9c7SGiridhar Malavali !(IS_QLA2200(ha) &&
1688ae6d9c7SGiridhar Malavali command == MBC_LOAD_RISC_RAM_EXTENDED))
1698ae6d9c7SGiridhar Malavali usleep_range(10000, 11000);
1708ae6d9c7SGiridhar Malavali } /* while */
1718ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx, vha, 0x112d,
1728ae6d9c7SGiridhar Malavali "Waited %d sec.\n",
1738ae6d9c7SGiridhar Malavali (uint)((jiffies - (wait_time - (mcp->tov * HZ)))/HZ));
1748ae6d9c7SGiridhar Malavali }
1758ae6d9c7SGiridhar Malavali
1768ae6d9c7SGiridhar Malavali /* Check whether we timed out */
1778ae6d9c7SGiridhar Malavali if (ha->flags.mbox_int) {
1788ae6d9c7SGiridhar Malavali uint32_t *iptr2;
1798ae6d9c7SGiridhar Malavali
1808ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx, vha, 0x112e,
1818ae6d9c7SGiridhar Malavali "Cmd=%x completed.\n", command);
1828ae6d9c7SGiridhar Malavali
1838ae6d9c7SGiridhar Malavali /* Got interrupt. Clear the flag. */
1848ae6d9c7SGiridhar Malavali ha->flags.mbox_int = 0;
1858ae6d9c7SGiridhar Malavali clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
1868ae6d9c7SGiridhar Malavali
1878ae6d9c7SGiridhar Malavali if (ha->mailbox_out32[0] != MBS_COMMAND_COMPLETE)
1888ae6d9c7SGiridhar Malavali rval = QLA_FUNCTION_FAILED;
1898ae6d9c7SGiridhar Malavali
1908ae6d9c7SGiridhar Malavali /* Load return mailbox registers. */
1918ae6d9c7SGiridhar Malavali iptr2 = mcp->mb;
1928ae6d9c7SGiridhar Malavali iptr = (uint32_t *)&ha->mailbox_out32[0];
1938ae6d9c7SGiridhar Malavali mboxes = mcp->in_mb;
1948ae6d9c7SGiridhar Malavali for (cnt = 0; cnt < ha->mbx_count; cnt++) {
1958ae6d9c7SGiridhar Malavali if (mboxes & BIT_0)
1968ae6d9c7SGiridhar Malavali *iptr2 = *iptr;
1978ae6d9c7SGiridhar Malavali
1988ae6d9c7SGiridhar Malavali mboxes >>= 1;
1998ae6d9c7SGiridhar Malavali iptr2++;
2008ae6d9c7SGiridhar Malavali iptr++;
2018ae6d9c7SGiridhar Malavali }
2028ae6d9c7SGiridhar Malavali } else {
2038ae6d9c7SGiridhar Malavali
2048ae6d9c7SGiridhar Malavali rval = QLA_FUNCTION_TIMEOUT;
2058ae6d9c7SGiridhar Malavali }
2068ae6d9c7SGiridhar Malavali
2078ae6d9c7SGiridhar Malavali ha->flags.mbox_busy = 0;
2088ae6d9c7SGiridhar Malavali
2098ae6d9c7SGiridhar Malavali /* Clean up */
2108ae6d9c7SGiridhar Malavali ha->mcp32 = NULL;
2118ae6d9c7SGiridhar Malavali
2128ae6d9c7SGiridhar Malavali if ((abort_active || !io_lock_on) && !IS_NOPOLLING_TYPE(ha)) {
2138ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx, vha, 0x113a,
2148ae6d9c7SGiridhar Malavali "checking for additional resp interrupt.\n");
2158ae6d9c7SGiridhar Malavali
2168ae6d9c7SGiridhar Malavali /* polling mode for non isp_abort commands. */
2178ae6d9c7SGiridhar Malavali qla2x00_poll(ha->rsp_q_map[0]);
2188ae6d9c7SGiridhar Malavali }
2198ae6d9c7SGiridhar Malavali
2208ae6d9c7SGiridhar Malavali if (rval == QLA_FUNCTION_TIMEOUT &&
2218ae6d9c7SGiridhar Malavali mcp->mb[0] != MBC_GEN_SYSTEM_ERROR) {
2228ae6d9c7SGiridhar Malavali if (!io_lock_on || (mcp->flags & IOCTL_CMD) ||
2238ae6d9c7SGiridhar Malavali ha->flags.eeh_busy) {
2248ae6d9c7SGiridhar Malavali /* not in dpc. schedule it for dpc to take over. */
2258ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx, vha, 0x115d,
2268ae6d9c7SGiridhar Malavali "Timeout, schedule isp_abort_needed.\n");
2278ae6d9c7SGiridhar Malavali
2288ae6d9c7SGiridhar Malavali if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) &&
2298ae6d9c7SGiridhar Malavali !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
2308ae6d9c7SGiridhar Malavali !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
2318ae6d9c7SGiridhar Malavali
2328ae6d9c7SGiridhar Malavali ql_log(ql_log_info, base_vha, 0x115e,
2338ae6d9c7SGiridhar Malavali "Mailbox cmd timeout occurred, cmd=0x%x, "
2348ae6d9c7SGiridhar Malavali "mb[0]=0x%x, eeh_busy=0x%x. Scheduling ISP "
2358ae6d9c7SGiridhar Malavali "abort.\n", command, mcp->mb[0],
2368ae6d9c7SGiridhar Malavali ha->flags.eeh_busy);
2378ae6d9c7SGiridhar Malavali set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
2388ae6d9c7SGiridhar Malavali qla2xxx_wake_dpc(vha);
2398ae6d9c7SGiridhar Malavali }
2408ae6d9c7SGiridhar Malavali } else if (!abort_active) {
2418ae6d9c7SGiridhar Malavali /* call abort directly since we are in the DPC thread */
2428ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx, vha, 0x1160,
2438ae6d9c7SGiridhar Malavali "Timeout, calling abort_isp.\n");
2448ae6d9c7SGiridhar Malavali
2458ae6d9c7SGiridhar Malavali if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) &&
2468ae6d9c7SGiridhar Malavali !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
2478ae6d9c7SGiridhar Malavali !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
2488ae6d9c7SGiridhar Malavali
2498ae6d9c7SGiridhar Malavali ql_log(ql_log_info, base_vha, 0x1161,
2508ae6d9c7SGiridhar Malavali "Mailbox cmd timeout occurred, cmd=0x%x, "
2518ae6d9c7SGiridhar Malavali "mb[0]=0x%x. Scheduling ISP abort ",
2528ae6d9c7SGiridhar Malavali command, mcp->mb[0]);
2538ae6d9c7SGiridhar Malavali
2548ae6d9c7SGiridhar Malavali set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
2558ae6d9c7SGiridhar Malavali clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
2568ae6d9c7SGiridhar Malavali if (ha->isp_ops->abort_isp(vha)) {
2578ae6d9c7SGiridhar Malavali /* Failed. retry later. */
2588ae6d9c7SGiridhar Malavali set_bit(ISP_ABORT_NEEDED,
2598ae6d9c7SGiridhar Malavali &vha->dpc_flags);
2608ae6d9c7SGiridhar Malavali }
2618ae6d9c7SGiridhar Malavali clear_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
2628ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx, vha, 0x1162,
2638ae6d9c7SGiridhar Malavali "Finished abort_isp.\n");
2648ae6d9c7SGiridhar Malavali }
2658ae6d9c7SGiridhar Malavali }
2668ae6d9c7SGiridhar Malavali }
2678ae6d9c7SGiridhar Malavali
2688ae6d9c7SGiridhar Malavali premature_exit:
2698ae6d9c7SGiridhar Malavali /* Allow next mbx cmd to come in. */
2708ae6d9c7SGiridhar Malavali complete(&ha->mbx_cmd_comp);
2718ae6d9c7SGiridhar Malavali
2728ae6d9c7SGiridhar Malavali if (rval) {
2738ae6d9c7SGiridhar Malavali ql_log(ql_log_warn, base_vha, 0x1163,
2743f918ffaSBart Van Assche "**** Failed=%x mbx[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x, cmd=%x ****.\n",
2753f918ffaSBart Van Assche rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3],
2763f918ffaSBart Van Assche command);
2778ae6d9c7SGiridhar Malavali } else {
2788ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx, base_vha, 0x1164, "Done %s.\n", __func__);
2798ae6d9c7SGiridhar Malavali }
2808ae6d9c7SGiridhar Malavali
2818ae6d9c7SGiridhar Malavali return rval;
2828ae6d9c7SGiridhar Malavali }
2838ae6d9c7SGiridhar Malavali
2848ae6d9c7SGiridhar Malavali /*
2858ae6d9c7SGiridhar Malavali * qlafx00_driver_shutdown
2868ae6d9c7SGiridhar Malavali * Indicate a driver shutdown to firmware.
2878ae6d9c7SGiridhar Malavali *
2888ae6d9c7SGiridhar Malavali * Input:
2898ae6d9c7SGiridhar Malavali * ha = adapter block pointer.
2908ae6d9c7SGiridhar Malavali *
2918ae6d9c7SGiridhar Malavali * Returns:
2928ae6d9c7SGiridhar Malavali * local function return status code.
2938ae6d9c7SGiridhar Malavali *
2948ae6d9c7SGiridhar Malavali * Context:
2958ae6d9c7SGiridhar Malavali * Kernel context.
2968ae6d9c7SGiridhar Malavali */
29742479343SArmen Baloyan int
qlafx00_driver_shutdown(scsi_qla_host_t * vha,int tmo)2988ae6d9c7SGiridhar Malavali qlafx00_driver_shutdown(scsi_qla_host_t *vha, int tmo)
2998ae6d9c7SGiridhar Malavali {
3008ae6d9c7SGiridhar Malavali int rval;
3018ae6d9c7SGiridhar Malavali struct mbx_cmd_32 mc;
3028ae6d9c7SGiridhar Malavali struct mbx_cmd_32 *mcp = &mc;
3038ae6d9c7SGiridhar Malavali
3048ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1166,
3058ae6d9c7SGiridhar Malavali "Entered %s.\n", __func__);
3068ae6d9c7SGiridhar Malavali
3078ae6d9c7SGiridhar Malavali mcp->mb[0] = MBC_MR_DRV_SHUTDOWN;
3088ae6d9c7SGiridhar Malavali mcp->out_mb = MBX_0;
3098ae6d9c7SGiridhar Malavali mcp->in_mb = MBX_0;
3108ae6d9c7SGiridhar Malavali if (tmo)
3118ae6d9c7SGiridhar Malavali mcp->tov = tmo;
3128ae6d9c7SGiridhar Malavali else
3138ae6d9c7SGiridhar Malavali mcp->tov = MBX_TOV_SECONDS;
3148ae6d9c7SGiridhar Malavali mcp->flags = 0;
3158ae6d9c7SGiridhar Malavali rval = qlafx00_mailbox_command(vha, mcp);
3168ae6d9c7SGiridhar Malavali
3178ae6d9c7SGiridhar Malavali if (rval != QLA_SUCCESS) {
3188ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx, vha, 0x1167,
3198ae6d9c7SGiridhar Malavali "Failed=%x.\n", rval);
3208ae6d9c7SGiridhar Malavali } else {
3218ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1168,
3228ae6d9c7SGiridhar Malavali "Done %s.\n", __func__);
3238ae6d9c7SGiridhar Malavali }
3248ae6d9c7SGiridhar Malavali
3258ae6d9c7SGiridhar Malavali return rval;
3268ae6d9c7SGiridhar Malavali }
3278ae6d9c7SGiridhar Malavali
3288ae6d9c7SGiridhar Malavali /*
3298ae6d9c7SGiridhar Malavali * qlafx00_get_firmware_state
3308ae6d9c7SGiridhar Malavali * Get adapter firmware state.
3318ae6d9c7SGiridhar Malavali *
3328ae6d9c7SGiridhar Malavali * Input:
3338ae6d9c7SGiridhar Malavali * ha = adapter block pointer.
3348ae6d9c7SGiridhar Malavali * TARGET_QUEUE_LOCK must be released.
3358ae6d9c7SGiridhar Malavali * ADAPTER_STATE_LOCK must be released.
3368ae6d9c7SGiridhar Malavali *
3378ae6d9c7SGiridhar Malavali * Returns:
3388ae6d9c7SGiridhar Malavali * qla7xxx local function return status code.
3398ae6d9c7SGiridhar Malavali *
3408ae6d9c7SGiridhar Malavali * Context:
3418ae6d9c7SGiridhar Malavali * Kernel context.
3428ae6d9c7SGiridhar Malavali */
3438ae6d9c7SGiridhar Malavali static int
qlafx00_get_firmware_state(scsi_qla_host_t * vha,uint32_t * states)3448ae6d9c7SGiridhar Malavali qlafx00_get_firmware_state(scsi_qla_host_t *vha, uint32_t *states)
3458ae6d9c7SGiridhar Malavali {
3468ae6d9c7SGiridhar Malavali int rval;
3478ae6d9c7SGiridhar Malavali struct mbx_cmd_32 mc;
3488ae6d9c7SGiridhar Malavali struct mbx_cmd_32 *mcp = &mc;
3498ae6d9c7SGiridhar Malavali
3508ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1169,
3518ae6d9c7SGiridhar Malavali "Entered %s.\n", __func__);
3528ae6d9c7SGiridhar Malavali
3538ae6d9c7SGiridhar Malavali mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
3548ae6d9c7SGiridhar Malavali mcp->out_mb = MBX_0;
3558ae6d9c7SGiridhar Malavali mcp->in_mb = MBX_1|MBX_0;
3568ae6d9c7SGiridhar Malavali mcp->tov = MBX_TOV_SECONDS;
3578ae6d9c7SGiridhar Malavali mcp->flags = 0;
3588ae6d9c7SGiridhar Malavali rval = qlafx00_mailbox_command(vha, mcp);
3598ae6d9c7SGiridhar Malavali
3608ae6d9c7SGiridhar Malavali /* Return firmware states. */
3618ae6d9c7SGiridhar Malavali states[0] = mcp->mb[1];
3628ae6d9c7SGiridhar Malavali
3638ae6d9c7SGiridhar Malavali if (rval != QLA_SUCCESS) {
3648ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx, vha, 0x116a,
3658ae6d9c7SGiridhar Malavali "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
3668ae6d9c7SGiridhar Malavali } else {
3678ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x116b,
3688ae6d9c7SGiridhar Malavali "Done %s.\n", __func__);
3698ae6d9c7SGiridhar Malavali }
3708ae6d9c7SGiridhar Malavali return rval;
3718ae6d9c7SGiridhar Malavali }
3728ae6d9c7SGiridhar Malavali
3738ae6d9c7SGiridhar Malavali /*
3748ae6d9c7SGiridhar Malavali * qlafx00_init_firmware
3758ae6d9c7SGiridhar Malavali * Initialize adapter firmware.
3768ae6d9c7SGiridhar Malavali *
3778ae6d9c7SGiridhar Malavali * Input:
3788ae6d9c7SGiridhar Malavali * ha = adapter block pointer.
3798ae6d9c7SGiridhar Malavali * dptr = Initialization control block pointer.
3808ae6d9c7SGiridhar Malavali * size = size of initialization control block.
3818ae6d9c7SGiridhar Malavali * TARGET_QUEUE_LOCK must be released.
3828ae6d9c7SGiridhar Malavali * ADAPTER_STATE_LOCK must be released.
3838ae6d9c7SGiridhar Malavali *
3848ae6d9c7SGiridhar Malavali * Returns:
3858ae6d9c7SGiridhar Malavali * qlafx00 local function return status code.
3868ae6d9c7SGiridhar Malavali *
3878ae6d9c7SGiridhar Malavali * Context:
3888ae6d9c7SGiridhar Malavali * Kernel context.
3898ae6d9c7SGiridhar Malavali */
3908ae6d9c7SGiridhar Malavali int
qlafx00_init_firmware(scsi_qla_host_t * vha,uint16_t size)3918ae6d9c7SGiridhar Malavali qlafx00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
3928ae6d9c7SGiridhar Malavali {
3938ae6d9c7SGiridhar Malavali int rval;
3948ae6d9c7SGiridhar Malavali struct mbx_cmd_32 mc;
3958ae6d9c7SGiridhar Malavali struct mbx_cmd_32 *mcp = &mc;
3968ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
3978ae6d9c7SGiridhar Malavali
3988ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x116c,
3998ae6d9c7SGiridhar Malavali "Entered %s.\n", __func__);
4008ae6d9c7SGiridhar Malavali
4018ae6d9c7SGiridhar Malavali mcp->mb[0] = MBC_INITIALIZE_FIRMWARE;
4028ae6d9c7SGiridhar Malavali
4038ae6d9c7SGiridhar Malavali mcp->mb[1] = 0;
4048ae6d9c7SGiridhar Malavali mcp->mb[2] = MSD(ha->init_cb_dma);
4058ae6d9c7SGiridhar Malavali mcp->mb[3] = LSD(ha->init_cb_dma);
4068ae6d9c7SGiridhar Malavali
4078ae6d9c7SGiridhar Malavali mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
4088ae6d9c7SGiridhar Malavali mcp->in_mb = MBX_0;
4098ae6d9c7SGiridhar Malavali mcp->buf_size = size;
4108ae6d9c7SGiridhar Malavali mcp->flags = MBX_DMA_OUT;
4118ae6d9c7SGiridhar Malavali mcp->tov = MBX_TOV_SECONDS;
4128ae6d9c7SGiridhar Malavali rval = qlafx00_mailbox_command(vha, mcp);
4138ae6d9c7SGiridhar Malavali
4148ae6d9c7SGiridhar Malavali if (rval != QLA_SUCCESS) {
4158ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx, vha, 0x116d,
4168ae6d9c7SGiridhar Malavali "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
4178ae6d9c7SGiridhar Malavali } else {
4188ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x116e,
4198ae6d9c7SGiridhar Malavali "Done %s.\n", __func__);
4208ae6d9c7SGiridhar Malavali }
4218ae6d9c7SGiridhar Malavali return rval;
4228ae6d9c7SGiridhar Malavali }
4238ae6d9c7SGiridhar Malavali
4248ae6d9c7SGiridhar Malavali /*
4258ae6d9c7SGiridhar Malavali * qlafx00_mbx_reg_test
4268ae6d9c7SGiridhar Malavali */
4278ae6d9c7SGiridhar Malavali static int
qlafx00_mbx_reg_test(scsi_qla_host_t * vha)4288ae6d9c7SGiridhar Malavali qlafx00_mbx_reg_test(scsi_qla_host_t *vha)
4298ae6d9c7SGiridhar Malavali {
4308ae6d9c7SGiridhar Malavali int rval;
4318ae6d9c7SGiridhar Malavali struct mbx_cmd_32 mc;
4328ae6d9c7SGiridhar Malavali struct mbx_cmd_32 *mcp = &mc;
4338ae6d9c7SGiridhar Malavali
4348ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x116f,
4358ae6d9c7SGiridhar Malavali "Entered %s.\n", __func__);
4368ae6d9c7SGiridhar Malavali
4378ae6d9c7SGiridhar Malavali
4388ae6d9c7SGiridhar Malavali mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST;
4398ae6d9c7SGiridhar Malavali mcp->mb[1] = 0xAAAA;
4408ae6d9c7SGiridhar Malavali mcp->mb[2] = 0x5555;
4418ae6d9c7SGiridhar Malavali mcp->mb[3] = 0xAA55;
4428ae6d9c7SGiridhar Malavali mcp->mb[4] = 0x55AA;
4438ae6d9c7SGiridhar Malavali mcp->mb[5] = 0xA5A5;
4448ae6d9c7SGiridhar Malavali mcp->mb[6] = 0x5A5A;
4458ae6d9c7SGiridhar Malavali mcp->mb[7] = 0x2525;
4468ae6d9c7SGiridhar Malavali mcp->mb[8] = 0xBBBB;
4478ae6d9c7SGiridhar Malavali mcp->mb[9] = 0x6666;
4488ae6d9c7SGiridhar Malavali mcp->mb[10] = 0xBB66;
4498ae6d9c7SGiridhar Malavali mcp->mb[11] = 0x66BB;
4508ae6d9c7SGiridhar Malavali mcp->mb[12] = 0xB6B6;
4518ae6d9c7SGiridhar Malavali mcp->mb[13] = 0x6B6B;
4528ae6d9c7SGiridhar Malavali mcp->mb[14] = 0x3636;
4538ae6d9c7SGiridhar Malavali mcp->mb[15] = 0xCCCC;
4548ae6d9c7SGiridhar Malavali
4558ae6d9c7SGiridhar Malavali
4568ae6d9c7SGiridhar Malavali mcp->out_mb = MBX_15|MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|
4578ae6d9c7SGiridhar Malavali MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4588ae6d9c7SGiridhar Malavali mcp->in_mb = MBX_15|MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|
4598ae6d9c7SGiridhar Malavali MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4608ae6d9c7SGiridhar Malavali mcp->buf_size = 0;
4618ae6d9c7SGiridhar Malavali mcp->flags = MBX_DMA_OUT;
4628ae6d9c7SGiridhar Malavali mcp->tov = MBX_TOV_SECONDS;
4638ae6d9c7SGiridhar Malavali rval = qlafx00_mailbox_command(vha, mcp);
4648ae6d9c7SGiridhar Malavali if (rval == QLA_SUCCESS) {
4658ae6d9c7SGiridhar Malavali if (mcp->mb[17] != 0xAAAA || mcp->mb[18] != 0x5555 ||
4668ae6d9c7SGiridhar Malavali mcp->mb[19] != 0xAA55 || mcp->mb[20] != 0x55AA)
4678ae6d9c7SGiridhar Malavali rval = QLA_FUNCTION_FAILED;
4688ae6d9c7SGiridhar Malavali if (mcp->mb[21] != 0xA5A5 || mcp->mb[22] != 0x5A5A ||
4698ae6d9c7SGiridhar Malavali mcp->mb[23] != 0x2525 || mcp->mb[24] != 0xBBBB)
4708ae6d9c7SGiridhar Malavali rval = QLA_FUNCTION_FAILED;
4718ae6d9c7SGiridhar Malavali if (mcp->mb[25] != 0x6666 || mcp->mb[26] != 0xBB66 ||
4728ae6d9c7SGiridhar Malavali mcp->mb[27] != 0x66BB || mcp->mb[28] != 0xB6B6)
4738ae6d9c7SGiridhar Malavali rval = QLA_FUNCTION_FAILED;
4748ae6d9c7SGiridhar Malavali if (mcp->mb[29] != 0x6B6B || mcp->mb[30] != 0x3636 ||
4758ae6d9c7SGiridhar Malavali mcp->mb[31] != 0xCCCC)
4768ae6d9c7SGiridhar Malavali rval = QLA_FUNCTION_FAILED;
4778ae6d9c7SGiridhar Malavali }
4788ae6d9c7SGiridhar Malavali
4798ae6d9c7SGiridhar Malavali if (rval != QLA_SUCCESS) {
4808ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx, vha, 0x1170,
4818ae6d9c7SGiridhar Malavali "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
4828ae6d9c7SGiridhar Malavali } else {
4838ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1171,
4848ae6d9c7SGiridhar Malavali "Done %s.\n", __func__);
4858ae6d9c7SGiridhar Malavali }
4868ae6d9c7SGiridhar Malavali return rval;
4878ae6d9c7SGiridhar Malavali }
4888ae6d9c7SGiridhar Malavali
4898ae6d9c7SGiridhar Malavali /**
4908ae6d9c7SGiridhar Malavali * qlafx00_pci_config() - Setup ISPFx00 PCI configuration registers.
4912db6228dSBart Van Assche * @vha: HA context
4928ae6d9c7SGiridhar Malavali *
4938ae6d9c7SGiridhar Malavali * Returns 0 on success.
4948ae6d9c7SGiridhar Malavali */
4958ae6d9c7SGiridhar Malavali int
qlafx00_pci_config(scsi_qla_host_t * vha)4968ae6d9c7SGiridhar Malavali qlafx00_pci_config(scsi_qla_host_t *vha)
4978ae6d9c7SGiridhar Malavali {
4988ae6d9c7SGiridhar Malavali uint16_t w;
4998ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
5008ae6d9c7SGiridhar Malavali
5018ae6d9c7SGiridhar Malavali pci_set_master(ha->pdev);
5028ae6d9c7SGiridhar Malavali pci_try_set_mwi(ha->pdev);
5038ae6d9c7SGiridhar Malavali
5048ae6d9c7SGiridhar Malavali pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
5058ae6d9c7SGiridhar Malavali w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
5068ae6d9c7SGiridhar Malavali w &= ~PCI_COMMAND_INTX_DISABLE;
5078ae6d9c7SGiridhar Malavali pci_write_config_word(ha->pdev, PCI_COMMAND, w);
5088ae6d9c7SGiridhar Malavali
5098ae6d9c7SGiridhar Malavali /* PCIe -- adjust Maximum Read Request Size (2048). */
510ce9f7ed9SYijing Wang if (pci_is_pcie(ha->pdev))
5118ae6d9c7SGiridhar Malavali pcie_set_readrq(ha->pdev, 2048);
5128ae6d9c7SGiridhar Malavali
5138ae6d9c7SGiridhar Malavali ha->chip_revision = ha->pdev->revision;
5148ae6d9c7SGiridhar Malavali
5158ae6d9c7SGiridhar Malavali return QLA_SUCCESS;
5168ae6d9c7SGiridhar Malavali }
5178ae6d9c7SGiridhar Malavali
5188ae6d9c7SGiridhar Malavali /**
51938109566SLee Jones * qlafx00_soc_cpu_reset() - Perform warm reset of iSA(CPUs being reset on SOC).
5202db6228dSBart Van Assche * @vha: HA context
5218ae6d9c7SGiridhar Malavali *
5228ae6d9c7SGiridhar Malavali */
5238ae6d9c7SGiridhar Malavali static inline void
qlafx00_soc_cpu_reset(scsi_qla_host_t * vha)5248ae6d9c7SGiridhar Malavali qlafx00_soc_cpu_reset(scsi_qla_host_t *vha)
5258ae6d9c7SGiridhar Malavali {
5268ae6d9c7SGiridhar Malavali unsigned long flags = 0;
5278ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
5288ae6d9c7SGiridhar Malavali int i, core;
5298ae6d9c7SGiridhar Malavali uint32_t cnt;
53042543fb9SArmen Baloyan uint32_t reg_val;
53142543fb9SArmen Baloyan
53242543fb9SArmen Baloyan spin_lock_irqsave(&ha->hardware_lock, flags);
53342543fb9SArmen Baloyan
53442543fb9SArmen Baloyan QLAFX00_SET_HBA_SOC_REG(ha, 0x80004, 0);
53542543fb9SArmen Baloyan QLAFX00_SET_HBA_SOC_REG(ha, 0x82004, 0);
53642543fb9SArmen Baloyan
53742543fb9SArmen Baloyan /* stop the XOR DMA engines */
53842543fb9SArmen Baloyan QLAFX00_SET_HBA_SOC_REG(ha, 0x60920, 0x02);
53942543fb9SArmen Baloyan QLAFX00_SET_HBA_SOC_REG(ha, 0x60924, 0x02);
54042543fb9SArmen Baloyan QLAFX00_SET_HBA_SOC_REG(ha, 0xf0920, 0x02);
54142543fb9SArmen Baloyan QLAFX00_SET_HBA_SOC_REG(ha, 0xf0924, 0x02);
54242543fb9SArmen Baloyan
54342543fb9SArmen Baloyan /* stop the IDMA engines */
54442543fb9SArmen Baloyan reg_val = QLAFX00_GET_HBA_SOC_REG(ha, 0x60840);
54542543fb9SArmen Baloyan reg_val &= ~(1<<12);
54642543fb9SArmen Baloyan QLAFX00_SET_HBA_SOC_REG(ha, 0x60840, reg_val);
54742543fb9SArmen Baloyan
54842543fb9SArmen Baloyan reg_val = QLAFX00_GET_HBA_SOC_REG(ha, 0x60844);
54942543fb9SArmen Baloyan reg_val &= ~(1<<12);
55042543fb9SArmen Baloyan QLAFX00_SET_HBA_SOC_REG(ha, 0x60844, reg_val);
55142543fb9SArmen Baloyan
55242543fb9SArmen Baloyan reg_val = QLAFX00_GET_HBA_SOC_REG(ha, 0x60848);
55342543fb9SArmen Baloyan reg_val &= ~(1<<12);
55442543fb9SArmen Baloyan QLAFX00_SET_HBA_SOC_REG(ha, 0x60848, reg_val);
55542543fb9SArmen Baloyan
55642543fb9SArmen Baloyan reg_val = QLAFX00_GET_HBA_SOC_REG(ha, 0x6084C);
55742543fb9SArmen Baloyan reg_val &= ~(1<<12);
55842543fb9SArmen Baloyan QLAFX00_SET_HBA_SOC_REG(ha, 0x6084C, reg_val);
55942543fb9SArmen Baloyan
56042543fb9SArmen Baloyan for (i = 0; i < 100000; i++) {
56142543fb9SArmen Baloyan if ((QLAFX00_GET_HBA_SOC_REG(ha, 0xd0000) & 0x10000000) == 0 &&
56242543fb9SArmen Baloyan (QLAFX00_GET_HBA_SOC_REG(ha, 0x10600) & 0x1) == 0)
56342543fb9SArmen Baloyan break;
56442543fb9SArmen Baloyan udelay(100);
56542543fb9SArmen Baloyan }
5668ae6d9c7SGiridhar Malavali
5678ae6d9c7SGiridhar Malavali /* Set all 4 cores in reset */
5688ae6d9c7SGiridhar Malavali for (i = 0; i < 4; i++) {
5698ae6d9c7SGiridhar Malavali QLAFX00_SET_HBA_SOC_REG(ha,
5708ae6d9c7SGiridhar Malavali (SOC_SW_RST_CONTROL_REG_CORE0 + 8*i), (0xF01));
5718ae6d9c7SGiridhar Malavali QLAFX00_SET_HBA_SOC_REG(ha,
5728ae6d9c7SGiridhar Malavali (SOC_SW_RST_CONTROL_REG_CORE0 + 4 + 8*i), (0x01010101));
5738ae6d9c7SGiridhar Malavali }
5748ae6d9c7SGiridhar Malavali
5758ae6d9c7SGiridhar Malavali /* Reset all units in Fabric */
57642543fb9SArmen Baloyan QLAFX00_SET_HBA_SOC_REG(ha, SOC_FABRIC_RST_CONTROL_REG, (0x011f0101));
57742543fb9SArmen Baloyan
57842543fb9SArmen Baloyan /* */
57942543fb9SArmen Baloyan QLAFX00_SET_HBA_SOC_REG(ha, 0x10610, 1);
58042543fb9SArmen Baloyan QLAFX00_SET_HBA_SOC_REG(ha, 0x10600, 0);
58142543fb9SArmen Baloyan
58242543fb9SArmen Baloyan /* Set all 4 core Memory Power Down Registers */
58342543fb9SArmen Baloyan for (i = 0; i < 5; i++) {
58442543fb9SArmen Baloyan QLAFX00_SET_HBA_SOC_REG(ha,
58542543fb9SArmen Baloyan (SOC_PWR_MANAGEMENT_PWR_DOWN_REG + 4*i), (0x0));
58642543fb9SArmen Baloyan }
5878ae6d9c7SGiridhar Malavali
5888ae6d9c7SGiridhar Malavali /* Reset all interrupt control registers */
5898ae6d9c7SGiridhar Malavali for (i = 0; i < 115; i++) {
5908ae6d9c7SGiridhar Malavali QLAFX00_SET_HBA_SOC_REG(ha,
5918ae6d9c7SGiridhar Malavali (SOC_INTERRUPT_SOURCE_I_CONTROL_REG + 4*i), (0x0));
5928ae6d9c7SGiridhar Malavali }
5938ae6d9c7SGiridhar Malavali
5948ae6d9c7SGiridhar Malavali /* Reset Timers control registers. per core */
5958ae6d9c7SGiridhar Malavali for (core = 0; core < 4; core++)
5968ae6d9c7SGiridhar Malavali for (i = 0; i < 8; i++)
5978ae6d9c7SGiridhar Malavali QLAFX00_SET_HBA_SOC_REG(ha,
5988ae6d9c7SGiridhar Malavali (SOC_CORE_TIMER_REG + 0x100*core + 4*i), (0x0));
5998ae6d9c7SGiridhar Malavali
6008ae6d9c7SGiridhar Malavali /* Reset per core IRQ ack register */
6018ae6d9c7SGiridhar Malavali for (core = 0; core < 4; core++)
6028ae6d9c7SGiridhar Malavali QLAFX00_SET_HBA_SOC_REG(ha,
6038ae6d9c7SGiridhar Malavali (SOC_IRQ_ACK_REG + 0x100*core), (0x3FF));
6048ae6d9c7SGiridhar Malavali
6058ae6d9c7SGiridhar Malavali /* Set Fabric control and config to defaults */
6068ae6d9c7SGiridhar Malavali QLAFX00_SET_HBA_SOC_REG(ha, SOC_FABRIC_CONTROL_REG, (0x2));
6078ae6d9c7SGiridhar Malavali QLAFX00_SET_HBA_SOC_REG(ha, SOC_FABRIC_CONFIG_REG, (0x3));
6088ae6d9c7SGiridhar Malavali
6098ae6d9c7SGiridhar Malavali /* Kick in Fabric units */
6108ae6d9c7SGiridhar Malavali QLAFX00_SET_HBA_SOC_REG(ha, SOC_FABRIC_RST_CONTROL_REG, (0x0));
6118ae6d9c7SGiridhar Malavali
6128ae6d9c7SGiridhar Malavali /* Kick in Core0 to start boot process */
6138ae6d9c7SGiridhar Malavali QLAFX00_SET_HBA_SOC_REG(ha, SOC_SW_RST_CONTROL_REG_CORE0, (0xF00));
6148ae6d9c7SGiridhar Malavali
615ec1937a2SSaurav Kashyap spin_unlock_irqrestore(&ha->hardware_lock, flags);
616ec1937a2SSaurav Kashyap
6178ae6d9c7SGiridhar Malavali /* Wait 10secs for soft-reset to complete. */
6188ae6d9c7SGiridhar Malavali for (cnt = 10; cnt; cnt--) {
6198ae6d9c7SGiridhar Malavali msleep(1000);
6208ae6d9c7SGiridhar Malavali barrier();
6218ae6d9c7SGiridhar Malavali }
6228ae6d9c7SGiridhar Malavali }
6238ae6d9c7SGiridhar Malavali
6248ae6d9c7SGiridhar Malavali /**
6258ae6d9c7SGiridhar Malavali * qlafx00_soft_reset() - Soft Reset ISPFx00.
6262db6228dSBart Van Assche * @vha: HA context
6278ae6d9c7SGiridhar Malavali *
6288ae6d9c7SGiridhar Malavali * Returns 0 on success.
6298ae6d9c7SGiridhar Malavali */
6303f006ac3SMichael Hernandez int
qlafx00_soft_reset(scsi_qla_host_t * vha)6318ae6d9c7SGiridhar Malavali qlafx00_soft_reset(scsi_qla_host_t *vha)
6328ae6d9c7SGiridhar Malavali {
6338ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
6343f006ac3SMichael Hernandez int rval = QLA_FUNCTION_FAILED;
6358ae6d9c7SGiridhar Malavali
6368ae6d9c7SGiridhar Malavali if (unlikely(pci_channel_offline(ha->pdev) &&
6378ae6d9c7SGiridhar Malavali ha->flags.pci_channel_io_perm_failure))
6383f006ac3SMichael Hernandez return rval;
6398ae6d9c7SGiridhar Malavali
6408ae6d9c7SGiridhar Malavali ha->isp_ops->disable_intrs(ha);
6418ae6d9c7SGiridhar Malavali qlafx00_soc_cpu_reset(vha);
6423f006ac3SMichael Hernandez
6433f006ac3SMichael Hernandez return QLA_SUCCESS;
6448ae6d9c7SGiridhar Malavali }
6458ae6d9c7SGiridhar Malavali
6468ae6d9c7SGiridhar Malavali /**
6478ae6d9c7SGiridhar Malavali * qlafx00_chip_diag() - Test ISPFx00 for proper operation.
6482db6228dSBart Van Assche * @vha: HA context
6498ae6d9c7SGiridhar Malavali *
6508ae6d9c7SGiridhar Malavali * Returns 0 on success.
6518ae6d9c7SGiridhar Malavali */
6528ae6d9c7SGiridhar Malavali int
qlafx00_chip_diag(scsi_qla_host_t * vha)6538ae6d9c7SGiridhar Malavali qlafx00_chip_diag(scsi_qla_host_t *vha)
6548ae6d9c7SGiridhar Malavali {
6558ae6d9c7SGiridhar Malavali int rval = 0;
6568ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
6578ae6d9c7SGiridhar Malavali struct req_que *req = ha->req_q_map[0];
6588ae6d9c7SGiridhar Malavali
6598ae6d9c7SGiridhar Malavali ha->fw_transfer_size = REQUEST_ENTRY_SIZE * req->length;
6608ae6d9c7SGiridhar Malavali
6618ae6d9c7SGiridhar Malavali rval = qlafx00_mbx_reg_test(vha);
6628ae6d9c7SGiridhar Malavali if (rval) {
6638ae6d9c7SGiridhar Malavali ql_log(ql_log_warn, vha, 0x1165,
6648ae6d9c7SGiridhar Malavali "Failed mailbox send register test\n");
6658ae6d9c7SGiridhar Malavali } else {
6668ae6d9c7SGiridhar Malavali /* Flag a successful rval */
6678ae6d9c7SGiridhar Malavali rval = QLA_SUCCESS;
6688ae6d9c7SGiridhar Malavali }
6698ae6d9c7SGiridhar Malavali return rval;
6708ae6d9c7SGiridhar Malavali }
6718ae6d9c7SGiridhar Malavali
6728ae6d9c7SGiridhar Malavali void
qlafx00_config_rings(struct scsi_qla_host * vha)6738ae6d9c7SGiridhar Malavali qlafx00_config_rings(struct scsi_qla_host *vha)
6748ae6d9c7SGiridhar Malavali {
6758ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
6768ae6d9c7SGiridhar Malavali struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00;
6778ae6d9c7SGiridhar Malavali
67804474d3aSBart Van Assche wrt_reg_dword(®->req_q_in, 0);
67904474d3aSBart Van Assche wrt_reg_dword(®->req_q_out, 0);
6808ae6d9c7SGiridhar Malavali
68104474d3aSBart Van Assche wrt_reg_dword(®->rsp_q_in, 0);
68204474d3aSBart Van Assche wrt_reg_dword(®->rsp_q_out, 0);
6838ae6d9c7SGiridhar Malavali
6848ae6d9c7SGiridhar Malavali /* PCI posting */
68504474d3aSBart Van Assche rd_reg_dword(®->rsp_q_out);
6868ae6d9c7SGiridhar Malavali }
6878ae6d9c7SGiridhar Malavali
6888ae6d9c7SGiridhar Malavali char *
qlafx00_pci_info_str(struct scsi_qla_host * vha,char * str,size_t str_len)689dc6d6d34SBart Van Assche qlafx00_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len)
6908ae6d9c7SGiridhar Malavali {
6918ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
6928ae6d9c7SGiridhar Malavali
693dc6d6d34SBart Van Assche if (pci_is_pcie(ha->pdev))
69437f1663cSAzeem Shaikh strscpy(str, "PCIe iSA", str_len);
6958ae6d9c7SGiridhar Malavali return str;
6968ae6d9c7SGiridhar Malavali }
6978ae6d9c7SGiridhar Malavali
6988ae6d9c7SGiridhar Malavali char *
qlafx00_fw_version_str(struct scsi_qla_host * vha,char * str,size_t size)699df57cabaSHimanshu Madhani qlafx00_fw_version_str(struct scsi_qla_host *vha, char *str, size_t size)
7008ae6d9c7SGiridhar Malavali {
7018ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
7028ae6d9c7SGiridhar Malavali
703df57cabaSHimanshu Madhani snprintf(str, size, "%s", ha->mr.fw_version);
7048ae6d9c7SGiridhar Malavali return str;
7058ae6d9c7SGiridhar Malavali }
7068ae6d9c7SGiridhar Malavali
7078ae6d9c7SGiridhar Malavali void
qlafx00_enable_intrs(struct qla_hw_data * ha)7088ae6d9c7SGiridhar Malavali qlafx00_enable_intrs(struct qla_hw_data *ha)
7098ae6d9c7SGiridhar Malavali {
7108ae6d9c7SGiridhar Malavali unsigned long flags = 0;
7118ae6d9c7SGiridhar Malavali
7128ae6d9c7SGiridhar Malavali spin_lock_irqsave(&ha->hardware_lock, flags);
7138ae6d9c7SGiridhar Malavali ha->interrupts_on = 1;
7148ae6d9c7SGiridhar Malavali QLAFX00_ENABLE_ICNTRL_REG(ha);
7158ae6d9c7SGiridhar Malavali spin_unlock_irqrestore(&ha->hardware_lock, flags);
7168ae6d9c7SGiridhar Malavali }
7178ae6d9c7SGiridhar Malavali
7188ae6d9c7SGiridhar Malavali void
qlafx00_disable_intrs(struct qla_hw_data * ha)7198ae6d9c7SGiridhar Malavali qlafx00_disable_intrs(struct qla_hw_data *ha)
7208ae6d9c7SGiridhar Malavali {
7218ae6d9c7SGiridhar Malavali unsigned long flags = 0;
7228ae6d9c7SGiridhar Malavali
7238ae6d9c7SGiridhar Malavali spin_lock_irqsave(&ha->hardware_lock, flags);
7248ae6d9c7SGiridhar Malavali ha->interrupts_on = 0;
7258ae6d9c7SGiridhar Malavali QLAFX00_DISABLE_ICNTRL_REG(ha);
7268ae6d9c7SGiridhar Malavali spin_unlock_irqrestore(&ha->hardware_lock, flags);
7278ae6d9c7SGiridhar Malavali }
7288ae6d9c7SGiridhar Malavali
7298ae6d9c7SGiridhar Malavali int
qlafx00_abort_target(fc_port_t * fcport,uint64_t l,int tag)7309cb78c16SHannes Reinecke qlafx00_abort_target(fc_port_t *fcport, uint64_t l, int tag)
7318ae6d9c7SGiridhar Malavali {
732faef62d1SArmen Baloyan return qla2x00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag);
7338ae6d9c7SGiridhar Malavali }
7348ae6d9c7SGiridhar Malavali
7358ae6d9c7SGiridhar Malavali int
qlafx00_lun_reset(fc_port_t * fcport,uint64_t l,int tag)7369cb78c16SHannes Reinecke qlafx00_lun_reset(fc_port_t *fcport, uint64_t l, int tag)
7378ae6d9c7SGiridhar Malavali {
738faef62d1SArmen Baloyan return qla2x00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag);
7398ae6d9c7SGiridhar Malavali }
7408ae6d9c7SGiridhar Malavali
7418ae6d9c7SGiridhar Malavali int
qlafx00_iospace_config(struct qla_hw_data * ha)7428ae6d9c7SGiridhar Malavali qlafx00_iospace_config(struct qla_hw_data *ha)
7438ae6d9c7SGiridhar Malavali {
7448ae6d9c7SGiridhar Malavali if (pci_request_selected_regions(ha->pdev, ha->bars,
7458ae6d9c7SGiridhar Malavali QLA2XXX_DRIVER_NAME)) {
7468ae6d9c7SGiridhar Malavali ql_log_pci(ql_log_fatal, ha->pdev, 0x014e,
7478ae6d9c7SGiridhar Malavali "Failed to reserve PIO/MMIO regions (%s), aborting.\n",
7488ae6d9c7SGiridhar Malavali pci_name(ha->pdev));
7498ae6d9c7SGiridhar Malavali goto iospace_error_exit;
7508ae6d9c7SGiridhar Malavali }
7518ae6d9c7SGiridhar Malavali
7528ae6d9c7SGiridhar Malavali /* Use MMIO operations for all accesses. */
7538ae6d9c7SGiridhar Malavali if (!(pci_resource_flags(ha->pdev, 0) & IORESOURCE_MEM)) {
7548ae6d9c7SGiridhar Malavali ql_log_pci(ql_log_warn, ha->pdev, 0x014f,
7558ae6d9c7SGiridhar Malavali "Invalid pci I/O region size (%s).\n",
7568ae6d9c7SGiridhar Malavali pci_name(ha->pdev));
7578ae6d9c7SGiridhar Malavali goto iospace_error_exit;
7588ae6d9c7SGiridhar Malavali }
7598ae6d9c7SGiridhar Malavali if (pci_resource_len(ha->pdev, 0) < BAR0_LEN_FX00) {
7608ae6d9c7SGiridhar Malavali ql_log_pci(ql_log_warn, ha->pdev, 0x0127,
7618ae6d9c7SGiridhar Malavali "Invalid PCI mem BAR0 region size (%s), aborting\n",
7628ae6d9c7SGiridhar Malavali pci_name(ha->pdev));
7638ae6d9c7SGiridhar Malavali goto iospace_error_exit;
7648ae6d9c7SGiridhar Malavali }
7658ae6d9c7SGiridhar Malavali
7668ae6d9c7SGiridhar Malavali ha->cregbase =
7674bdc0d67SChristoph Hellwig ioremap(pci_resource_start(ha->pdev, 0), BAR0_LEN_FX00);
7688ae6d9c7SGiridhar Malavali if (!ha->cregbase) {
7698ae6d9c7SGiridhar Malavali ql_log_pci(ql_log_fatal, ha->pdev, 0x0128,
7708ae6d9c7SGiridhar Malavali "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev));
7718ae6d9c7SGiridhar Malavali goto iospace_error_exit;
7728ae6d9c7SGiridhar Malavali }
7738ae6d9c7SGiridhar Malavali
7748ae6d9c7SGiridhar Malavali if (!(pci_resource_flags(ha->pdev, 2) & IORESOURCE_MEM)) {
7758ae6d9c7SGiridhar Malavali ql_log_pci(ql_log_warn, ha->pdev, 0x0129,
7768ae6d9c7SGiridhar Malavali "region #2 not an MMIO resource (%s), aborting\n",
7778ae6d9c7SGiridhar Malavali pci_name(ha->pdev));
7788ae6d9c7SGiridhar Malavali goto iospace_error_exit;
7798ae6d9c7SGiridhar Malavali }
7808ae6d9c7SGiridhar Malavali if (pci_resource_len(ha->pdev, 2) < BAR2_LEN_FX00) {
7818ae6d9c7SGiridhar Malavali ql_log_pci(ql_log_warn, ha->pdev, 0x012a,
7828ae6d9c7SGiridhar Malavali "Invalid PCI mem BAR2 region size (%s), aborting\n",
7838ae6d9c7SGiridhar Malavali pci_name(ha->pdev));
7848ae6d9c7SGiridhar Malavali goto iospace_error_exit;
7858ae6d9c7SGiridhar Malavali }
7868ae6d9c7SGiridhar Malavali
7878ae6d9c7SGiridhar Malavali ha->iobase =
7884bdc0d67SChristoph Hellwig ioremap(pci_resource_start(ha->pdev, 2), BAR2_LEN_FX00);
7898ae6d9c7SGiridhar Malavali if (!ha->iobase) {
7908ae6d9c7SGiridhar Malavali ql_log_pci(ql_log_fatal, ha->pdev, 0x012b,
7918ae6d9c7SGiridhar Malavali "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev));
7928ae6d9c7SGiridhar Malavali goto iospace_error_exit;
7938ae6d9c7SGiridhar Malavali }
7948ae6d9c7SGiridhar Malavali
7958ae6d9c7SGiridhar Malavali /* Determine queue resources */
7968ae6d9c7SGiridhar Malavali ha->max_req_queues = ha->max_rsp_queues = 1;
7978ae6d9c7SGiridhar Malavali
7988ae6d9c7SGiridhar Malavali ql_log_pci(ql_log_info, ha->pdev, 0x012c,
7998ae6d9c7SGiridhar Malavali "Bars 0x%x, iobase0 0x%p, iobase2 0x%p\n",
8008ae6d9c7SGiridhar Malavali ha->bars, ha->cregbase, ha->iobase);
8018ae6d9c7SGiridhar Malavali
8028ae6d9c7SGiridhar Malavali return 0;
8038ae6d9c7SGiridhar Malavali
8048ae6d9c7SGiridhar Malavali iospace_error_exit:
8058ae6d9c7SGiridhar Malavali return -ENOMEM;
8068ae6d9c7SGiridhar Malavali }
8078ae6d9c7SGiridhar Malavali
8088ae6d9c7SGiridhar Malavali static void
qlafx00_save_queue_ptrs(struct scsi_qla_host * vha)8098ae6d9c7SGiridhar Malavali qlafx00_save_queue_ptrs(struct scsi_qla_host *vha)
8108ae6d9c7SGiridhar Malavali {
8118ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
8128ae6d9c7SGiridhar Malavali struct req_que *req = ha->req_q_map[0];
8138ae6d9c7SGiridhar Malavali struct rsp_que *rsp = ha->rsp_q_map[0];
8148ae6d9c7SGiridhar Malavali
8158ae6d9c7SGiridhar Malavali req->length_fx00 = req->length;
8168ae6d9c7SGiridhar Malavali req->ring_fx00 = req->ring;
8178ae6d9c7SGiridhar Malavali req->dma_fx00 = req->dma;
8188ae6d9c7SGiridhar Malavali
8198ae6d9c7SGiridhar Malavali rsp->length_fx00 = rsp->length;
8208ae6d9c7SGiridhar Malavali rsp->ring_fx00 = rsp->ring;
8218ae6d9c7SGiridhar Malavali rsp->dma_fx00 = rsp->dma;
8228ae6d9c7SGiridhar Malavali
8238ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x012d,
8248ae6d9c7SGiridhar Malavali "req: %p, ring_fx00: %p, length_fx00: 0x%x,"
8258ae6d9c7SGiridhar Malavali "req->dma_fx00: 0x%llx\n", req, req->ring_fx00,
8268ae6d9c7SGiridhar Malavali req->length_fx00, (u64)req->dma_fx00);
8278ae6d9c7SGiridhar Malavali
8288ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x012e,
8298ae6d9c7SGiridhar Malavali "rsp: %p, ring_fx00: %p, length_fx00: 0x%x,"
8308ae6d9c7SGiridhar Malavali "rsp->dma_fx00: 0x%llx\n", rsp, rsp->ring_fx00,
8318ae6d9c7SGiridhar Malavali rsp->length_fx00, (u64)rsp->dma_fx00);
8328ae6d9c7SGiridhar Malavali }
8338ae6d9c7SGiridhar Malavali
8348ae6d9c7SGiridhar Malavali static int
qlafx00_config_queues(struct scsi_qla_host * vha)8358ae6d9c7SGiridhar Malavali qlafx00_config_queues(struct scsi_qla_host *vha)
8368ae6d9c7SGiridhar Malavali {
8378ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
8388ae6d9c7SGiridhar Malavali struct req_que *req = ha->req_q_map[0];
8398ae6d9c7SGiridhar Malavali struct rsp_que *rsp = ha->rsp_q_map[0];
8408ae6d9c7SGiridhar Malavali dma_addr_t bar2_hdl = pci_resource_start(ha->pdev, 2);
8418ae6d9c7SGiridhar Malavali
8428ae6d9c7SGiridhar Malavali req->length = ha->req_que_len;
8438dfa4b5aSBart Van Assche req->ring = (void __force *)ha->iobase + ha->req_que_off;
8448ae6d9c7SGiridhar Malavali req->dma = bar2_hdl + ha->req_que_off;
8458ae6d9c7SGiridhar Malavali if ((!req->ring) || (req->length == 0)) {
8468ae6d9c7SGiridhar Malavali ql_log_pci(ql_log_info, ha->pdev, 0x012f,
8478ae6d9c7SGiridhar Malavali "Unable to allocate memory for req_ring\n");
8488ae6d9c7SGiridhar Malavali return QLA_FUNCTION_FAILED;
8498ae6d9c7SGiridhar Malavali }
8508ae6d9c7SGiridhar Malavali
8518ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x0130,
8528ae6d9c7SGiridhar Malavali "req: %p req_ring pointer %p req len 0x%x "
8538ae6d9c7SGiridhar Malavali "req off 0x%x\n, req->dma: 0x%llx",
8548ae6d9c7SGiridhar Malavali req, req->ring, req->length,
8558ae6d9c7SGiridhar Malavali ha->req_que_off, (u64)req->dma);
8568ae6d9c7SGiridhar Malavali
8578ae6d9c7SGiridhar Malavali rsp->length = ha->rsp_que_len;
8588dfa4b5aSBart Van Assche rsp->ring = (void __force *)ha->iobase + ha->rsp_que_off;
8598ae6d9c7SGiridhar Malavali rsp->dma = bar2_hdl + ha->rsp_que_off;
8608ae6d9c7SGiridhar Malavali if ((!rsp->ring) || (rsp->length == 0)) {
8618ae6d9c7SGiridhar Malavali ql_log_pci(ql_log_info, ha->pdev, 0x0131,
8628ae6d9c7SGiridhar Malavali "Unable to allocate memory for rsp_ring\n");
8638ae6d9c7SGiridhar Malavali return QLA_FUNCTION_FAILED;
8648ae6d9c7SGiridhar Malavali }
8658ae6d9c7SGiridhar Malavali
8668ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x0132,
8678ae6d9c7SGiridhar Malavali "rsp: %p rsp_ring pointer %p rsp len 0x%x "
8688ae6d9c7SGiridhar Malavali "rsp off 0x%x, rsp->dma: 0x%llx\n",
8698ae6d9c7SGiridhar Malavali rsp, rsp->ring, rsp->length,
8708ae6d9c7SGiridhar Malavali ha->rsp_que_off, (u64)rsp->dma);
8718ae6d9c7SGiridhar Malavali
8728ae6d9c7SGiridhar Malavali return QLA_SUCCESS;
8738ae6d9c7SGiridhar Malavali }
8748ae6d9c7SGiridhar Malavali
8758ae6d9c7SGiridhar Malavali static int
qlafx00_init_fw_ready(scsi_qla_host_t * vha)8768ae6d9c7SGiridhar Malavali qlafx00_init_fw_ready(scsi_qla_host_t *vha)
8778ae6d9c7SGiridhar Malavali {
8788ae6d9c7SGiridhar Malavali int rval = 0;
8798ae6d9c7SGiridhar Malavali unsigned long wtime;
8808ae6d9c7SGiridhar Malavali uint16_t wait_time; /* Wait time */
8818ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
8828ae6d9c7SGiridhar Malavali struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00;
8838ae6d9c7SGiridhar Malavali uint32_t aenmbx, aenmbx7 = 0;
884f9a2a543SArmen Baloyan uint32_t pseudo_aen;
8858ae6d9c7SGiridhar Malavali uint32_t state[5];
8868ae6d9c7SGiridhar Malavali bool done = false;
8878ae6d9c7SGiridhar Malavali
8888ae6d9c7SGiridhar Malavali /* 30 seconds wait - Adjust if required */
8898ae6d9c7SGiridhar Malavali wait_time = 30;
8908ae6d9c7SGiridhar Malavali
89104474d3aSBart Van Assche pseudo_aen = rd_reg_dword(®->pseudoaen);
892f9a2a543SArmen Baloyan if (pseudo_aen == 1) {
89304474d3aSBart Van Assche aenmbx7 = rd_reg_dword(®->initval7);
894f9a2a543SArmen Baloyan ha->mbx_intr_code = MSW(aenmbx7);
895f9a2a543SArmen Baloyan ha->rqstq_intr_code = LSW(aenmbx7);
896f9a2a543SArmen Baloyan rval = qlafx00_driver_shutdown(vha, 10);
897f9a2a543SArmen Baloyan if (rval != QLA_SUCCESS)
898f9a2a543SArmen Baloyan qlafx00_soft_reset(vha);
899f9a2a543SArmen Baloyan }
900f9a2a543SArmen Baloyan
9018ae6d9c7SGiridhar Malavali /* wait time before firmware ready */
9028ae6d9c7SGiridhar Malavali wtime = jiffies + (wait_time * HZ);
9038ae6d9c7SGiridhar Malavali do {
90404474d3aSBart Van Assche aenmbx = rd_reg_dword(®->aenmailbox0);
9058ae6d9c7SGiridhar Malavali barrier();
9068ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_mbx, vha, 0x0133,
9078ae6d9c7SGiridhar Malavali "aenmbx: 0x%x\n", aenmbx);
9088ae6d9c7SGiridhar Malavali
9098ae6d9c7SGiridhar Malavali switch (aenmbx) {
9108ae6d9c7SGiridhar Malavali case MBA_FW_NOT_STARTED:
9118ae6d9c7SGiridhar Malavali case MBA_FW_STARTING:
9128ae6d9c7SGiridhar Malavali break;
9138ae6d9c7SGiridhar Malavali
9148ae6d9c7SGiridhar Malavali case MBA_SYSTEM_ERR:
9158ae6d9c7SGiridhar Malavali case MBA_REQ_TRANSFER_ERR:
9168ae6d9c7SGiridhar Malavali case MBA_RSP_TRANSFER_ERR:
9178ae6d9c7SGiridhar Malavali case MBA_FW_INIT_FAILURE:
9188ae6d9c7SGiridhar Malavali qlafx00_soft_reset(vha);
9198ae6d9c7SGiridhar Malavali break;
9208ae6d9c7SGiridhar Malavali
9218ae6d9c7SGiridhar Malavali case MBA_FW_RESTART_CMPLT:
9228ae6d9c7SGiridhar Malavali /* Set the mbx and rqstq intr code */
92304474d3aSBart Van Assche aenmbx7 = rd_reg_dword(®->aenmailbox7);
9248ae6d9c7SGiridhar Malavali ha->mbx_intr_code = MSW(aenmbx7);
9258ae6d9c7SGiridhar Malavali ha->rqstq_intr_code = LSW(aenmbx7);
92604474d3aSBart Van Assche ha->req_que_off = rd_reg_dword(®->aenmailbox1);
92704474d3aSBart Van Assche ha->rsp_que_off = rd_reg_dword(®->aenmailbox3);
92804474d3aSBart Van Assche ha->req_que_len = rd_reg_dword(®->aenmailbox5);
92904474d3aSBart Van Assche ha->rsp_que_len = rd_reg_dword(®->aenmailbox6);
93004474d3aSBart Van Assche wrt_reg_dword(®->aenmailbox0, 0);
93104474d3aSBart Van Assche rd_reg_dword_relaxed(®->aenmailbox0);
9328ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x0134,
9338ae6d9c7SGiridhar Malavali "f/w returned mbx_intr_code: 0x%x, "
9348ae6d9c7SGiridhar Malavali "rqstq_intr_code: 0x%x\n",
9358ae6d9c7SGiridhar Malavali ha->mbx_intr_code, ha->rqstq_intr_code);
9368ae6d9c7SGiridhar Malavali QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS);
9378ae6d9c7SGiridhar Malavali rval = QLA_SUCCESS;
9388ae6d9c7SGiridhar Malavali done = true;
9398ae6d9c7SGiridhar Malavali break;
9408ae6d9c7SGiridhar Malavali
9418ae6d9c7SGiridhar Malavali default:
9420f8cdff5SArmen Baloyan if ((aenmbx & 0xFF00) == MBA_FW_INIT_INPROGRESS)
9430f8cdff5SArmen Baloyan break;
9440f8cdff5SArmen Baloyan
9458ae6d9c7SGiridhar Malavali /* If fw is apparently not ready. In order to continue,
9468ae6d9c7SGiridhar Malavali * we might need to issue Mbox cmd, but the problem is
9478ae6d9c7SGiridhar Malavali * that the DoorBell vector values that come with the
9488ae6d9c7SGiridhar Malavali * 8060 AEN are most likely gone by now (and thus no
9498ae6d9c7SGiridhar Malavali * bell would be rung on the fw side when mbox cmd is
9508ae6d9c7SGiridhar Malavali * issued). We have to therefore grab the 8060 AEN
9518ae6d9c7SGiridhar Malavali * shadow regs (filled in by FW when the last 8060
9528ae6d9c7SGiridhar Malavali * AEN was being posted).
9538ae6d9c7SGiridhar Malavali * Do the following to determine what is needed in
9548ae6d9c7SGiridhar Malavali * order to get the FW ready:
9558ae6d9c7SGiridhar Malavali * 1. reload the 8060 AEN values from the shadow regs
9568ae6d9c7SGiridhar Malavali * 2. clear int status to get rid of possible pending
9578ae6d9c7SGiridhar Malavali * interrupts
9588ae6d9c7SGiridhar Malavali * 3. issue Get FW State Mbox cmd to determine fw state
9598ae6d9c7SGiridhar Malavali * Set the mbx and rqstq intr code from Shadow Regs
9608ae6d9c7SGiridhar Malavali */
96104474d3aSBart Van Assche aenmbx7 = rd_reg_dword(®->initval7);
9628ae6d9c7SGiridhar Malavali ha->mbx_intr_code = MSW(aenmbx7);
9638ae6d9c7SGiridhar Malavali ha->rqstq_intr_code = LSW(aenmbx7);
96404474d3aSBart Van Assche ha->req_que_off = rd_reg_dword(®->initval1);
96504474d3aSBart Van Assche ha->rsp_que_off = rd_reg_dword(®->initval3);
96604474d3aSBart Van Assche ha->req_que_len = rd_reg_dword(®->initval5);
96704474d3aSBart Van Assche ha->rsp_que_len = rd_reg_dword(®->initval6);
9688ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x0135,
9698ae6d9c7SGiridhar Malavali "f/w returned mbx_intr_code: 0x%x, "
9708ae6d9c7SGiridhar Malavali "rqstq_intr_code: 0x%x\n",
9718ae6d9c7SGiridhar Malavali ha->mbx_intr_code, ha->rqstq_intr_code);
9728ae6d9c7SGiridhar Malavali QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS);
9738ae6d9c7SGiridhar Malavali
9748ae6d9c7SGiridhar Malavali /* Get the FW state */
9758ae6d9c7SGiridhar Malavali rval = qlafx00_get_firmware_state(vha, state);
9768ae6d9c7SGiridhar Malavali if (rval != QLA_SUCCESS) {
9778ae6d9c7SGiridhar Malavali /* Retry if timer has not expired */
9788ae6d9c7SGiridhar Malavali break;
9798ae6d9c7SGiridhar Malavali }
9808ae6d9c7SGiridhar Malavali
9818ae6d9c7SGiridhar Malavali if (state[0] == FSTATE_FX00_CONFIG_WAIT) {
9828ae6d9c7SGiridhar Malavali /* Firmware is waiting to be
9838ae6d9c7SGiridhar Malavali * initialized by driver
9848ae6d9c7SGiridhar Malavali */
9858ae6d9c7SGiridhar Malavali rval = QLA_SUCCESS;
9868ae6d9c7SGiridhar Malavali done = true;
9878ae6d9c7SGiridhar Malavali break;
9888ae6d9c7SGiridhar Malavali }
9898ae6d9c7SGiridhar Malavali
9908ae6d9c7SGiridhar Malavali /* Issue driver shutdown and wait until f/w recovers.
9918ae6d9c7SGiridhar Malavali * Driver should continue to poll until 8060 AEN is
9928ae6d9c7SGiridhar Malavali * received indicating firmware recovery.
9938ae6d9c7SGiridhar Malavali */
9948ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x0136,
9958ae6d9c7SGiridhar Malavali "Sending Driver shutdown fw_state 0x%x\n",
9968ae6d9c7SGiridhar Malavali state[0]);
9978ae6d9c7SGiridhar Malavali
9988ae6d9c7SGiridhar Malavali rval = qlafx00_driver_shutdown(vha, 10);
9998ae6d9c7SGiridhar Malavali if (rval != QLA_SUCCESS) {
10008ae6d9c7SGiridhar Malavali rval = QLA_FUNCTION_FAILED;
10018ae6d9c7SGiridhar Malavali break;
10028ae6d9c7SGiridhar Malavali }
10038ae6d9c7SGiridhar Malavali msleep(500);
10048ae6d9c7SGiridhar Malavali
10058ae6d9c7SGiridhar Malavali wtime = jiffies + (wait_time * HZ);
10068ae6d9c7SGiridhar Malavali break;
10078ae6d9c7SGiridhar Malavali }
10088ae6d9c7SGiridhar Malavali
10098ae6d9c7SGiridhar Malavali if (!done) {
10108ae6d9c7SGiridhar Malavali if (time_after_eq(jiffies, wtime)) {
10118ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x0137,
10128ae6d9c7SGiridhar Malavali "Init f/w failed: aen[7]: 0x%x\n",
101304474d3aSBart Van Assche rd_reg_dword(®->aenmailbox7));
10148ae6d9c7SGiridhar Malavali rval = QLA_FUNCTION_FAILED;
10158ae6d9c7SGiridhar Malavali done = true;
10168ae6d9c7SGiridhar Malavali break;
10178ae6d9c7SGiridhar Malavali }
10188ae6d9c7SGiridhar Malavali /* Delay for a while */
10198ae6d9c7SGiridhar Malavali msleep(500);
10208ae6d9c7SGiridhar Malavali }
10218ae6d9c7SGiridhar Malavali } while (!done);
10228ae6d9c7SGiridhar Malavali
10238ae6d9c7SGiridhar Malavali if (rval)
10248ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x0138,
10258ae6d9c7SGiridhar Malavali "%s **** FAILED ****.\n", __func__);
10268ae6d9c7SGiridhar Malavali else
10278ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x0139,
10288ae6d9c7SGiridhar Malavali "%s **** SUCCESS ****.\n", __func__);
10298ae6d9c7SGiridhar Malavali
10308ae6d9c7SGiridhar Malavali return rval;
10318ae6d9c7SGiridhar Malavali }
10328ae6d9c7SGiridhar Malavali
10338ae6d9c7SGiridhar Malavali /*
10348ae6d9c7SGiridhar Malavali * qlafx00_fw_ready() - Waits for firmware ready.
10358ae6d9c7SGiridhar Malavali * @ha: HA context
10368ae6d9c7SGiridhar Malavali *
10378ae6d9c7SGiridhar Malavali * Returns 0 on success.
10388ae6d9c7SGiridhar Malavali */
10398ae6d9c7SGiridhar Malavali int
qlafx00_fw_ready(scsi_qla_host_t * vha)10408ae6d9c7SGiridhar Malavali qlafx00_fw_ready(scsi_qla_host_t *vha)
10418ae6d9c7SGiridhar Malavali {
10428ae6d9c7SGiridhar Malavali int rval;
10438ae6d9c7SGiridhar Malavali unsigned long wtime;
10448ae6d9c7SGiridhar Malavali uint16_t wait_time; /* Wait time if loop is coming ready */
10458ae6d9c7SGiridhar Malavali uint32_t state[5];
10468ae6d9c7SGiridhar Malavali
10478ae6d9c7SGiridhar Malavali rval = QLA_SUCCESS;
10488ae6d9c7SGiridhar Malavali
10498ae6d9c7SGiridhar Malavali wait_time = 10;
10508ae6d9c7SGiridhar Malavali
10518ae6d9c7SGiridhar Malavali /* wait time before firmware ready */
10528ae6d9c7SGiridhar Malavali wtime = jiffies + (wait_time * HZ);
10538ae6d9c7SGiridhar Malavali
10548ae6d9c7SGiridhar Malavali /* Wait for ISP to finish init */
10558ae6d9c7SGiridhar Malavali if (!vha->flags.init_done)
10568ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x013a,
10578ae6d9c7SGiridhar Malavali "Waiting for init to complete...\n");
10588ae6d9c7SGiridhar Malavali
10598ae6d9c7SGiridhar Malavali do {
10608ae6d9c7SGiridhar Malavali rval = qlafx00_get_firmware_state(vha, state);
10618ae6d9c7SGiridhar Malavali
10628ae6d9c7SGiridhar Malavali if (rval == QLA_SUCCESS) {
10638ae6d9c7SGiridhar Malavali if (state[0] == FSTATE_FX00_INITIALIZED) {
10648ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x013b,
10658ae6d9c7SGiridhar Malavali "fw_state=%x\n", state[0]);
10668ae6d9c7SGiridhar Malavali rval = QLA_SUCCESS;
10678ae6d9c7SGiridhar Malavali break;
10688ae6d9c7SGiridhar Malavali }
10698ae6d9c7SGiridhar Malavali }
10708ae6d9c7SGiridhar Malavali rval = QLA_FUNCTION_FAILED;
10718ae6d9c7SGiridhar Malavali
10728ae6d9c7SGiridhar Malavali if (time_after_eq(jiffies, wtime))
10738ae6d9c7SGiridhar Malavali break;
10748ae6d9c7SGiridhar Malavali
10758ae6d9c7SGiridhar Malavali /* Delay for a while */
10768ae6d9c7SGiridhar Malavali msleep(500);
10778ae6d9c7SGiridhar Malavali
10788ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x013c,
10798ae6d9c7SGiridhar Malavali "fw_state=%x curr time=%lx.\n", state[0], jiffies);
10808ae6d9c7SGiridhar Malavali } while (1);
10818ae6d9c7SGiridhar Malavali
10828ae6d9c7SGiridhar Malavali
10838ae6d9c7SGiridhar Malavali if (rval)
10848ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x013d,
10858ae6d9c7SGiridhar Malavali "Firmware ready **** FAILED ****.\n");
10868ae6d9c7SGiridhar Malavali else
10878ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x013e,
10888ae6d9c7SGiridhar Malavali "Firmware ready **** SUCCESS ****.\n");
10898ae6d9c7SGiridhar Malavali
10908ae6d9c7SGiridhar Malavali return rval;
10918ae6d9c7SGiridhar Malavali }
10928ae6d9c7SGiridhar Malavali
10938ae6d9c7SGiridhar Malavali static int
qlafx00_find_all_targets(scsi_qla_host_t * vha,struct list_head * new_fcports)10948ae6d9c7SGiridhar Malavali qlafx00_find_all_targets(scsi_qla_host_t *vha,
10958ae6d9c7SGiridhar Malavali struct list_head *new_fcports)
10968ae6d9c7SGiridhar Malavali {
10978ae6d9c7SGiridhar Malavali int rval;
10988ae6d9c7SGiridhar Malavali uint16_t tgt_id;
10998ae6d9c7SGiridhar Malavali fc_port_t *fcport, *new_fcport;
11008ae6d9c7SGiridhar Malavali int found;
11018ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
11028ae6d9c7SGiridhar Malavali
11038ae6d9c7SGiridhar Malavali rval = QLA_SUCCESS;
11048ae6d9c7SGiridhar Malavali
11058ae6d9c7SGiridhar Malavali if (!test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))
11068ae6d9c7SGiridhar Malavali return QLA_FUNCTION_FAILED;
11078ae6d9c7SGiridhar Malavali
11088ae6d9c7SGiridhar Malavali if ((atomic_read(&vha->loop_down_timer) ||
11098ae6d9c7SGiridhar Malavali STATE_TRANSITION(vha))) {
11108ae6d9c7SGiridhar Malavali atomic_set(&vha->loop_down_timer, 0);
11118ae6d9c7SGiridhar Malavali set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
11128ae6d9c7SGiridhar Malavali return QLA_FUNCTION_FAILED;
11138ae6d9c7SGiridhar Malavali }
11148ae6d9c7SGiridhar Malavali
11158ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_disc + ql_dbg_init, vha, 0x2088,
11168ae6d9c7SGiridhar Malavali "Listing Target bit map...\n");
1117f8f97b0cSJoe Carnuccio ql_dump_buffer(ql_dbg_disc + ql_dbg_init, vha, 0x2089,
1118f8f97b0cSJoe Carnuccio ha->gid_list, 32);
11198ae6d9c7SGiridhar Malavali
11208ae6d9c7SGiridhar Malavali /* Allocate temporary rmtport for any new rmtports discovered. */
11218ae6d9c7SGiridhar Malavali new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
11228ae6d9c7SGiridhar Malavali if (new_fcport == NULL)
11238ae6d9c7SGiridhar Malavali return QLA_MEMORY_ALLOC_FAILED;
11248ae6d9c7SGiridhar Malavali
11258ae6d9c7SGiridhar Malavali for_each_set_bit(tgt_id, (void *)ha->gid_list,
11268ae6d9c7SGiridhar Malavali QLAFX00_TGT_NODE_LIST_SIZE) {
11278ae6d9c7SGiridhar Malavali
11288ae6d9c7SGiridhar Malavali /* Send get target node info */
11298ae6d9c7SGiridhar Malavali new_fcport->tgt_id = tgt_id;
11308ae6d9c7SGiridhar Malavali rval = qlafx00_fx_disc(vha, new_fcport,
11318ae6d9c7SGiridhar Malavali FXDISC_GET_TGT_NODE_INFO);
11328ae6d9c7SGiridhar Malavali if (rval != QLA_SUCCESS) {
11338ae6d9c7SGiridhar Malavali ql_log(ql_log_warn, vha, 0x208a,
11348ae6d9c7SGiridhar Malavali "Target info scan failed -- assuming zero-entry "
11358ae6d9c7SGiridhar Malavali "result...\n");
11368ae6d9c7SGiridhar Malavali continue;
11378ae6d9c7SGiridhar Malavali }
11388ae6d9c7SGiridhar Malavali
11398ae6d9c7SGiridhar Malavali /* Locate matching device in database. */
11408ae6d9c7SGiridhar Malavali found = 0;
11418ae6d9c7SGiridhar Malavali list_for_each_entry(fcport, &vha->vp_fcports, list) {
11428ae6d9c7SGiridhar Malavali if (memcmp(new_fcport->port_name,
11438ae6d9c7SGiridhar Malavali fcport->port_name, WWN_SIZE))
11448ae6d9c7SGiridhar Malavali continue;
11458ae6d9c7SGiridhar Malavali
11468ae6d9c7SGiridhar Malavali found++;
11478ae6d9c7SGiridhar Malavali
11488ae6d9c7SGiridhar Malavali /*
11498ae6d9c7SGiridhar Malavali * If tgt_id is same and state FCS_ONLINE, nothing
11508ae6d9c7SGiridhar Malavali * changed.
11518ae6d9c7SGiridhar Malavali */
11528ae6d9c7SGiridhar Malavali if (fcport->tgt_id == new_fcport->tgt_id &&
11538ae6d9c7SGiridhar Malavali atomic_read(&fcport->state) == FCS_ONLINE)
11548ae6d9c7SGiridhar Malavali break;
11558ae6d9c7SGiridhar Malavali
11568ae6d9c7SGiridhar Malavali /*
11578ae6d9c7SGiridhar Malavali * Tgt ID changed or device was marked to be updated.
11588ae6d9c7SGiridhar Malavali */
11598ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_disc + ql_dbg_init, vha, 0x208b,
11608ae6d9c7SGiridhar Malavali "TGT-ID Change(%s): Present tgt id: "
11618ae6d9c7SGiridhar Malavali "0x%x state: 0x%x "
11628ae6d9c7SGiridhar Malavali "wwnn = %llx wwpn = %llx.\n",
11638ae6d9c7SGiridhar Malavali __func__, fcport->tgt_id,
11648ae6d9c7SGiridhar Malavali atomic_read(&fcport->state),
11658ae6d9c7SGiridhar Malavali (unsigned long long)wwn_to_u64(fcport->node_name),
11668ae6d9c7SGiridhar Malavali (unsigned long long)wwn_to_u64(fcport->port_name));
11678ae6d9c7SGiridhar Malavali
11688ae6d9c7SGiridhar Malavali ql_log(ql_log_info, vha, 0x208c,
11698ae6d9c7SGiridhar Malavali "TGT-ID Announce(%s): Discovered tgt "
11708ae6d9c7SGiridhar Malavali "id 0x%x wwnn = %llx "
11718ae6d9c7SGiridhar Malavali "wwpn = %llx.\n", __func__, new_fcport->tgt_id,
11728ae6d9c7SGiridhar Malavali (unsigned long long)
11738ae6d9c7SGiridhar Malavali wwn_to_u64(new_fcport->node_name),
11748ae6d9c7SGiridhar Malavali (unsigned long long)
11758ae6d9c7SGiridhar Malavali wwn_to_u64(new_fcport->port_name));
11768ae6d9c7SGiridhar Malavali
11778ae6d9c7SGiridhar Malavali if (atomic_read(&fcport->state) != FCS_ONLINE) {
11788ae6d9c7SGiridhar Malavali fcport->old_tgt_id = fcport->tgt_id;
11798ae6d9c7SGiridhar Malavali fcport->tgt_id = new_fcport->tgt_id;
11808ae6d9c7SGiridhar Malavali ql_log(ql_log_info, vha, 0x208d,
11818ae6d9c7SGiridhar Malavali "TGT-ID: New fcport Added: %p\n", fcport);
11828ae6d9c7SGiridhar Malavali qla2x00_update_fcport(vha, fcport);
11838ae6d9c7SGiridhar Malavali } else {
11848ae6d9c7SGiridhar Malavali ql_log(ql_log_info, vha, 0x208e,
11858ae6d9c7SGiridhar Malavali " Existing TGT-ID %x did not get "
11868ae6d9c7SGiridhar Malavali " offline event from firmware.\n",
11878ae6d9c7SGiridhar Malavali fcport->old_tgt_id);
11883c75ad1dSHimanshu Madhani qla2x00_mark_device_lost(vha, fcport, 0);
11898ae6d9c7SGiridhar Malavali set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
11903dae2205SQuinn Tran qla2x00_free_fcport(new_fcport);
11918ae6d9c7SGiridhar Malavali return rval;
11928ae6d9c7SGiridhar Malavali }
11938ae6d9c7SGiridhar Malavali break;
11948ae6d9c7SGiridhar Malavali }
11958ae6d9c7SGiridhar Malavali
11968ae6d9c7SGiridhar Malavali if (found)
11978ae6d9c7SGiridhar Malavali continue;
11988ae6d9c7SGiridhar Malavali
11998ae6d9c7SGiridhar Malavali /* If device was not in our fcports list, then add it. */
12008ae6d9c7SGiridhar Malavali list_add_tail(&new_fcport->list, new_fcports);
12018ae6d9c7SGiridhar Malavali
12028ae6d9c7SGiridhar Malavali /* Allocate a new replacement fcport. */
12038ae6d9c7SGiridhar Malavali new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
12048ae6d9c7SGiridhar Malavali if (new_fcport == NULL)
12058ae6d9c7SGiridhar Malavali return QLA_MEMORY_ALLOC_FAILED;
12068ae6d9c7SGiridhar Malavali }
12078ae6d9c7SGiridhar Malavali
12083dae2205SQuinn Tran qla2x00_free_fcport(new_fcport);
12098ae6d9c7SGiridhar Malavali return rval;
12108ae6d9c7SGiridhar Malavali }
12118ae6d9c7SGiridhar Malavali
12128ae6d9c7SGiridhar Malavali /*
12138ae6d9c7SGiridhar Malavali * qlafx00_configure_all_targets
12148ae6d9c7SGiridhar Malavali * Setup target devices with node ID's.
12158ae6d9c7SGiridhar Malavali *
12168ae6d9c7SGiridhar Malavali * Input:
12178ae6d9c7SGiridhar Malavali * ha = adapter block pointer.
12188ae6d9c7SGiridhar Malavali *
12198ae6d9c7SGiridhar Malavali * Returns:
12208ae6d9c7SGiridhar Malavali * 0 = success.
12218ae6d9c7SGiridhar Malavali * BIT_0 = error
12228ae6d9c7SGiridhar Malavali */
12238ae6d9c7SGiridhar Malavali static int
qlafx00_configure_all_targets(scsi_qla_host_t * vha)12248ae6d9c7SGiridhar Malavali qlafx00_configure_all_targets(scsi_qla_host_t *vha)
12258ae6d9c7SGiridhar Malavali {
12268ae6d9c7SGiridhar Malavali int rval;
12278ae6d9c7SGiridhar Malavali fc_port_t *fcport, *rmptemp;
12288ae6d9c7SGiridhar Malavali LIST_HEAD(new_fcports);
12298ae6d9c7SGiridhar Malavali
12308ae6d9c7SGiridhar Malavali rval = qlafx00_fx_disc(vha, &vha->hw->mr.fcport,
12318ae6d9c7SGiridhar Malavali FXDISC_GET_TGT_NODE_LIST);
12328ae6d9c7SGiridhar Malavali if (rval != QLA_SUCCESS) {
12338ae6d9c7SGiridhar Malavali set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
12348ae6d9c7SGiridhar Malavali return rval;
12358ae6d9c7SGiridhar Malavali }
12368ae6d9c7SGiridhar Malavali
12378ae6d9c7SGiridhar Malavali rval = qlafx00_find_all_targets(vha, &new_fcports);
12388ae6d9c7SGiridhar Malavali if (rval != QLA_SUCCESS) {
12398ae6d9c7SGiridhar Malavali set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
12408ae6d9c7SGiridhar Malavali return rval;
12418ae6d9c7SGiridhar Malavali }
12428ae6d9c7SGiridhar Malavali
12438ae6d9c7SGiridhar Malavali /*
12448ae6d9c7SGiridhar Malavali * Delete all previous devices marked lost.
12458ae6d9c7SGiridhar Malavali */
12468ae6d9c7SGiridhar Malavali list_for_each_entry(fcport, &vha->vp_fcports, list) {
12478ae6d9c7SGiridhar Malavali if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
12488ae6d9c7SGiridhar Malavali break;
12498ae6d9c7SGiridhar Malavali
12508ae6d9c7SGiridhar Malavali if (atomic_read(&fcport->state) == FCS_DEVICE_LOST) {
12518ae6d9c7SGiridhar Malavali if (fcport->port_type != FCT_INITIATOR)
12523c75ad1dSHimanshu Madhani qla2x00_mark_device_lost(vha, fcport, 0);
12538ae6d9c7SGiridhar Malavali }
12548ae6d9c7SGiridhar Malavali }
12558ae6d9c7SGiridhar Malavali
12568ae6d9c7SGiridhar Malavali /*
12578ae6d9c7SGiridhar Malavali * Add the new devices to our devices list.
12588ae6d9c7SGiridhar Malavali */
12598ae6d9c7SGiridhar Malavali list_for_each_entry_safe(fcport, rmptemp, &new_fcports, list) {
12608ae6d9c7SGiridhar Malavali if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
12618ae6d9c7SGiridhar Malavali break;
12628ae6d9c7SGiridhar Malavali
12638ae6d9c7SGiridhar Malavali qla2x00_update_fcport(vha, fcport);
12648ae6d9c7SGiridhar Malavali list_move_tail(&fcport->list, &vha->vp_fcports);
12658ae6d9c7SGiridhar Malavali ql_log(ql_log_info, vha, 0x208f,
12668ae6d9c7SGiridhar Malavali "Attach new target id 0x%x wwnn = %llx "
12678ae6d9c7SGiridhar Malavali "wwpn = %llx.\n",
12688ae6d9c7SGiridhar Malavali fcport->tgt_id,
12698ae6d9c7SGiridhar Malavali (unsigned long long)wwn_to_u64(fcport->node_name),
12708ae6d9c7SGiridhar Malavali (unsigned long long)wwn_to_u64(fcport->port_name));
12718ae6d9c7SGiridhar Malavali }
12728ae6d9c7SGiridhar Malavali
12738ae6d9c7SGiridhar Malavali /* Free all new device structures not processed. */
12748ae6d9c7SGiridhar Malavali list_for_each_entry_safe(fcport, rmptemp, &new_fcports, list) {
12758ae6d9c7SGiridhar Malavali list_del(&fcport->list);
12763dae2205SQuinn Tran qla2x00_free_fcport(fcport);
12778ae6d9c7SGiridhar Malavali }
12788ae6d9c7SGiridhar Malavali
12798ae6d9c7SGiridhar Malavali return rval;
12808ae6d9c7SGiridhar Malavali }
12818ae6d9c7SGiridhar Malavali
12828ae6d9c7SGiridhar Malavali /*
12838ae6d9c7SGiridhar Malavali * qlafx00_configure_devices
12848ae6d9c7SGiridhar Malavali * Updates Fibre Channel Device Database with what is actually on loop.
12858ae6d9c7SGiridhar Malavali *
12868ae6d9c7SGiridhar Malavali * Input:
12878ae6d9c7SGiridhar Malavali * ha = adapter block pointer.
12888ae6d9c7SGiridhar Malavali *
12898ae6d9c7SGiridhar Malavali * Returns:
12908ae6d9c7SGiridhar Malavali * 0 = success.
12918ae6d9c7SGiridhar Malavali * 1 = error.
12928ae6d9c7SGiridhar Malavali * 2 = database was full and device was not configured.
12938ae6d9c7SGiridhar Malavali */
12948ae6d9c7SGiridhar Malavali int
qlafx00_configure_devices(scsi_qla_host_t * vha)12958ae6d9c7SGiridhar Malavali qlafx00_configure_devices(scsi_qla_host_t *vha)
12968ae6d9c7SGiridhar Malavali {
12978ae6d9c7SGiridhar Malavali int rval;
129852c82823SBart Van Assche unsigned long flags;
1299bd432bb5SBart Van Assche
13008ae6d9c7SGiridhar Malavali rval = QLA_SUCCESS;
13018ae6d9c7SGiridhar Malavali
130252c82823SBart Van Assche flags = vha->dpc_flags;
13038ae6d9c7SGiridhar Malavali
13048ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_disc, vha, 0x2090,
13058ae6d9c7SGiridhar Malavali "Configure devices -- dpc flags =0x%lx\n", flags);
13068ae6d9c7SGiridhar Malavali
13078ae6d9c7SGiridhar Malavali rval = qlafx00_configure_all_targets(vha);
13088ae6d9c7SGiridhar Malavali
13098ae6d9c7SGiridhar Malavali if (rval == QLA_SUCCESS) {
13108ae6d9c7SGiridhar Malavali if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
13118ae6d9c7SGiridhar Malavali rval = QLA_FUNCTION_FAILED;
13128ae6d9c7SGiridhar Malavali } else {
13138ae6d9c7SGiridhar Malavali atomic_set(&vha->loop_state, LOOP_READY);
13148ae6d9c7SGiridhar Malavali ql_log(ql_log_info, vha, 0x2091,
13158ae6d9c7SGiridhar Malavali "Device Ready\n");
13168ae6d9c7SGiridhar Malavali }
13178ae6d9c7SGiridhar Malavali }
13188ae6d9c7SGiridhar Malavali
13198ae6d9c7SGiridhar Malavali if (rval) {
13208ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_disc, vha, 0x2092,
13218ae6d9c7SGiridhar Malavali "%s *** FAILED ***.\n", __func__);
13228ae6d9c7SGiridhar Malavali } else {
13238ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_disc, vha, 0x2093,
13248ae6d9c7SGiridhar Malavali "%s: exiting normally.\n", __func__);
13258ae6d9c7SGiridhar Malavali }
13268ae6d9c7SGiridhar Malavali return rval;
13278ae6d9c7SGiridhar Malavali }
13288ae6d9c7SGiridhar Malavali
13298ae6d9c7SGiridhar Malavali static void
qlafx00_abort_isp_cleanup(scsi_qla_host_t * vha,bool critemp)133071e56003SArmen Baloyan qlafx00_abort_isp_cleanup(scsi_qla_host_t *vha, bool critemp)
13318ae6d9c7SGiridhar Malavali {
13328ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
13338ae6d9c7SGiridhar Malavali fc_port_t *fcport;
13348ae6d9c7SGiridhar Malavali
13358ae6d9c7SGiridhar Malavali vha->flags.online = 0;
13368ae6d9c7SGiridhar Malavali ha->mr.fw_hbt_en = 0;
133771e56003SArmen Baloyan
133871e56003SArmen Baloyan if (!critemp) {
133971e56003SArmen Baloyan ha->flags.chip_reset_done = 0;
13408ae6d9c7SGiridhar Malavali clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
13418ae6d9c7SGiridhar Malavali vha->qla_stats.total_isp_aborts++;
13428ae6d9c7SGiridhar Malavali ql_log(ql_log_info, vha, 0x013f,
13438ae6d9c7SGiridhar Malavali "Performing ISP error recovery - ha = %p.\n", ha);
13448ae6d9c7SGiridhar Malavali ha->isp_ops->reset_chip(vha);
134571e56003SArmen Baloyan }
13468ae6d9c7SGiridhar Malavali
13478ae6d9c7SGiridhar Malavali if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
13488ae6d9c7SGiridhar Malavali atomic_set(&vha->loop_state, LOOP_DOWN);
13498ae6d9c7SGiridhar Malavali atomic_set(&vha->loop_down_timer,
13508ae6d9c7SGiridhar Malavali QLAFX00_LOOP_DOWN_TIME);
13518ae6d9c7SGiridhar Malavali } else {
13528ae6d9c7SGiridhar Malavali if (!atomic_read(&vha->loop_down_timer))
13538ae6d9c7SGiridhar Malavali atomic_set(&vha->loop_down_timer,
13548ae6d9c7SGiridhar Malavali QLAFX00_LOOP_DOWN_TIME);
13558ae6d9c7SGiridhar Malavali }
13568ae6d9c7SGiridhar Malavali
13578ae6d9c7SGiridhar Malavali /* Clear all async request states across all VPs. */
13588ae6d9c7SGiridhar Malavali list_for_each_entry(fcport, &vha->vp_fcports, list) {
13598ae6d9c7SGiridhar Malavali fcport->flags = 0;
13608ae6d9c7SGiridhar Malavali if (atomic_read(&fcport->state) == FCS_ONLINE)
13618ae6d9c7SGiridhar Malavali qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
13628ae6d9c7SGiridhar Malavali }
13638ae6d9c7SGiridhar Malavali
13648ae6d9c7SGiridhar Malavali if (!ha->flags.eeh_busy) {
136571e56003SArmen Baloyan if (critemp) {
136671e56003SArmen Baloyan qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);
136771e56003SArmen Baloyan } else {
13688ae6d9c7SGiridhar Malavali /* Requeue all commands in outstanding command list. */
13698ae6d9c7SGiridhar Malavali qla2x00_abort_all_cmds(vha, DID_RESET << 16);
13708ae6d9c7SGiridhar Malavali }
137171e56003SArmen Baloyan }
13728ae6d9c7SGiridhar Malavali
13738ae6d9c7SGiridhar Malavali qla2x00_free_irqs(vha);
137471e56003SArmen Baloyan if (critemp)
137571e56003SArmen Baloyan set_bit(FX00_CRITEMP_RECOVERY, &vha->dpc_flags);
137671e56003SArmen Baloyan else
13778ae6d9c7SGiridhar Malavali set_bit(FX00_RESET_RECOVERY, &vha->dpc_flags);
13788ae6d9c7SGiridhar Malavali
13798ae6d9c7SGiridhar Malavali /* Clear the Interrupts */
13808ae6d9c7SGiridhar Malavali QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS);
13818ae6d9c7SGiridhar Malavali
13828ae6d9c7SGiridhar Malavali ql_log(ql_log_info, vha, 0x0140,
13838ae6d9c7SGiridhar Malavali "%s Done done - ha=%p.\n", __func__, ha);
13848ae6d9c7SGiridhar Malavali }
13858ae6d9c7SGiridhar Malavali
13868ae6d9c7SGiridhar Malavali /**
13878ae6d9c7SGiridhar Malavali * qlafx00_init_response_q_entries() - Initializes response queue entries.
13882db6228dSBart Van Assche * @rsp: response queue
13898ae6d9c7SGiridhar Malavali *
13908ae6d9c7SGiridhar Malavali * Beginning of request ring has initialization control block already built
13918ae6d9c7SGiridhar Malavali * by nvram config routine.
13928ae6d9c7SGiridhar Malavali *
13938ae6d9c7SGiridhar Malavali * Returns 0 on success.
13948ae6d9c7SGiridhar Malavali */
13958ae6d9c7SGiridhar Malavali void
qlafx00_init_response_q_entries(struct rsp_que * rsp)13968ae6d9c7SGiridhar Malavali qlafx00_init_response_q_entries(struct rsp_que *rsp)
13978ae6d9c7SGiridhar Malavali {
13988ae6d9c7SGiridhar Malavali uint16_t cnt;
13998ae6d9c7SGiridhar Malavali response_t *pkt;
14008ae6d9c7SGiridhar Malavali
14018ae6d9c7SGiridhar Malavali rsp->ring_ptr = rsp->ring;
14028ae6d9c7SGiridhar Malavali rsp->ring_index = 0;
14038ae6d9c7SGiridhar Malavali rsp->status_srb = NULL;
14048ae6d9c7SGiridhar Malavali pkt = rsp->ring_ptr;
14058ae6d9c7SGiridhar Malavali for (cnt = 0; cnt < rsp->length; cnt++) {
14068ae6d9c7SGiridhar Malavali pkt->signature = RESPONSE_PROCESSED;
140704474d3aSBart Van Assche wrt_reg_dword((void __force __iomem *)&pkt->signature,
14081f8deefeSSaurav Kashyap RESPONSE_PROCESSED);
14098ae6d9c7SGiridhar Malavali pkt++;
14108ae6d9c7SGiridhar Malavali }
14118ae6d9c7SGiridhar Malavali }
14128ae6d9c7SGiridhar Malavali
14138ae6d9c7SGiridhar Malavali int
qlafx00_rescan_isp(scsi_qla_host_t * vha)14148ae6d9c7SGiridhar Malavali qlafx00_rescan_isp(scsi_qla_host_t *vha)
14158ae6d9c7SGiridhar Malavali {
14168ae6d9c7SGiridhar Malavali uint32_t status = QLA_FUNCTION_FAILED;
14178ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
14188ae6d9c7SGiridhar Malavali struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00;
14198ae6d9c7SGiridhar Malavali uint32_t aenmbx7;
14208ae6d9c7SGiridhar Malavali
14218ae6d9c7SGiridhar Malavali qla2x00_request_irqs(ha, ha->rsp_q_map[0]);
14228ae6d9c7SGiridhar Malavali
142304474d3aSBart Van Assche aenmbx7 = rd_reg_dword(®->aenmailbox7);
14248ae6d9c7SGiridhar Malavali ha->mbx_intr_code = MSW(aenmbx7);
14258ae6d9c7SGiridhar Malavali ha->rqstq_intr_code = LSW(aenmbx7);
142604474d3aSBart Van Assche ha->req_que_off = rd_reg_dword(®->aenmailbox1);
142704474d3aSBart Van Assche ha->rsp_que_off = rd_reg_dword(®->aenmailbox3);
142804474d3aSBart Van Assche ha->req_que_len = rd_reg_dword(®->aenmailbox5);
142904474d3aSBart Van Assche ha->rsp_que_len = rd_reg_dword(®->aenmailbox6);
14308ae6d9c7SGiridhar Malavali
14318ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_disc, vha, 0x2094,
14328ae6d9c7SGiridhar Malavali "fw returned mbx_intr_code: 0x%x, rqstq_intr_code: 0x%x "
14338ae6d9c7SGiridhar Malavali " Req que offset 0x%x Rsp que offset 0x%x\n",
14348ae6d9c7SGiridhar Malavali ha->mbx_intr_code, ha->rqstq_intr_code,
14358ae6d9c7SGiridhar Malavali ha->req_que_off, ha->rsp_que_len);
14368ae6d9c7SGiridhar Malavali
14378ae6d9c7SGiridhar Malavali /* Clear the Interrupts */
14388ae6d9c7SGiridhar Malavali QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS);
14398ae6d9c7SGiridhar Malavali
14408ae6d9c7SGiridhar Malavali status = qla2x00_init_rings(vha);
14418ae6d9c7SGiridhar Malavali if (!status) {
14428ae6d9c7SGiridhar Malavali vha->flags.online = 1;
14438ae6d9c7SGiridhar Malavali
14448ae6d9c7SGiridhar Malavali /* if no cable then assume it's good */
14458ae6d9c7SGiridhar Malavali if ((vha->device_flags & DFLG_NO_CABLE))
14468ae6d9c7SGiridhar Malavali status = 0;
14478ae6d9c7SGiridhar Malavali /* Register system information */
14488ae6d9c7SGiridhar Malavali if (qlafx00_fx_disc(vha,
14498ae6d9c7SGiridhar Malavali &vha->hw->mr.fcport, FXDISC_REG_HOST_INFO))
14508ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_disc, vha, 0x2095,
14518ae6d9c7SGiridhar Malavali "failed to register host info\n");
14528ae6d9c7SGiridhar Malavali }
14538ae6d9c7SGiridhar Malavali scsi_unblock_requests(vha->host);
14548ae6d9c7SGiridhar Malavali return status;
14558ae6d9c7SGiridhar Malavali }
14568ae6d9c7SGiridhar Malavali
14578ae6d9c7SGiridhar Malavali void
qlafx00_timer_routine(scsi_qla_host_t * vha)14588ae6d9c7SGiridhar Malavali qlafx00_timer_routine(scsi_qla_host_t *vha)
14598ae6d9c7SGiridhar Malavali {
14608ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
14618ae6d9c7SGiridhar Malavali uint32_t fw_heart_beat;
14628ae6d9c7SGiridhar Malavali uint32_t aenmbx0;
14638ae6d9c7SGiridhar Malavali struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00;
146471e56003SArmen Baloyan uint32_t tempc;
14658ae6d9c7SGiridhar Malavali
14668ae6d9c7SGiridhar Malavali /* Check firmware health */
14678ae6d9c7SGiridhar Malavali if (ha->mr.fw_hbt_cnt)
14688ae6d9c7SGiridhar Malavali ha->mr.fw_hbt_cnt--;
14698ae6d9c7SGiridhar Malavali else {
14708ae6d9c7SGiridhar Malavali if ((!ha->flags.mr_reset_hdlr_active) &&
14718ae6d9c7SGiridhar Malavali (!test_bit(UNLOADING, &vha->dpc_flags)) &&
14728ae6d9c7SGiridhar Malavali (!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) &&
14738ae6d9c7SGiridhar Malavali (ha->mr.fw_hbt_en)) {
147404474d3aSBart Van Assche fw_heart_beat = rd_reg_dword(®->fwheartbeat);
14758ae6d9c7SGiridhar Malavali if (fw_heart_beat != ha->mr.old_fw_hbt_cnt) {
14768ae6d9c7SGiridhar Malavali ha->mr.old_fw_hbt_cnt = fw_heart_beat;
14778ae6d9c7SGiridhar Malavali ha->mr.fw_hbt_miss_cnt = 0;
14788ae6d9c7SGiridhar Malavali } else {
14798ae6d9c7SGiridhar Malavali ha->mr.fw_hbt_miss_cnt++;
14808ae6d9c7SGiridhar Malavali if (ha->mr.fw_hbt_miss_cnt ==
14818ae6d9c7SGiridhar Malavali QLAFX00_HEARTBEAT_MISS_CNT) {
14828ae6d9c7SGiridhar Malavali set_bit(ISP_ABORT_NEEDED,
14838ae6d9c7SGiridhar Malavali &vha->dpc_flags);
14848ae6d9c7SGiridhar Malavali qla2xxx_wake_dpc(vha);
14858ae6d9c7SGiridhar Malavali ha->mr.fw_hbt_miss_cnt = 0;
14868ae6d9c7SGiridhar Malavali }
14878ae6d9c7SGiridhar Malavali }
14888ae6d9c7SGiridhar Malavali }
14898ae6d9c7SGiridhar Malavali ha->mr.fw_hbt_cnt = QLAFX00_HEARTBEAT_INTERVAL;
14908ae6d9c7SGiridhar Malavali }
14918ae6d9c7SGiridhar Malavali
14928ae6d9c7SGiridhar Malavali if (test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags)) {
14938ae6d9c7SGiridhar Malavali /* Reset recovery to be performed in timer routine */
149404474d3aSBart Van Assche aenmbx0 = rd_reg_dword(®->aenmailbox0);
14958ae6d9c7SGiridhar Malavali if (ha->mr.fw_reset_timer_exp) {
14968ae6d9c7SGiridhar Malavali set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
14978ae6d9c7SGiridhar Malavali qla2xxx_wake_dpc(vha);
14988ae6d9c7SGiridhar Malavali ha->mr.fw_reset_timer_exp = 0;
14998ae6d9c7SGiridhar Malavali } else if (aenmbx0 == MBA_FW_RESTART_CMPLT) {
15008ae6d9c7SGiridhar Malavali /* Wake up DPC to rescan the targets */
15018ae6d9c7SGiridhar Malavali set_bit(FX00_TARGET_SCAN, &vha->dpc_flags);
15028ae6d9c7SGiridhar Malavali clear_bit(FX00_RESET_RECOVERY, &vha->dpc_flags);
15038ae6d9c7SGiridhar Malavali qla2xxx_wake_dpc(vha);
15048ae6d9c7SGiridhar Malavali ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL;
15058ae6d9c7SGiridhar Malavali } else if ((aenmbx0 == MBA_FW_STARTING) &&
15068ae6d9c7SGiridhar Malavali (!ha->mr.fw_hbt_en)) {
15078ae6d9c7SGiridhar Malavali ha->mr.fw_hbt_en = 1;
15088ae6d9c7SGiridhar Malavali } else if (!ha->mr.fw_reset_timer_tick) {
15098ae6d9c7SGiridhar Malavali if (aenmbx0 == ha->mr.old_aenmbx0_state)
15108ae6d9c7SGiridhar Malavali ha->mr.fw_reset_timer_exp = 1;
15118ae6d9c7SGiridhar Malavali ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL;
15128ae6d9c7SGiridhar Malavali } else if (aenmbx0 == 0xFFFFFFFF) {
15138ae6d9c7SGiridhar Malavali uint32_t data0, data1;
15148ae6d9c7SGiridhar Malavali
15158ae6d9c7SGiridhar Malavali data0 = QLAFX00_RD_REG(ha,
15168ae6d9c7SGiridhar Malavali QLAFX00_BAR1_BASE_ADDR_REG);
15178ae6d9c7SGiridhar Malavali data1 = QLAFX00_RD_REG(ha,
15188ae6d9c7SGiridhar Malavali QLAFX00_PEX0_WIN0_BASE_ADDR_REG);
15198ae6d9c7SGiridhar Malavali
15208ae6d9c7SGiridhar Malavali data0 &= 0xffff0000;
15218ae6d9c7SGiridhar Malavali data1 &= 0x0000ffff;
15228ae6d9c7SGiridhar Malavali
15238ae6d9c7SGiridhar Malavali QLAFX00_WR_REG(ha,
15248ae6d9c7SGiridhar Malavali QLAFX00_PEX0_WIN0_BASE_ADDR_REG,
15258ae6d9c7SGiridhar Malavali (data0 | data1));
15268ae6d9c7SGiridhar Malavali } else if ((aenmbx0 & 0xFF00) == MBA_FW_POLL_STATE) {
15278ae6d9c7SGiridhar Malavali ha->mr.fw_reset_timer_tick =
15288ae6d9c7SGiridhar Malavali QLAFX00_MAX_RESET_INTERVAL;
1529b6511d99SArmen Baloyan } else if (aenmbx0 == MBA_FW_RESET_FCT) {
1530b6511d99SArmen Baloyan ha->mr.fw_reset_timer_tick =
1531b6511d99SArmen Baloyan QLAFX00_MAX_RESET_INTERVAL;
15328ae6d9c7SGiridhar Malavali }
1533e475f9c0SJan Kulich if (ha->mr.old_aenmbx0_state != aenmbx0) {
15348ae6d9c7SGiridhar Malavali ha->mr.old_aenmbx0_state = aenmbx0;
1535e475f9c0SJan Kulich ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL;
1536e475f9c0SJan Kulich }
15378ae6d9c7SGiridhar Malavali ha->mr.fw_reset_timer_tick--;
15388ae6d9c7SGiridhar Malavali }
153971e56003SArmen Baloyan if (test_bit(FX00_CRITEMP_RECOVERY, &vha->dpc_flags)) {
154071e56003SArmen Baloyan /*
154171e56003SArmen Baloyan * Critical temperature recovery to be
154271e56003SArmen Baloyan * performed in timer routine
154371e56003SArmen Baloyan */
154471e56003SArmen Baloyan if (ha->mr.fw_critemp_timer_tick == 0) {
154571e56003SArmen Baloyan tempc = QLAFX00_GET_TEMPERATURE(ha);
15466ddcfef7SSaurav Kashyap ql_dbg(ql_dbg_timer, vha, 0x6012,
154771e56003SArmen Baloyan "ISPFx00(%s): Critical temp timer, "
154871e56003SArmen Baloyan "current SOC temperature: %d\n",
154971e56003SArmen Baloyan __func__, tempc);
155071e56003SArmen Baloyan if (tempc < ha->mr.critical_temperature) {
155171e56003SArmen Baloyan set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
155271e56003SArmen Baloyan clear_bit(FX00_CRITEMP_RECOVERY,
155371e56003SArmen Baloyan &vha->dpc_flags);
155471e56003SArmen Baloyan qla2xxx_wake_dpc(vha);
155571e56003SArmen Baloyan }
155671e56003SArmen Baloyan ha->mr.fw_critemp_timer_tick =
155771e56003SArmen Baloyan QLAFX00_CRITEMP_INTERVAL;
155871e56003SArmen Baloyan } else {
155971e56003SArmen Baloyan ha->mr.fw_critemp_timer_tick--;
156071e56003SArmen Baloyan }
156171e56003SArmen Baloyan }
1562e8f5e95dSArmen Baloyan if (ha->mr.host_info_resend) {
1563e8f5e95dSArmen Baloyan /*
1564e8f5e95dSArmen Baloyan * Incomplete host info might be sent to firmware
1565e8f5e95dSArmen Baloyan * durinng system boot - info should be resend
1566e8f5e95dSArmen Baloyan */
1567e8f5e95dSArmen Baloyan if (ha->mr.hinfo_resend_timer_tick == 0) {
1568e8f5e95dSArmen Baloyan ha->mr.host_info_resend = false;
1569e8f5e95dSArmen Baloyan set_bit(FX00_HOST_INFO_RESEND, &vha->dpc_flags);
1570e8f5e95dSArmen Baloyan ha->mr.hinfo_resend_timer_tick =
1571e8f5e95dSArmen Baloyan QLAFX00_HINFO_RESEND_INTERVAL;
1572e8f5e95dSArmen Baloyan qla2xxx_wake_dpc(vha);
1573e8f5e95dSArmen Baloyan } else {
1574e8f5e95dSArmen Baloyan ha->mr.hinfo_resend_timer_tick--;
1575e8f5e95dSArmen Baloyan }
1576e8f5e95dSArmen Baloyan }
1577e8f5e95dSArmen Baloyan
15788ae6d9c7SGiridhar Malavali }
15798ae6d9c7SGiridhar Malavali
15808ae6d9c7SGiridhar Malavali /*
15818ae6d9c7SGiridhar Malavali * qlfx00a_reset_initialize
15828ae6d9c7SGiridhar Malavali * Re-initialize after a iSA device reset.
15838ae6d9c7SGiridhar Malavali *
15848ae6d9c7SGiridhar Malavali * Input:
15858ae6d9c7SGiridhar Malavali * ha = adapter block pointer.
15868ae6d9c7SGiridhar Malavali *
15878ae6d9c7SGiridhar Malavali * Returns:
15888ae6d9c7SGiridhar Malavali * 0 = success
15898ae6d9c7SGiridhar Malavali */
15908ae6d9c7SGiridhar Malavali int
qlafx00_reset_initialize(scsi_qla_host_t * vha)15918ae6d9c7SGiridhar Malavali qlafx00_reset_initialize(scsi_qla_host_t *vha)
15928ae6d9c7SGiridhar Malavali {
15938ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
15948ae6d9c7SGiridhar Malavali
15958ae6d9c7SGiridhar Malavali if (vha->device_flags & DFLG_DEV_FAILED) {
15968ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x0142,
15978ae6d9c7SGiridhar Malavali "Device in failed state\n");
15988ae6d9c7SGiridhar Malavali return QLA_SUCCESS;
15998ae6d9c7SGiridhar Malavali }
16008ae6d9c7SGiridhar Malavali
16018ae6d9c7SGiridhar Malavali ha->flags.mr_reset_hdlr_active = 1;
16028ae6d9c7SGiridhar Malavali
16038ae6d9c7SGiridhar Malavali if (vha->flags.online) {
16048ae6d9c7SGiridhar Malavali scsi_block_requests(vha->host);
160571e56003SArmen Baloyan qlafx00_abort_isp_cleanup(vha, false);
16068ae6d9c7SGiridhar Malavali }
16078ae6d9c7SGiridhar Malavali
16088ae6d9c7SGiridhar Malavali ql_log(ql_log_info, vha, 0x0143,
16098ae6d9c7SGiridhar Malavali "(%s): succeeded.\n", __func__);
16108ae6d9c7SGiridhar Malavali ha->flags.mr_reset_hdlr_active = 0;
16118ae6d9c7SGiridhar Malavali return QLA_SUCCESS;
16128ae6d9c7SGiridhar Malavali }
16138ae6d9c7SGiridhar Malavali
16148ae6d9c7SGiridhar Malavali /*
16158ae6d9c7SGiridhar Malavali * qlafx00_abort_isp
16168ae6d9c7SGiridhar Malavali * Resets ISP and aborts all outstanding commands.
16178ae6d9c7SGiridhar Malavali *
16188ae6d9c7SGiridhar Malavali * Input:
16198ae6d9c7SGiridhar Malavali * ha = adapter block pointer.
16208ae6d9c7SGiridhar Malavali *
16218ae6d9c7SGiridhar Malavali * Returns:
16228ae6d9c7SGiridhar Malavali * 0 = success
16238ae6d9c7SGiridhar Malavali */
16248ae6d9c7SGiridhar Malavali int
qlafx00_abort_isp(scsi_qla_host_t * vha)16258ae6d9c7SGiridhar Malavali qlafx00_abort_isp(scsi_qla_host_t *vha)
16268ae6d9c7SGiridhar Malavali {
16278ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
16288ae6d9c7SGiridhar Malavali
16298ae6d9c7SGiridhar Malavali if (vha->flags.online) {
16308ae6d9c7SGiridhar Malavali if (unlikely(pci_channel_offline(ha->pdev) &&
16318ae6d9c7SGiridhar Malavali ha->flags.pci_channel_io_perm_failure)) {
16328ae6d9c7SGiridhar Malavali clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
16338ae6d9c7SGiridhar Malavali return QLA_SUCCESS;
16348ae6d9c7SGiridhar Malavali }
16358ae6d9c7SGiridhar Malavali
16368ae6d9c7SGiridhar Malavali scsi_block_requests(vha->host);
163771e56003SArmen Baloyan qlafx00_abort_isp_cleanup(vha, false);
1638e601d778SArmen Baloyan } else {
1639e601d778SArmen Baloyan scsi_block_requests(vha->host);
1640e601d778SArmen Baloyan clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
1641e601d778SArmen Baloyan vha->qla_stats.total_isp_aborts++;
1642e601d778SArmen Baloyan ha->isp_ops->reset_chip(vha);
1643e601d778SArmen Baloyan set_bit(FX00_RESET_RECOVERY, &vha->dpc_flags);
1644e601d778SArmen Baloyan /* Clear the Interrupts */
1645e601d778SArmen Baloyan QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS);
16468ae6d9c7SGiridhar Malavali }
16478ae6d9c7SGiridhar Malavali
16488ae6d9c7SGiridhar Malavali ql_log(ql_log_info, vha, 0x0145,
16498ae6d9c7SGiridhar Malavali "(%s): succeeded.\n", __func__);
16508ae6d9c7SGiridhar Malavali
16518ae6d9c7SGiridhar Malavali return QLA_SUCCESS;
16528ae6d9c7SGiridhar Malavali }
16538ae6d9c7SGiridhar Malavali
16548ae6d9c7SGiridhar Malavali static inline fc_port_t*
qlafx00_get_fcport(struct scsi_qla_host * vha,int tgt_id)16558ae6d9c7SGiridhar Malavali qlafx00_get_fcport(struct scsi_qla_host *vha, int tgt_id)
16568ae6d9c7SGiridhar Malavali {
16578ae6d9c7SGiridhar Malavali fc_port_t *fcport;
16588ae6d9c7SGiridhar Malavali
16598ae6d9c7SGiridhar Malavali /* Check for matching device in remote port list. */
16608ae6d9c7SGiridhar Malavali list_for_each_entry(fcport, &vha->vp_fcports, list) {
16618ae6d9c7SGiridhar Malavali if (fcport->tgt_id == tgt_id) {
16628ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_async, vha, 0x5072,
16638ae6d9c7SGiridhar Malavali "Matching fcport(%p) found with TGT-ID: 0x%x "
16648ae6d9c7SGiridhar Malavali "and Remote TGT_ID: 0x%x\n",
16658ae6d9c7SGiridhar Malavali fcport, fcport->tgt_id, tgt_id);
16668ae6d9c7SGiridhar Malavali return fcport;
16678ae6d9c7SGiridhar Malavali }
166824a42d50SJoe Carnuccio }
166924a42d50SJoe Carnuccio return NULL;
167024a42d50SJoe Carnuccio }
16718ae6d9c7SGiridhar Malavali
16728ae6d9c7SGiridhar Malavali static void
qlafx00_tgt_detach(struct scsi_qla_host * vha,int tgt_id)16738ae6d9c7SGiridhar Malavali qlafx00_tgt_detach(struct scsi_qla_host *vha, int tgt_id)
16748ae6d9c7SGiridhar Malavali {
16758ae6d9c7SGiridhar Malavali fc_port_t *fcport;
16768ae6d9c7SGiridhar Malavali
16778ae6d9c7SGiridhar Malavali ql_log(ql_log_info, vha, 0x5073,
16788ae6d9c7SGiridhar Malavali "Detach TGT-ID: 0x%x\n", tgt_id);
16798ae6d9c7SGiridhar Malavali
16808ae6d9c7SGiridhar Malavali fcport = qlafx00_get_fcport(vha, tgt_id);
16818ae6d9c7SGiridhar Malavali if (!fcport)
16828ae6d9c7SGiridhar Malavali return;
16838ae6d9c7SGiridhar Malavali
16843c75ad1dSHimanshu Madhani qla2x00_mark_device_lost(vha, fcport, 0);
16858ae6d9c7SGiridhar Malavali
16868ae6d9c7SGiridhar Malavali return;
16878ae6d9c7SGiridhar Malavali }
16888ae6d9c7SGiridhar Malavali
168988bfdf56SJason Yan void
qlafx00_process_aen(struct scsi_qla_host * vha,struct qla_work_evt * evt)16908ae6d9c7SGiridhar Malavali qlafx00_process_aen(struct scsi_qla_host *vha, struct qla_work_evt *evt)
16918ae6d9c7SGiridhar Malavali {
16928ae6d9c7SGiridhar Malavali uint32_t aen_code, aen_data;
16938ae6d9c7SGiridhar Malavali
16948ae6d9c7SGiridhar Malavali aen_code = FCH_EVT_VENDOR_UNIQUE;
16958ae6d9c7SGiridhar Malavali aen_data = evt->u.aenfx.evtcode;
16968ae6d9c7SGiridhar Malavali
16978ae6d9c7SGiridhar Malavali switch (evt->u.aenfx.evtcode) {
16988ae6d9c7SGiridhar Malavali case QLAFX00_MBA_PORT_UPDATE: /* Port database update */
16998ae6d9c7SGiridhar Malavali if (evt->u.aenfx.mbx[1] == 0) {
17008ae6d9c7SGiridhar Malavali if (evt->u.aenfx.mbx[2] == 1) {
17018ae6d9c7SGiridhar Malavali if (!vha->flags.fw_tgt_reported)
17028ae6d9c7SGiridhar Malavali vha->flags.fw_tgt_reported = 1;
17038ae6d9c7SGiridhar Malavali atomic_set(&vha->loop_down_timer, 0);
17048ae6d9c7SGiridhar Malavali atomic_set(&vha->loop_state, LOOP_UP);
17058ae6d9c7SGiridhar Malavali set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
17068ae6d9c7SGiridhar Malavali qla2xxx_wake_dpc(vha);
17078ae6d9c7SGiridhar Malavali } else if (evt->u.aenfx.mbx[2] == 2) {
17088ae6d9c7SGiridhar Malavali qlafx00_tgt_detach(vha, evt->u.aenfx.mbx[3]);
17098ae6d9c7SGiridhar Malavali }
17108ae6d9c7SGiridhar Malavali } else if (evt->u.aenfx.mbx[1] == 0xffff) {
17118ae6d9c7SGiridhar Malavali if (evt->u.aenfx.mbx[2] == 1) {
17128ae6d9c7SGiridhar Malavali if (!vha->flags.fw_tgt_reported)
17138ae6d9c7SGiridhar Malavali vha->flags.fw_tgt_reported = 1;
17148ae6d9c7SGiridhar Malavali set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
17158ae6d9c7SGiridhar Malavali } else if (evt->u.aenfx.mbx[2] == 2) {
17168ae6d9c7SGiridhar Malavali vha->device_flags |= DFLG_NO_CABLE;
17173c75ad1dSHimanshu Madhani qla2x00_mark_all_devices_lost(vha);
17188ae6d9c7SGiridhar Malavali }
17198ae6d9c7SGiridhar Malavali }
17208ae6d9c7SGiridhar Malavali break;
17218ae6d9c7SGiridhar Malavali case QLAFX00_MBA_LINK_UP:
17228ae6d9c7SGiridhar Malavali aen_code = FCH_EVT_LINKUP;
17238ae6d9c7SGiridhar Malavali aen_data = 0;
17248ae6d9c7SGiridhar Malavali break;
17258ae6d9c7SGiridhar Malavali case QLAFX00_MBA_LINK_DOWN:
17268ae6d9c7SGiridhar Malavali aen_code = FCH_EVT_LINKDOWN;
17278ae6d9c7SGiridhar Malavali aen_data = 0;
17288ae6d9c7SGiridhar Malavali break;
172971e56003SArmen Baloyan case QLAFX00_MBA_TEMP_CRIT: /* Critical temperature event */
173071e56003SArmen Baloyan ql_log(ql_log_info, vha, 0x5082,
173171e56003SArmen Baloyan "Process critical temperature event "
173271e56003SArmen Baloyan "aenmb[0]: %x\n",
173371e56003SArmen Baloyan evt->u.aenfx.evtcode);
173471e56003SArmen Baloyan scsi_block_requests(vha->host);
173571e56003SArmen Baloyan qlafx00_abort_isp_cleanup(vha, true);
173671e56003SArmen Baloyan scsi_unblock_requests(vha->host);
173771e56003SArmen Baloyan break;
17388ae6d9c7SGiridhar Malavali }
17398ae6d9c7SGiridhar Malavali
17408ae6d9c7SGiridhar Malavali fc_host_post_event(vha->host, fc_get_event_number(),
17418ae6d9c7SGiridhar Malavali aen_code, aen_data);
17428ae6d9c7SGiridhar Malavali }
17438ae6d9c7SGiridhar Malavali
17448ae6d9c7SGiridhar Malavali static void
qlafx00_update_host_attr(scsi_qla_host_t * vha,struct port_info_data * pinfo)17458ae6d9c7SGiridhar Malavali qlafx00_update_host_attr(scsi_qla_host_t *vha, struct port_info_data *pinfo)
17468ae6d9c7SGiridhar Malavali {
17478ae6d9c7SGiridhar Malavali u64 port_name = 0, node_name = 0;
17488ae6d9c7SGiridhar Malavali
17498ae6d9c7SGiridhar Malavali port_name = (unsigned long long)wwn_to_u64(pinfo->port_name);
17508ae6d9c7SGiridhar Malavali node_name = (unsigned long long)wwn_to_u64(pinfo->node_name);
17518ae6d9c7SGiridhar Malavali
17528ae6d9c7SGiridhar Malavali fc_host_node_name(vha->host) = node_name;
17538ae6d9c7SGiridhar Malavali fc_host_port_name(vha->host) = port_name;
17548ae6d9c7SGiridhar Malavali if (!pinfo->port_type)
17558ae6d9c7SGiridhar Malavali vha->hw->current_topology = ISP_CFG_F;
17568ae6d9c7SGiridhar Malavali if (pinfo->link_status == QLAFX00_LINK_STATUS_UP)
17578ae6d9c7SGiridhar Malavali atomic_set(&vha->loop_state, LOOP_READY);
17588ae6d9c7SGiridhar Malavali else if (pinfo->link_status == QLAFX00_LINK_STATUS_DOWN)
17598ae6d9c7SGiridhar Malavali atomic_set(&vha->loop_state, LOOP_DOWN);
17608ae6d9c7SGiridhar Malavali vha->hw->link_data_rate = (uint16_t)pinfo->link_config;
17618ae6d9c7SGiridhar Malavali }
17628ae6d9c7SGiridhar Malavali
17638ae6d9c7SGiridhar Malavali static void
qla2x00_fxdisc_iocb_timeout(void * data)17648ae6d9c7SGiridhar Malavali qla2x00_fxdisc_iocb_timeout(void *data)
17658ae6d9c7SGiridhar Malavali {
176625ff6af1SJoe Carnuccio srb_t *sp = data;
17678ae6d9c7SGiridhar Malavali struct srb_iocb *lio = &sp->u.iocb_cmd;
17688ae6d9c7SGiridhar Malavali
17698ae6d9c7SGiridhar Malavali complete(&lio->u.fxiocb.fxiocb_comp);
17708ae6d9c7SGiridhar Malavali }
17718ae6d9c7SGiridhar Malavali
qla2x00_fxdisc_sp_done(srb_t * sp,int res)17726c18a43eSBart Van Assche static void qla2x00_fxdisc_sp_done(srb_t *sp, int res)
17738ae6d9c7SGiridhar Malavali {
17748ae6d9c7SGiridhar Malavali struct srb_iocb *lio = &sp->u.iocb_cmd;
17758ae6d9c7SGiridhar Malavali
17768ae6d9c7SGiridhar Malavali complete(&lio->u.fxiocb.fxiocb_comp);
17778ae6d9c7SGiridhar Malavali }
17788ae6d9c7SGiridhar Malavali
17798ae6d9c7SGiridhar Malavali int
qlafx00_fx_disc(scsi_qla_host_t * vha,fc_port_t * fcport,uint16_t fx_type)17801f8deefeSSaurav Kashyap qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
17818ae6d9c7SGiridhar Malavali {
17828ae6d9c7SGiridhar Malavali srb_t *sp;
17838ae6d9c7SGiridhar Malavali struct srb_iocb *fdisc;
17848ae6d9c7SGiridhar Malavali int rval = QLA_FUNCTION_FAILED;
17858ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
17868ae6d9c7SGiridhar Malavali struct host_system_info *phost_info;
17878ae6d9c7SGiridhar Malavali struct register_host_info *preg_hsi;
17888ae6d9c7SGiridhar Malavali struct new_utsname *p_sysid = NULL;
17898ae6d9c7SGiridhar Malavali
179031e6cdbeSSaurav Kashyap /* ref: INIT */
17918ae6d9c7SGiridhar Malavali sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
17928ae6d9c7SGiridhar Malavali if (!sp)
17938ae6d9c7SGiridhar Malavali goto done;
17948ae6d9c7SGiridhar Malavali
1795e0824e69SJoe Carnuccio sp->type = SRB_FXIOCB_DCMD;
1796e0824e69SJoe Carnuccio sp->name = "fxdisc";
1797d4523bd6SDaniel Wagner qla2x00_init_async_sp(sp, FXDISC_TIMEOUT,
1798d4523bd6SDaniel Wagner qla2x00_fxdisc_sp_done);
1799d4523bd6SDaniel Wagner sp->u.iocb_cmd.timeout = qla2x00_fxdisc_iocb_timeout;
1800e0824e69SJoe Carnuccio
18018ae6d9c7SGiridhar Malavali fdisc = &sp->u.iocb_cmd;
18028ae6d9c7SGiridhar Malavali switch (fx_type) {
18038ae6d9c7SGiridhar Malavali case FXDISC_GET_CONFIG_INFO:
18048ae6d9c7SGiridhar Malavali fdisc->u.fxiocb.flags =
18058ae6d9c7SGiridhar Malavali SRB_FXDISC_RESP_DMA_VALID;
18068ae6d9c7SGiridhar Malavali fdisc->u.fxiocb.rsp_len = sizeof(struct config_info_data);
18078ae6d9c7SGiridhar Malavali break;
18088ae6d9c7SGiridhar Malavali case FXDISC_GET_PORT_INFO:
18098ae6d9c7SGiridhar Malavali fdisc->u.fxiocb.flags =
18108ae6d9c7SGiridhar Malavali SRB_FXDISC_RESP_DMA_VALID | SRB_FXDISC_REQ_DWRD_VALID;
18118ae6d9c7SGiridhar Malavali fdisc->u.fxiocb.rsp_len = QLAFX00_PORT_DATA_INFO;
18121f8deefeSSaurav Kashyap fdisc->u.fxiocb.req_data = cpu_to_le32(fcport->port_id);
18138ae6d9c7SGiridhar Malavali break;
18148ae6d9c7SGiridhar Malavali case FXDISC_GET_TGT_NODE_INFO:
18158ae6d9c7SGiridhar Malavali fdisc->u.fxiocb.flags =
18168ae6d9c7SGiridhar Malavali SRB_FXDISC_RESP_DMA_VALID | SRB_FXDISC_REQ_DWRD_VALID;
18178ae6d9c7SGiridhar Malavali fdisc->u.fxiocb.rsp_len = QLAFX00_TGT_NODE_INFO;
18181f8deefeSSaurav Kashyap fdisc->u.fxiocb.req_data = cpu_to_le32(fcport->tgt_id);
18198ae6d9c7SGiridhar Malavali break;
18208ae6d9c7SGiridhar Malavali case FXDISC_GET_TGT_NODE_LIST:
18218ae6d9c7SGiridhar Malavali fdisc->u.fxiocb.flags =
18228ae6d9c7SGiridhar Malavali SRB_FXDISC_RESP_DMA_VALID | SRB_FXDISC_REQ_DWRD_VALID;
18238ae6d9c7SGiridhar Malavali fdisc->u.fxiocb.rsp_len = QLAFX00_TGT_NODE_LIST_SIZE;
18248ae6d9c7SGiridhar Malavali break;
18258ae6d9c7SGiridhar Malavali case FXDISC_REG_HOST_INFO:
18268ae6d9c7SGiridhar Malavali fdisc->u.fxiocb.flags = SRB_FXDISC_REQ_DMA_VALID;
18278ae6d9c7SGiridhar Malavali fdisc->u.fxiocb.req_len = sizeof(struct register_host_info);
18288ae6d9c7SGiridhar Malavali p_sysid = utsname();
18298ae6d9c7SGiridhar Malavali if (!p_sysid) {
18308ae6d9c7SGiridhar Malavali ql_log(ql_log_warn, vha, 0x303c,
18310b1587b1SMasanari Iida "Not able to get the system information\n");
18328ae6d9c7SGiridhar Malavali goto done_free_sp;
18338ae6d9c7SGiridhar Malavali }
18348ae6d9c7SGiridhar Malavali break;
1835767157c5SArmen Baloyan case FXDISC_ABORT_IOCTL:
18368ae6d9c7SGiridhar Malavali default:
18378ae6d9c7SGiridhar Malavali break;
18388ae6d9c7SGiridhar Malavali }
18398ae6d9c7SGiridhar Malavali
18408ae6d9c7SGiridhar Malavali if (fdisc->u.fxiocb.flags & SRB_FXDISC_REQ_DMA_VALID) {
18418ae6d9c7SGiridhar Malavali fdisc->u.fxiocb.req_addr = dma_alloc_coherent(&ha->pdev->dev,
18428ae6d9c7SGiridhar Malavali fdisc->u.fxiocb.req_len,
18438ae6d9c7SGiridhar Malavali &fdisc->u.fxiocb.req_dma_handle, GFP_KERNEL);
18448ae6d9c7SGiridhar Malavali if (!fdisc->u.fxiocb.req_addr)
18458ae6d9c7SGiridhar Malavali goto done_free_sp;
18468ae6d9c7SGiridhar Malavali
18478ae6d9c7SGiridhar Malavali if (fx_type == FXDISC_REG_HOST_INFO) {
18488ae6d9c7SGiridhar Malavali preg_hsi = (struct register_host_info *)
18498ae6d9c7SGiridhar Malavali fdisc->u.fxiocb.req_addr;
18508ae6d9c7SGiridhar Malavali phost_info = &preg_hsi->hsi;
18518ae6d9c7SGiridhar Malavali memset(preg_hsi, 0, sizeof(struct register_host_info));
18528ae6d9c7SGiridhar Malavali phost_info->os_type = OS_TYPE_LINUX;
185337f1663cSAzeem Shaikh strscpy(phost_info->sysname, p_sysid->sysname,
1854cc74049fSBart Van Assche sizeof(phost_info->sysname));
185537f1663cSAzeem Shaikh strscpy(phost_info->nodename, p_sysid->nodename,
1856cc74049fSBart Van Assche sizeof(phost_info->nodename));
1857e8f5e95dSArmen Baloyan if (!strcmp(phost_info->nodename, "(none)"))
1858e8f5e95dSArmen Baloyan ha->mr.host_info_resend = true;
185937f1663cSAzeem Shaikh strscpy(phost_info->release, p_sysid->release,
1860cc74049fSBart Van Assche sizeof(phost_info->release));
186137f1663cSAzeem Shaikh strscpy(phost_info->version, p_sysid->version,
1862cc74049fSBart Van Assche sizeof(phost_info->version));
186337f1663cSAzeem Shaikh strscpy(phost_info->machine, p_sysid->machine,
1864cc74049fSBart Van Assche sizeof(phost_info->machine));
186537f1663cSAzeem Shaikh strscpy(phost_info->domainname, p_sysid->domainname,
1866cc74049fSBart Van Assche sizeof(phost_info->domainname));
186737f1663cSAzeem Shaikh strscpy(phost_info->hostdriver, QLA2XXX_VERSION,
1868cc74049fSBart Van Assche sizeof(phost_info->hostdriver));
18695ea33eb5STina Ruchandani preg_hsi->utc = (uint64_t)ktime_get_real_seconds();
18708ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x0149,
18718ae6d9c7SGiridhar Malavali "ISP%04X: Host registration with firmware\n",
18728ae6d9c7SGiridhar Malavali ha->pdev->device);
18738ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x014a,
18748ae6d9c7SGiridhar Malavali "os_type = '%d', sysname = '%s', nodname = '%s'\n",
18758ae6d9c7SGiridhar Malavali phost_info->os_type,
18768ae6d9c7SGiridhar Malavali phost_info->sysname,
18778ae6d9c7SGiridhar Malavali phost_info->nodename);
18788ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x014b,
18798ae6d9c7SGiridhar Malavali "release = '%s', version = '%s'\n",
18808ae6d9c7SGiridhar Malavali phost_info->release,
18818ae6d9c7SGiridhar Malavali phost_info->version);
18828ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x014c,
18838ae6d9c7SGiridhar Malavali "machine = '%s' "
18848ae6d9c7SGiridhar Malavali "domainname = '%s', hostdriver = '%s'\n",
18858ae6d9c7SGiridhar Malavali phost_info->machine,
18868ae6d9c7SGiridhar Malavali phost_info->domainname,
18878ae6d9c7SGiridhar Malavali phost_info->hostdriver);
18888ae6d9c7SGiridhar Malavali ql_dump_buffer(ql_dbg_init + ql_dbg_disc, vha, 0x014d,
1889f8f97b0cSJoe Carnuccio phost_info, sizeof(*phost_info));
18908ae6d9c7SGiridhar Malavali }
18918ae6d9c7SGiridhar Malavali }
18928ae6d9c7SGiridhar Malavali
18938ae6d9c7SGiridhar Malavali if (fdisc->u.fxiocb.flags & SRB_FXDISC_RESP_DMA_VALID) {
18948ae6d9c7SGiridhar Malavali fdisc->u.fxiocb.rsp_addr = dma_alloc_coherent(&ha->pdev->dev,
18958ae6d9c7SGiridhar Malavali fdisc->u.fxiocb.rsp_len,
18968ae6d9c7SGiridhar Malavali &fdisc->u.fxiocb.rsp_dma_handle, GFP_KERNEL);
18978ae6d9c7SGiridhar Malavali if (!fdisc->u.fxiocb.rsp_addr)
18988ae6d9c7SGiridhar Malavali goto done_unmap_req;
18998ae6d9c7SGiridhar Malavali }
19008ae6d9c7SGiridhar Malavali
19011f8deefeSSaurav Kashyap fdisc->u.fxiocb.req_func_type = cpu_to_le16(fx_type);
19028ae6d9c7SGiridhar Malavali
19038ae6d9c7SGiridhar Malavali rval = qla2x00_start_sp(sp);
19048ae6d9c7SGiridhar Malavali if (rval != QLA_SUCCESS)
19058ae6d9c7SGiridhar Malavali goto done_unmap_dma;
19068ae6d9c7SGiridhar Malavali
19078ae6d9c7SGiridhar Malavali wait_for_completion(&fdisc->u.fxiocb.fxiocb_comp);
19088ae6d9c7SGiridhar Malavali
19098ae6d9c7SGiridhar Malavali if (fx_type == FXDISC_GET_CONFIG_INFO) {
19108ae6d9c7SGiridhar Malavali struct config_info_data *pinfo =
19118ae6d9c7SGiridhar Malavali (struct config_info_data *) fdisc->u.fxiocb.rsp_addr;
1912*c3408c4aSKees Cook memtostr(vha->hw->model_number, pinfo->model_num);
1913*c3408c4aSKees Cook memtostr(vha->hw->model_desc, pinfo->model_description);
19148ae6d9c7SGiridhar Malavali memcpy(&vha->hw->mr.symbolic_name, pinfo->symbolic_name,
19158ae6d9c7SGiridhar Malavali sizeof(vha->hw->mr.symbolic_name));
19168ae6d9c7SGiridhar Malavali memcpy(&vha->hw->mr.serial_num, pinfo->serial_num,
19178ae6d9c7SGiridhar Malavali sizeof(vha->hw->mr.serial_num));
19188ae6d9c7SGiridhar Malavali memcpy(&vha->hw->mr.hw_version, pinfo->hw_version,
19198ae6d9c7SGiridhar Malavali sizeof(vha->hw->mr.hw_version));
19208ae6d9c7SGiridhar Malavali memcpy(&vha->hw->mr.fw_version, pinfo->fw_version,
19218ae6d9c7SGiridhar Malavali sizeof(vha->hw->mr.fw_version));
19228ae6d9c7SGiridhar Malavali strim(vha->hw->mr.fw_version);
19238ae6d9c7SGiridhar Malavali memcpy(&vha->hw->mr.uboot_version, pinfo->uboot_version,
19248ae6d9c7SGiridhar Malavali sizeof(vha->hw->mr.uboot_version));
19258ae6d9c7SGiridhar Malavali memcpy(&vha->hw->mr.fru_serial_num, pinfo->fru_serial_num,
19268ae6d9c7SGiridhar Malavali sizeof(vha->hw->mr.fru_serial_num));
1927f875cd4cSArmen Baloyan vha->hw->mr.critical_temperature =
1928f875cd4cSArmen Baloyan (pinfo->nominal_temp_value) ?
1929f875cd4cSArmen Baloyan pinfo->nominal_temp_value : QLAFX00_CRITEMP_THRSHLD;
19301fe19ee4SArmen Baloyan ha->mr.extended_io_enabled = (pinfo->enabled_capabilities &
19311fe19ee4SArmen Baloyan QLAFX00_EXTENDED_IO_EN_MASK) != 0;
19328ae6d9c7SGiridhar Malavali } else if (fx_type == FXDISC_GET_PORT_INFO) {
19338ae6d9c7SGiridhar Malavali struct port_info_data *pinfo =
19348ae6d9c7SGiridhar Malavali (struct port_info_data *) fdisc->u.fxiocb.rsp_addr;
19358ae6d9c7SGiridhar Malavali memcpy(vha->node_name, pinfo->node_name, WWN_SIZE);
19368ae6d9c7SGiridhar Malavali memcpy(vha->port_name, pinfo->port_name, WWN_SIZE);
19378ae6d9c7SGiridhar Malavali vha->d_id.b.domain = pinfo->port_id[0];
19388ae6d9c7SGiridhar Malavali vha->d_id.b.area = pinfo->port_id[1];
19398ae6d9c7SGiridhar Malavali vha->d_id.b.al_pa = pinfo->port_id[2];
19408ae6d9c7SGiridhar Malavali qlafx00_update_host_attr(vha, pinfo);
19418ae6d9c7SGiridhar Malavali ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0141,
1942f8f97b0cSJoe Carnuccio pinfo, 16);
19438ae6d9c7SGiridhar Malavali } else if (fx_type == FXDISC_GET_TGT_NODE_INFO) {
19448ae6d9c7SGiridhar Malavali struct qlafx00_tgt_node_info *pinfo =
19458ae6d9c7SGiridhar Malavali (struct qlafx00_tgt_node_info *) fdisc->u.fxiocb.rsp_addr;
19468ae6d9c7SGiridhar Malavali memcpy(fcport->node_name, pinfo->tgt_node_wwnn, WWN_SIZE);
19478ae6d9c7SGiridhar Malavali memcpy(fcport->port_name, pinfo->tgt_node_wwpn, WWN_SIZE);
19488ae6d9c7SGiridhar Malavali fcport->port_type = FCT_TARGET;
19498ae6d9c7SGiridhar Malavali ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0144,
1950f8f97b0cSJoe Carnuccio pinfo, 16);
19518ae6d9c7SGiridhar Malavali } else if (fx_type == FXDISC_GET_TGT_NODE_LIST) {
19528ae6d9c7SGiridhar Malavali struct qlafx00_tgt_node_info *pinfo =
19538ae6d9c7SGiridhar Malavali (struct qlafx00_tgt_node_info *) fdisc->u.fxiocb.rsp_addr;
19548ae6d9c7SGiridhar Malavali ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0146,
1955f8f97b0cSJoe Carnuccio pinfo, 16);
19568ae6d9c7SGiridhar Malavali memcpy(vha->hw->gid_list, pinfo, QLAFX00_TGT_NODE_LIST_SIZE);
1957767157c5SArmen Baloyan } else if (fx_type == FXDISC_ABORT_IOCTL)
1958767157c5SArmen Baloyan fdisc->u.fxiocb.result =
1959b593931dSArmen Baloyan (fdisc->u.fxiocb.result ==
1960b593931dSArmen Baloyan cpu_to_le32(QLAFX00_IOCTL_ICOB_ABORT_SUCCESS)) ?
1961767157c5SArmen Baloyan cpu_to_le32(QLA_SUCCESS) : cpu_to_le32(QLA_FUNCTION_FAILED);
1962767157c5SArmen Baloyan
19631f8deefeSSaurav Kashyap rval = le32_to_cpu(fdisc->u.fxiocb.result);
19648ae6d9c7SGiridhar Malavali
19658ae6d9c7SGiridhar Malavali done_unmap_dma:
19668ae6d9c7SGiridhar Malavali if (fdisc->u.fxiocb.rsp_addr)
19678ae6d9c7SGiridhar Malavali dma_free_coherent(&ha->pdev->dev, fdisc->u.fxiocb.rsp_len,
19688ae6d9c7SGiridhar Malavali fdisc->u.fxiocb.rsp_addr, fdisc->u.fxiocb.rsp_dma_handle);
19698ae6d9c7SGiridhar Malavali
19708ae6d9c7SGiridhar Malavali done_unmap_req:
19718ae6d9c7SGiridhar Malavali if (fdisc->u.fxiocb.req_addr)
19728ae6d9c7SGiridhar Malavali dma_free_coherent(&ha->pdev->dev, fdisc->u.fxiocb.req_len,
19738ae6d9c7SGiridhar Malavali fdisc->u.fxiocb.req_addr, fdisc->u.fxiocb.req_dma_handle);
19748ae6d9c7SGiridhar Malavali done_free_sp:
197531e6cdbeSSaurav Kashyap /* ref: INIT */
197631e6cdbeSSaurav Kashyap kref_put(&sp->cmd_kref, qla2x00_sp_release);
19778ae6d9c7SGiridhar Malavali done:
19788ae6d9c7SGiridhar Malavali return rval;
19798ae6d9c7SGiridhar Malavali }
19808ae6d9c7SGiridhar Malavali
19818ae6d9c7SGiridhar Malavali /*
19828ae6d9c7SGiridhar Malavali * qlafx00_initialize_adapter
19838ae6d9c7SGiridhar Malavali * Initialize board.
19848ae6d9c7SGiridhar Malavali *
19858ae6d9c7SGiridhar Malavali * Input:
19868ae6d9c7SGiridhar Malavali * ha = adapter block pointer.
19878ae6d9c7SGiridhar Malavali *
19888ae6d9c7SGiridhar Malavali * Returns:
19898ae6d9c7SGiridhar Malavali * 0 = success
19908ae6d9c7SGiridhar Malavali */
19918ae6d9c7SGiridhar Malavali int
qlafx00_initialize_adapter(scsi_qla_host_t * vha)19928ae6d9c7SGiridhar Malavali qlafx00_initialize_adapter(scsi_qla_host_t *vha)
19938ae6d9c7SGiridhar Malavali {
19948ae6d9c7SGiridhar Malavali int rval;
19958ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
199671e56003SArmen Baloyan uint32_t tempc;
19978ae6d9c7SGiridhar Malavali
19988ae6d9c7SGiridhar Malavali /* Clear adapter flags. */
19998ae6d9c7SGiridhar Malavali vha->flags.online = 0;
20008ae6d9c7SGiridhar Malavali ha->flags.chip_reset_done = 0;
20018ae6d9c7SGiridhar Malavali vha->flags.reset_active = 0;
20028ae6d9c7SGiridhar Malavali ha->flags.pci_channel_io_perm_failure = 0;
20038ae6d9c7SGiridhar Malavali ha->flags.eeh_busy = 0;
20048ae6d9c7SGiridhar Malavali atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
20058ae6d9c7SGiridhar Malavali atomic_set(&vha->loop_state, LOOP_DOWN);
20068ae6d9c7SGiridhar Malavali vha->device_flags = DFLG_NO_CABLE;
20078ae6d9c7SGiridhar Malavali vha->dpc_flags = 0;
20088ae6d9c7SGiridhar Malavali vha->flags.management_server_logged_in = 0;
20098ae6d9c7SGiridhar Malavali ha->isp_abort_cnt = 0;
20108ae6d9c7SGiridhar Malavali ha->beacon_blink_led = 0;
20118ae6d9c7SGiridhar Malavali
20128ae6d9c7SGiridhar Malavali set_bit(0, ha->req_qid_map);
20138ae6d9c7SGiridhar Malavali set_bit(0, ha->rsp_qid_map);
20148ae6d9c7SGiridhar Malavali
20158ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_init, vha, 0x0147,
20168ae6d9c7SGiridhar Malavali "Configuring PCI space...\n");
20178ae6d9c7SGiridhar Malavali
20188ae6d9c7SGiridhar Malavali rval = ha->isp_ops->pci_config(vha);
20198ae6d9c7SGiridhar Malavali if (rval) {
20208ae6d9c7SGiridhar Malavali ql_log(ql_log_warn, vha, 0x0148,
20218ae6d9c7SGiridhar Malavali "Unable to configure PCI space.\n");
20228ae6d9c7SGiridhar Malavali return rval;
20238ae6d9c7SGiridhar Malavali }
20248ae6d9c7SGiridhar Malavali
20258ae6d9c7SGiridhar Malavali rval = qlafx00_init_fw_ready(vha);
20268ae6d9c7SGiridhar Malavali if (rval != QLA_SUCCESS)
20278ae6d9c7SGiridhar Malavali return rval;
20288ae6d9c7SGiridhar Malavali
20298ae6d9c7SGiridhar Malavali qlafx00_save_queue_ptrs(vha);
20308ae6d9c7SGiridhar Malavali
20318ae6d9c7SGiridhar Malavali rval = qlafx00_config_queues(vha);
20328ae6d9c7SGiridhar Malavali if (rval != QLA_SUCCESS)
20338ae6d9c7SGiridhar Malavali return rval;
20348ae6d9c7SGiridhar Malavali
20358ae6d9c7SGiridhar Malavali /*
20368ae6d9c7SGiridhar Malavali * Allocate the array of outstanding commands
20378ae6d9c7SGiridhar Malavali * now that we know the firmware resources.
20388ae6d9c7SGiridhar Malavali */
20398ae6d9c7SGiridhar Malavali rval = qla2x00_alloc_outstanding_cmds(ha, vha->req);
20408ae6d9c7SGiridhar Malavali if (rval != QLA_SUCCESS)
20418ae6d9c7SGiridhar Malavali return rval;
20428ae6d9c7SGiridhar Malavali
20438ae6d9c7SGiridhar Malavali rval = qla2x00_init_rings(vha);
20448ae6d9c7SGiridhar Malavali ha->flags.chip_reset_done = 1;
20458ae6d9c7SGiridhar Malavali
204671e56003SArmen Baloyan tempc = QLAFX00_GET_TEMPERATURE(ha);
204771e56003SArmen Baloyan ql_dbg(ql_dbg_init, vha, 0x0152,
204871e56003SArmen Baloyan "ISPFx00(%s): Critical temp timer, current SOC temperature: 0x%x\n",
204971e56003SArmen Baloyan __func__, tempc);
205071e56003SArmen Baloyan
20518ae6d9c7SGiridhar Malavali return rval;
20528ae6d9c7SGiridhar Malavali }
20538ae6d9c7SGiridhar Malavali
20548ae6d9c7SGiridhar Malavali uint32_t
qlafx00_fw_state_show(struct device * dev,struct device_attribute * attr,char * buf)20558ae6d9c7SGiridhar Malavali qlafx00_fw_state_show(struct device *dev, struct device_attribute *attr,
20568ae6d9c7SGiridhar Malavali char *buf)
20578ae6d9c7SGiridhar Malavali {
20588ae6d9c7SGiridhar Malavali scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
20598ae6d9c7SGiridhar Malavali int rval = QLA_FUNCTION_FAILED;
20608ae6d9c7SGiridhar Malavali uint32_t state[1];
20618ae6d9c7SGiridhar Malavali
20628ae6d9c7SGiridhar Malavali if (qla2x00_reset_active(vha))
20638ae6d9c7SGiridhar Malavali ql_log(ql_log_warn, vha, 0x70ce,
20648ae6d9c7SGiridhar Malavali "ISP reset active.\n");
20658ae6d9c7SGiridhar Malavali else if (!vha->hw->flags.eeh_busy) {
20668ae6d9c7SGiridhar Malavali rval = qlafx00_get_firmware_state(vha, state);
20678ae6d9c7SGiridhar Malavali }
20688ae6d9c7SGiridhar Malavali if (rval != QLA_SUCCESS)
20698ae6d9c7SGiridhar Malavali memset(state, -1, sizeof(state));
20708ae6d9c7SGiridhar Malavali
20718ae6d9c7SGiridhar Malavali return state[0];
20728ae6d9c7SGiridhar Malavali }
20738ae6d9c7SGiridhar Malavali
20748ae6d9c7SGiridhar Malavali void
qlafx00_get_host_speed(struct Scsi_Host * shost)20758ae6d9c7SGiridhar Malavali qlafx00_get_host_speed(struct Scsi_Host *shost)
20768ae6d9c7SGiridhar Malavali {
20778ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = ((struct scsi_qla_host *)
20788ae6d9c7SGiridhar Malavali (shost_priv(shost)))->hw;
20798ae6d9c7SGiridhar Malavali u32 speed = FC_PORTSPEED_UNKNOWN;
20808ae6d9c7SGiridhar Malavali
20818ae6d9c7SGiridhar Malavali switch (ha->link_data_rate) {
20828ae6d9c7SGiridhar Malavali case QLAFX00_PORT_SPEED_2G:
20838ae6d9c7SGiridhar Malavali speed = FC_PORTSPEED_2GBIT;
20848ae6d9c7SGiridhar Malavali break;
20858ae6d9c7SGiridhar Malavali case QLAFX00_PORT_SPEED_4G:
20868ae6d9c7SGiridhar Malavali speed = FC_PORTSPEED_4GBIT;
20878ae6d9c7SGiridhar Malavali break;
20888ae6d9c7SGiridhar Malavali case QLAFX00_PORT_SPEED_8G:
20898ae6d9c7SGiridhar Malavali speed = FC_PORTSPEED_8GBIT;
20908ae6d9c7SGiridhar Malavali break;
20918ae6d9c7SGiridhar Malavali case QLAFX00_PORT_SPEED_10G:
20928ae6d9c7SGiridhar Malavali speed = FC_PORTSPEED_10GBIT;
20938ae6d9c7SGiridhar Malavali break;
20948ae6d9c7SGiridhar Malavali }
20958ae6d9c7SGiridhar Malavali fc_host_speed(shost) = speed;
20968ae6d9c7SGiridhar Malavali }
20978ae6d9c7SGiridhar Malavali
20988ae6d9c7SGiridhar Malavali /** QLAFX00 specific ISR implementation functions */
20998ae6d9c7SGiridhar Malavali
21008ae6d9c7SGiridhar Malavali static inline void
qlafx00_handle_sense(srb_t * sp,uint8_t * sense_data,uint32_t par_sense_len,uint32_t sense_len,struct rsp_que * rsp,int res)21018ae6d9c7SGiridhar Malavali qlafx00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len,
21028ae6d9c7SGiridhar Malavali uint32_t sense_len, struct rsp_que *rsp, int res)
21038ae6d9c7SGiridhar Malavali {
210425ff6af1SJoe Carnuccio struct scsi_qla_host *vha = sp->vha;
21058ae6d9c7SGiridhar Malavali struct scsi_cmnd *cp = GET_CMD_SP(sp);
21068ae6d9c7SGiridhar Malavali uint32_t track_sense_len;
21078ae6d9c7SGiridhar Malavali
21088ae6d9c7SGiridhar Malavali SET_FW_SENSE_LEN(sp, sense_len);
21098ae6d9c7SGiridhar Malavali
21108ae6d9c7SGiridhar Malavali if (sense_len >= SCSI_SENSE_BUFFERSIZE)
21118ae6d9c7SGiridhar Malavali sense_len = SCSI_SENSE_BUFFERSIZE;
21128ae6d9c7SGiridhar Malavali
21138ae6d9c7SGiridhar Malavali SET_CMD_SENSE_LEN(sp, sense_len);
21148ae6d9c7SGiridhar Malavali SET_CMD_SENSE_PTR(sp, cp->sense_buffer);
21158ae6d9c7SGiridhar Malavali track_sense_len = sense_len;
21168ae6d9c7SGiridhar Malavali
21178ae6d9c7SGiridhar Malavali if (sense_len > par_sense_len)
21188ae6d9c7SGiridhar Malavali sense_len = par_sense_len;
21198ae6d9c7SGiridhar Malavali
21208ae6d9c7SGiridhar Malavali memcpy(cp->sense_buffer, sense_data, sense_len);
21218ae6d9c7SGiridhar Malavali
21228ae6d9c7SGiridhar Malavali SET_FW_SENSE_LEN(sp, GET_FW_SENSE_LEN(sp) - sense_len);
21238ae6d9c7SGiridhar Malavali
21248ae6d9c7SGiridhar Malavali SET_CMD_SENSE_PTR(sp, cp->sense_buffer + sense_len);
21258ae6d9c7SGiridhar Malavali track_sense_len -= sense_len;
21268ae6d9c7SGiridhar Malavali SET_CMD_SENSE_LEN(sp, track_sense_len);
21278ae6d9c7SGiridhar Malavali
21288ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, vha, 0x304d,
21298ae6d9c7SGiridhar Malavali "sense_len=0x%x par_sense_len=0x%x track_sense_len=0x%x.\n",
21308ae6d9c7SGiridhar Malavali sense_len, par_sense_len, track_sense_len);
21318ae6d9c7SGiridhar Malavali if (GET_FW_SENSE_LEN(sp) > 0) {
21328ae6d9c7SGiridhar Malavali rsp->status_srb = sp;
21338ae6d9c7SGiridhar Malavali cp->result = res;
21348ae6d9c7SGiridhar Malavali }
21358ae6d9c7SGiridhar Malavali
21368ae6d9c7SGiridhar Malavali if (sense_len) {
21378ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3039,
21389cb78c16SHannes Reinecke "Check condition Sense data, nexus%ld:%d:%llu cmd=%p.\n",
213925ff6af1SJoe Carnuccio sp->vha->host_no, cp->device->id, cp->device->lun,
21408ae6d9c7SGiridhar Malavali cp);
21418ae6d9c7SGiridhar Malavali ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x3049,
21428ae6d9c7SGiridhar Malavali cp->sense_buffer, sense_len);
21438ae6d9c7SGiridhar Malavali }
21448ae6d9c7SGiridhar Malavali }
21458ae6d9c7SGiridhar Malavali
21468ae6d9c7SGiridhar Malavali static void
qlafx00_tm_iocb_entry(scsi_qla_host_t * vha,struct req_que * req,struct tsk_mgmt_entry_fx00 * pkt,srb_t * sp,__le16 sstatus,__le16 cpstatus)21478ae6d9c7SGiridhar Malavali qlafx00_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
21488ae6d9c7SGiridhar Malavali struct tsk_mgmt_entry_fx00 *pkt, srb_t *sp,
21491f8deefeSSaurav Kashyap __le16 sstatus, __le16 cpstatus)
21508ae6d9c7SGiridhar Malavali {
21518ae6d9c7SGiridhar Malavali struct srb_iocb *tmf;
21528ae6d9c7SGiridhar Malavali
21538ae6d9c7SGiridhar Malavali tmf = &sp->u.iocb_cmd;
21541f8deefeSSaurav Kashyap if (cpstatus != cpu_to_le16((uint16_t)CS_COMPLETE) ||
21551f8deefeSSaurav Kashyap (sstatus & cpu_to_le16((uint16_t)SS_RESPONSE_INFO_LEN_VALID)))
21561f8deefeSSaurav Kashyap cpstatus = cpu_to_le16((uint16_t)CS_INCOMPLETE);
21578ae6d9c7SGiridhar Malavali tmf->u.tmf.comp_status = cpstatus;
215825ff6af1SJoe Carnuccio sp->done(sp, 0);
21598ae6d9c7SGiridhar Malavali }
21608ae6d9c7SGiridhar Malavali
21618ae6d9c7SGiridhar Malavali static void
qlafx00_abort_iocb_entry(scsi_qla_host_t * vha,struct req_que * req,struct abort_iocb_entry_fx00 * pkt)21628ae6d9c7SGiridhar Malavali qlafx00_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
21638ae6d9c7SGiridhar Malavali struct abort_iocb_entry_fx00 *pkt)
21648ae6d9c7SGiridhar Malavali {
21658ae6d9c7SGiridhar Malavali const char func[] = "ABT_IOCB";
21668ae6d9c7SGiridhar Malavali srb_t *sp;
21678ae6d9c7SGiridhar Malavali struct srb_iocb *abt;
21688ae6d9c7SGiridhar Malavali
21698ae6d9c7SGiridhar Malavali sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
21708ae6d9c7SGiridhar Malavali if (!sp)
21718ae6d9c7SGiridhar Malavali return;
21728ae6d9c7SGiridhar Malavali
21738ae6d9c7SGiridhar Malavali abt = &sp->u.iocb_cmd;
21741f8deefeSSaurav Kashyap abt->u.abt.comp_status = pkt->tgt_id_sts;
217525ff6af1SJoe Carnuccio sp->done(sp, 0);
21768ae6d9c7SGiridhar Malavali }
21778ae6d9c7SGiridhar Malavali
21788ae6d9c7SGiridhar Malavali static void
qlafx00_ioctl_iosb_entry(scsi_qla_host_t * vha,struct req_que * req,struct ioctl_iocb_entry_fx00 * pkt)21798ae6d9c7SGiridhar Malavali qlafx00_ioctl_iosb_entry(scsi_qla_host_t *vha, struct req_que *req,
21808ae6d9c7SGiridhar Malavali struct ioctl_iocb_entry_fx00 *pkt)
21818ae6d9c7SGiridhar Malavali {
21828ae6d9c7SGiridhar Malavali const char func[] = "IOSB_IOCB";
21838ae6d9c7SGiridhar Malavali srb_t *sp;
218475cc8cfcSJohannes Thumshirn struct bsg_job *bsg_job;
218501e0e15cSJohannes Thumshirn struct fc_bsg_reply *bsg_reply;
21868ae6d9c7SGiridhar Malavali struct srb_iocb *iocb_job;
21875b0af477SBart Van Assche int res = 0;
21888ae6d9c7SGiridhar Malavali struct qla_mt_iocb_rsp_fx00 fstatus;
21898ae6d9c7SGiridhar Malavali uint8_t *fw_sts_ptr;
21908ae6d9c7SGiridhar Malavali
21918ae6d9c7SGiridhar Malavali sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
21928ae6d9c7SGiridhar Malavali if (!sp)
21938ae6d9c7SGiridhar Malavali return;
21948ae6d9c7SGiridhar Malavali
21958ae6d9c7SGiridhar Malavali if (sp->type == SRB_FXIOCB_DCMD) {
21968ae6d9c7SGiridhar Malavali iocb_job = &sp->u.iocb_cmd;
21971f8deefeSSaurav Kashyap iocb_job->u.fxiocb.seq_number = pkt->seq_no;
21981f8deefeSSaurav Kashyap iocb_job->u.fxiocb.fw_flags = pkt->fw_iotcl_flags;
21991f8deefeSSaurav Kashyap iocb_job->u.fxiocb.result = pkt->status;
22008ae6d9c7SGiridhar Malavali if (iocb_job->u.fxiocb.flags & SRB_FXDISC_RSP_DWRD_VALID)
22018ae6d9c7SGiridhar Malavali iocb_job->u.fxiocb.req_data =
22021f8deefeSSaurav Kashyap pkt->dataword_r;
22038ae6d9c7SGiridhar Malavali } else {
22048ae6d9c7SGiridhar Malavali bsg_job = sp->u.bsg_job;
220501e0e15cSJohannes Thumshirn bsg_reply = bsg_job->reply;
22068ae6d9c7SGiridhar Malavali
22078ae6d9c7SGiridhar Malavali memset(&fstatus, 0, sizeof(struct qla_mt_iocb_rsp_fx00));
22088ae6d9c7SGiridhar Malavali
22098ae6d9c7SGiridhar Malavali fstatus.reserved_1 = pkt->reserved_0;
22108ae6d9c7SGiridhar Malavali fstatus.func_type = pkt->comp_func_num;
22118ae6d9c7SGiridhar Malavali fstatus.ioctl_flags = pkt->fw_iotcl_flags;
22128ae6d9c7SGiridhar Malavali fstatus.ioctl_data = pkt->dataword_r;
22138ae6d9c7SGiridhar Malavali fstatus.adapid = pkt->adapid;
2214d68b3e01SArmen Baloyan fstatus.reserved_2 = pkt->dataword_r_extra;
22158ae6d9c7SGiridhar Malavali fstatus.res_count = pkt->residuallen;
22168ae6d9c7SGiridhar Malavali fstatus.status = pkt->status;
22178ae6d9c7SGiridhar Malavali fstatus.seq_number = pkt->seq_no;
22188ae6d9c7SGiridhar Malavali memcpy(fstatus.reserved_3,
22198ae6d9c7SGiridhar Malavali pkt->reserved_2, 20 * sizeof(uint8_t));
22208ae6d9c7SGiridhar Malavali
222105231a3bSChristoph Hellwig fw_sts_ptr = bsg_job->reply + sizeof(struct fc_bsg_reply);
22228ae6d9c7SGiridhar Malavali
2223f8f97b0cSJoe Carnuccio memcpy(fw_sts_ptr, &fstatus, sizeof(fstatus));
22248ae6d9c7SGiridhar Malavali bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
22258ae6d9c7SGiridhar Malavali sizeof(struct qla_mt_iocb_rsp_fx00) + sizeof(uint8_t);
22268ae6d9c7SGiridhar Malavali
22278ae6d9c7SGiridhar Malavali ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
2228f8f97b0cSJoe Carnuccio sp->vha, 0x5080, pkt, sizeof(*pkt));
22298ae6d9c7SGiridhar Malavali
22308ae6d9c7SGiridhar Malavali ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
2231f8f97b0cSJoe Carnuccio sp->vha, 0x5074,
2232f8f97b0cSJoe Carnuccio fw_sts_ptr, sizeof(fstatus));
22338ae6d9c7SGiridhar Malavali
223401e0e15cSJohannes Thumshirn res = bsg_reply->result = DID_OK << 16;
223501e0e15cSJohannes Thumshirn bsg_reply->reply_payload_rcv_len =
22368ae6d9c7SGiridhar Malavali bsg_job->reply_payload.payload_len;
22378ae6d9c7SGiridhar Malavali }
223825ff6af1SJoe Carnuccio sp->done(sp, res);
22398ae6d9c7SGiridhar Malavali }
22408ae6d9c7SGiridhar Malavali
22418ae6d9c7SGiridhar Malavali /**
22428ae6d9c7SGiridhar Malavali * qlafx00_status_entry() - Process a Status IOCB entry.
22432db6228dSBart Van Assche * @vha: SCSI driver HA context
22442db6228dSBart Van Assche * @rsp: response queue
22458ae6d9c7SGiridhar Malavali * @pkt: Entry pointer
22468ae6d9c7SGiridhar Malavali */
22478ae6d9c7SGiridhar Malavali static void
qlafx00_status_entry(scsi_qla_host_t * vha,struct rsp_que * rsp,void * pkt)22488ae6d9c7SGiridhar Malavali qlafx00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
22498ae6d9c7SGiridhar Malavali {
22508ae6d9c7SGiridhar Malavali srb_t *sp;
22518ae6d9c7SGiridhar Malavali fc_port_t *fcport;
22528ae6d9c7SGiridhar Malavali struct scsi_cmnd *cp;
22538ae6d9c7SGiridhar Malavali struct sts_entry_fx00 *sts;
22541f8deefeSSaurav Kashyap __le16 comp_status;
22551f8deefeSSaurav Kashyap __le16 scsi_status;
22561f8deefeSSaurav Kashyap __le16 lscsi_status;
22578ae6d9c7SGiridhar Malavali int32_t resid;
22588ae6d9c7SGiridhar Malavali uint32_t sense_len, par_sense_len, rsp_info_len, resid_len,
22598ae6d9c7SGiridhar Malavali fw_resid_len;
22608ae6d9c7SGiridhar Malavali uint8_t *rsp_info = NULL, *sense_data = NULL;
22618ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
22628ae6d9c7SGiridhar Malavali uint32_t hindex, handle;
22638ae6d9c7SGiridhar Malavali uint16_t que;
22648ae6d9c7SGiridhar Malavali struct req_que *req;
22658ae6d9c7SGiridhar Malavali int logit = 1;
22668ae6d9c7SGiridhar Malavali int res = 0;
22678ae6d9c7SGiridhar Malavali
22688ae6d9c7SGiridhar Malavali sts = (struct sts_entry_fx00 *) pkt;
22698ae6d9c7SGiridhar Malavali
22701f8deefeSSaurav Kashyap comp_status = sts->comp_status;
22711f8deefeSSaurav Kashyap scsi_status = sts->scsi_status & cpu_to_le16((uint16_t)SS_MASK);
22728ae6d9c7SGiridhar Malavali hindex = sts->handle;
22738ae6d9c7SGiridhar Malavali handle = LSW(hindex);
22748ae6d9c7SGiridhar Malavali
22758ae6d9c7SGiridhar Malavali que = MSW(hindex);
22768ae6d9c7SGiridhar Malavali req = ha->req_q_map[que];
22778ae6d9c7SGiridhar Malavali
22788ae6d9c7SGiridhar Malavali /* Validate handle. */
22798ae6d9c7SGiridhar Malavali if (handle < req->num_outstanding_cmds)
22808ae6d9c7SGiridhar Malavali sp = req->outstanding_cmds[handle];
22818ae6d9c7SGiridhar Malavali else
22828ae6d9c7SGiridhar Malavali sp = NULL;
22838ae6d9c7SGiridhar Malavali
22848ae6d9c7SGiridhar Malavali if (sp == NULL) {
22858ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, vha, 0x3034,
22868ae6d9c7SGiridhar Malavali "Invalid status handle (0x%x).\n", handle);
22878ae6d9c7SGiridhar Malavali
22888ae6d9c7SGiridhar Malavali set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
22898ae6d9c7SGiridhar Malavali qla2xxx_wake_dpc(vha);
22908ae6d9c7SGiridhar Malavali return;
22918ae6d9c7SGiridhar Malavali }
22928ae6d9c7SGiridhar Malavali
22938ae6d9c7SGiridhar Malavali if (sp->type == SRB_TM_CMD) {
22948ae6d9c7SGiridhar Malavali req->outstanding_cmds[handle] = NULL;
22958ae6d9c7SGiridhar Malavali qlafx00_tm_iocb_entry(vha, req, pkt, sp,
22968ae6d9c7SGiridhar Malavali scsi_status, comp_status);
22978ae6d9c7SGiridhar Malavali return;
22988ae6d9c7SGiridhar Malavali }
22998ae6d9c7SGiridhar Malavali
23008ae6d9c7SGiridhar Malavali /* Fast path completion. */
23018ae6d9c7SGiridhar Malavali if (comp_status == CS_COMPLETE && scsi_status == 0) {
23028ae6d9c7SGiridhar Malavali qla2x00_process_completed_request(vha, req, handle);
23038ae6d9c7SGiridhar Malavali return;
23048ae6d9c7SGiridhar Malavali }
23058ae6d9c7SGiridhar Malavali
23068ae6d9c7SGiridhar Malavali req->outstanding_cmds[handle] = NULL;
23078ae6d9c7SGiridhar Malavali cp = GET_CMD_SP(sp);
23088ae6d9c7SGiridhar Malavali if (cp == NULL) {
23098ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, vha, 0x3048,
23108ae6d9c7SGiridhar Malavali "Command already returned (0x%x/%p).\n",
23118ae6d9c7SGiridhar Malavali handle, sp);
23128ae6d9c7SGiridhar Malavali
23138ae6d9c7SGiridhar Malavali return;
23148ae6d9c7SGiridhar Malavali }
23158ae6d9c7SGiridhar Malavali
23161f8deefeSSaurav Kashyap lscsi_status = scsi_status & cpu_to_le16((uint16_t)STATUS_MASK);
23178ae6d9c7SGiridhar Malavali
23188ae6d9c7SGiridhar Malavali fcport = sp->fcport;
23198ae6d9c7SGiridhar Malavali
23208ae6d9c7SGiridhar Malavali sense_len = par_sense_len = rsp_info_len = resid_len =
23218ae6d9c7SGiridhar Malavali fw_resid_len = 0;
23221f8deefeSSaurav Kashyap if (scsi_status & cpu_to_le16((uint16_t)SS_SENSE_LEN_VALID))
23231f8deefeSSaurav Kashyap sense_len = sts->sense_len;
23241f8deefeSSaurav Kashyap if (scsi_status & cpu_to_le16(((uint16_t)SS_RESIDUAL_UNDER
23251f8deefeSSaurav Kashyap | (uint16_t)SS_RESIDUAL_OVER)))
23268ae6d9c7SGiridhar Malavali resid_len = le32_to_cpu(sts->residual_len);
23271f8deefeSSaurav Kashyap if (comp_status == cpu_to_le16((uint16_t)CS_DATA_UNDERRUN))
23288ae6d9c7SGiridhar Malavali fw_resid_len = le32_to_cpu(sts->residual_len);
23298ae6d9c7SGiridhar Malavali rsp_info = sense_data = sts->data;
23308ae6d9c7SGiridhar Malavali par_sense_len = sizeof(sts->data);
23318ae6d9c7SGiridhar Malavali
23328ae6d9c7SGiridhar Malavali /* Check for overrun. */
23338ae6d9c7SGiridhar Malavali if (comp_status == CS_COMPLETE &&
23341f8deefeSSaurav Kashyap scsi_status & cpu_to_le16((uint16_t)SS_RESIDUAL_OVER))
23351f8deefeSSaurav Kashyap comp_status = cpu_to_le16((uint16_t)CS_DATA_OVERRUN);
23368ae6d9c7SGiridhar Malavali
23378ae6d9c7SGiridhar Malavali /*
23388ae6d9c7SGiridhar Malavali * Based on Host and scsi status generate status code for Linux
23398ae6d9c7SGiridhar Malavali */
23401f8deefeSSaurav Kashyap switch (le16_to_cpu(comp_status)) {
23418ae6d9c7SGiridhar Malavali case CS_COMPLETE:
23428ae6d9c7SGiridhar Malavali case CS_QUEUE_FULL:
23438ae6d9c7SGiridhar Malavali if (scsi_status == 0) {
23448ae6d9c7SGiridhar Malavali res = DID_OK << 16;
23458ae6d9c7SGiridhar Malavali break;
23468ae6d9c7SGiridhar Malavali }
23471f8deefeSSaurav Kashyap if (scsi_status & cpu_to_le16(((uint16_t)SS_RESIDUAL_UNDER
23481f8deefeSSaurav Kashyap | (uint16_t)SS_RESIDUAL_OVER))) {
23498ae6d9c7SGiridhar Malavali resid = resid_len;
23508ae6d9c7SGiridhar Malavali scsi_set_resid(cp, resid);
23518ae6d9c7SGiridhar Malavali
23528ae6d9c7SGiridhar Malavali if (!lscsi_status &&
23538ae6d9c7SGiridhar Malavali ((unsigned)(scsi_bufflen(cp) - resid) <
23548ae6d9c7SGiridhar Malavali cp->underflow)) {
23558ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, fcport->vha, 0x3050,
23568ae6d9c7SGiridhar Malavali "Mid-layer underflow "
23578ae6d9c7SGiridhar Malavali "detected (0x%x of 0x%x bytes).\n",
23588ae6d9c7SGiridhar Malavali resid, scsi_bufflen(cp));
23598ae6d9c7SGiridhar Malavali
23608ae6d9c7SGiridhar Malavali res = DID_ERROR << 16;
23618ae6d9c7SGiridhar Malavali break;
23628ae6d9c7SGiridhar Malavali }
23638ae6d9c7SGiridhar Malavali }
23641f8deefeSSaurav Kashyap res = DID_OK << 16 | le16_to_cpu(lscsi_status);
23658ae6d9c7SGiridhar Malavali
23661f8deefeSSaurav Kashyap if (lscsi_status ==
23671f8deefeSSaurav Kashyap cpu_to_le16((uint16_t)SAM_STAT_TASK_SET_FULL)) {
23688ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, fcport->vha, 0x3051,
23698ae6d9c7SGiridhar Malavali "QUEUE FULL detected.\n");
23708ae6d9c7SGiridhar Malavali break;
23718ae6d9c7SGiridhar Malavali }
23728ae6d9c7SGiridhar Malavali logit = 0;
23731f8deefeSSaurav Kashyap if (lscsi_status != cpu_to_le16((uint16_t)SS_CHECK_CONDITION))
23748ae6d9c7SGiridhar Malavali break;
23758ae6d9c7SGiridhar Malavali
23768ae6d9c7SGiridhar Malavali memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
23771f8deefeSSaurav Kashyap if (!(scsi_status & cpu_to_le16((uint16_t)SS_SENSE_LEN_VALID)))
23788ae6d9c7SGiridhar Malavali break;
23798ae6d9c7SGiridhar Malavali
23808ae6d9c7SGiridhar Malavali qlafx00_handle_sense(sp, sense_data, par_sense_len, sense_len,
23818ae6d9c7SGiridhar Malavali rsp, res);
23828ae6d9c7SGiridhar Malavali break;
23838ae6d9c7SGiridhar Malavali
23848ae6d9c7SGiridhar Malavali case CS_DATA_UNDERRUN:
23858ae6d9c7SGiridhar Malavali /* Use F/W calculated residual length. */
23868ae6d9c7SGiridhar Malavali if (IS_FWI2_CAPABLE(ha) || IS_QLAFX00(ha))
23878ae6d9c7SGiridhar Malavali resid = fw_resid_len;
23888ae6d9c7SGiridhar Malavali else
23898ae6d9c7SGiridhar Malavali resid = resid_len;
23908ae6d9c7SGiridhar Malavali scsi_set_resid(cp, resid);
23911f8deefeSSaurav Kashyap if (scsi_status & cpu_to_le16((uint16_t)SS_RESIDUAL_UNDER)) {
23928ae6d9c7SGiridhar Malavali if ((IS_FWI2_CAPABLE(ha) || IS_QLAFX00(ha))
23938ae6d9c7SGiridhar Malavali && fw_resid_len != resid_len) {
23948ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, fcport->vha, 0x3052,
23958ae6d9c7SGiridhar Malavali "Dropped frame(s) detected "
23968ae6d9c7SGiridhar Malavali "(0x%x of 0x%x bytes).\n",
23978ae6d9c7SGiridhar Malavali resid, scsi_bufflen(cp));
23988ae6d9c7SGiridhar Malavali
23991f8deefeSSaurav Kashyap res = DID_ERROR << 16 |
24001f8deefeSSaurav Kashyap le16_to_cpu(lscsi_status);
24018ae6d9c7SGiridhar Malavali goto check_scsi_status;
24028ae6d9c7SGiridhar Malavali }
24038ae6d9c7SGiridhar Malavali
24048ae6d9c7SGiridhar Malavali if (!lscsi_status &&
24058ae6d9c7SGiridhar Malavali ((unsigned)(scsi_bufflen(cp) - resid) <
24068ae6d9c7SGiridhar Malavali cp->underflow)) {
24078ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, fcport->vha, 0x3053,
24088ae6d9c7SGiridhar Malavali "Mid-layer underflow "
24098ae6d9c7SGiridhar Malavali "detected (0x%x of 0x%x bytes, "
24108ae6d9c7SGiridhar Malavali "cp->underflow: 0x%x).\n",
24118ae6d9c7SGiridhar Malavali resid, scsi_bufflen(cp), cp->underflow);
24128ae6d9c7SGiridhar Malavali
24138ae6d9c7SGiridhar Malavali res = DID_ERROR << 16;
24148ae6d9c7SGiridhar Malavali break;
24158ae6d9c7SGiridhar Malavali }
24161f8deefeSSaurav Kashyap } else if (lscsi_status !=
24171f8deefeSSaurav Kashyap cpu_to_le16((uint16_t)SAM_STAT_TASK_SET_FULL) &&
24181f8deefeSSaurav Kashyap lscsi_status != cpu_to_le16((uint16_t)SAM_STAT_BUSY)) {
24198ae6d9c7SGiridhar Malavali /*
24208ae6d9c7SGiridhar Malavali * scsi status of task set and busy are considered
24218ae6d9c7SGiridhar Malavali * to be task not completed.
24228ae6d9c7SGiridhar Malavali */
24238ae6d9c7SGiridhar Malavali
24248ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, fcport->vha, 0x3054,
24258ae6d9c7SGiridhar Malavali "Dropped frame(s) detected (0x%x "
24268ae6d9c7SGiridhar Malavali "of 0x%x bytes).\n", resid,
24278ae6d9c7SGiridhar Malavali scsi_bufflen(cp));
24288ae6d9c7SGiridhar Malavali
24291f8deefeSSaurav Kashyap res = DID_ERROR << 16 | le16_to_cpu(lscsi_status);
24308ae6d9c7SGiridhar Malavali goto check_scsi_status;
24318ae6d9c7SGiridhar Malavali } else {
24328ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, fcport->vha, 0x3055,
24338ae6d9c7SGiridhar Malavali "scsi_status: 0x%x, lscsi_status: 0x%x\n",
24348ae6d9c7SGiridhar Malavali scsi_status, lscsi_status);
24358ae6d9c7SGiridhar Malavali }
24368ae6d9c7SGiridhar Malavali
24371f8deefeSSaurav Kashyap res = DID_OK << 16 | le16_to_cpu(lscsi_status);
24388ae6d9c7SGiridhar Malavali logit = 0;
24398ae6d9c7SGiridhar Malavali
24408ae6d9c7SGiridhar Malavali check_scsi_status:
24418ae6d9c7SGiridhar Malavali /*
24428ae6d9c7SGiridhar Malavali * Check to see if SCSI Status is non zero. If so report SCSI
24438ae6d9c7SGiridhar Malavali * Status.
24448ae6d9c7SGiridhar Malavali */
24458ae6d9c7SGiridhar Malavali if (lscsi_status != 0) {
24461f8deefeSSaurav Kashyap if (lscsi_status ==
24471f8deefeSSaurav Kashyap cpu_to_le16((uint16_t)SAM_STAT_TASK_SET_FULL)) {
24488ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, fcport->vha, 0x3056,
24498ae6d9c7SGiridhar Malavali "QUEUE FULL detected.\n");
24508ae6d9c7SGiridhar Malavali logit = 1;
24518ae6d9c7SGiridhar Malavali break;
24528ae6d9c7SGiridhar Malavali }
24531f8deefeSSaurav Kashyap if (lscsi_status !=
24541f8deefeSSaurav Kashyap cpu_to_le16((uint16_t)SS_CHECK_CONDITION))
24558ae6d9c7SGiridhar Malavali break;
24568ae6d9c7SGiridhar Malavali
24578ae6d9c7SGiridhar Malavali memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
24581f8deefeSSaurav Kashyap if (!(scsi_status &
24591f8deefeSSaurav Kashyap cpu_to_le16((uint16_t)SS_SENSE_LEN_VALID)))
24608ae6d9c7SGiridhar Malavali break;
24618ae6d9c7SGiridhar Malavali
24628ae6d9c7SGiridhar Malavali qlafx00_handle_sense(sp, sense_data, par_sense_len,
24638ae6d9c7SGiridhar Malavali sense_len, rsp, res);
24648ae6d9c7SGiridhar Malavali }
24658ae6d9c7SGiridhar Malavali break;
24668ae6d9c7SGiridhar Malavali
24678ae6d9c7SGiridhar Malavali case CS_PORT_LOGGED_OUT:
24688ae6d9c7SGiridhar Malavali case CS_PORT_CONFIG_CHG:
24698ae6d9c7SGiridhar Malavali case CS_PORT_BUSY:
24708ae6d9c7SGiridhar Malavali case CS_INCOMPLETE:
24718ae6d9c7SGiridhar Malavali case CS_PORT_UNAVAILABLE:
24728ae6d9c7SGiridhar Malavali case CS_TIMEOUT:
24738ae6d9c7SGiridhar Malavali case CS_RESET:
24748ae6d9c7SGiridhar Malavali
24758ae6d9c7SGiridhar Malavali /*
24768ae6d9c7SGiridhar Malavali * We are going to have the fc class block the rport
24778ae6d9c7SGiridhar Malavali * while we try to recover so instruct the mid layer
24788ae6d9c7SGiridhar Malavali * to requeue until the class decides how to handle this.
24798ae6d9c7SGiridhar Malavali */
24808ae6d9c7SGiridhar Malavali res = DID_TRANSPORT_DISRUPTED << 16;
24818ae6d9c7SGiridhar Malavali
24828ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, fcport->vha, 0x3057,
24838ae6d9c7SGiridhar Malavali "Port down status: port-state=0x%x.\n",
24848ae6d9c7SGiridhar Malavali atomic_read(&fcport->state));
24858ae6d9c7SGiridhar Malavali
24868ae6d9c7SGiridhar Malavali if (atomic_read(&fcport->state) == FCS_ONLINE)
24873c75ad1dSHimanshu Madhani qla2x00_mark_device_lost(fcport->vha, fcport, 1);
24888ae6d9c7SGiridhar Malavali break;
24898ae6d9c7SGiridhar Malavali
24908ae6d9c7SGiridhar Malavali case CS_ABORTED:
24918ae6d9c7SGiridhar Malavali res = DID_RESET << 16;
24928ae6d9c7SGiridhar Malavali break;
24938ae6d9c7SGiridhar Malavali
24948ae6d9c7SGiridhar Malavali default:
24958ae6d9c7SGiridhar Malavali res = DID_ERROR << 16;
24968ae6d9c7SGiridhar Malavali break;
24978ae6d9c7SGiridhar Malavali }
24988ae6d9c7SGiridhar Malavali
24998ae6d9c7SGiridhar Malavali if (logit)
25008ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, fcport->vha, 0x3058,
25019cb78c16SHannes Reinecke "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu "
25027b833558SOleksandr Khoshaba "tgt_id: 0x%x lscsi_status: 0x%x cdb=%10phN len=0x%x "
2503c3ff356dSBart Van Assche "rsp_info=%p resid=0x%x fw_resid=0x%x sense_len=0x%x, "
25047b833558SOleksandr Khoshaba "par_sense_len=0x%x, rsp_info_len=0x%x\n",
25058ae6d9c7SGiridhar Malavali comp_status, scsi_status, res, vha->host_no,
25068ae6d9c7SGiridhar Malavali cp->device->id, cp->device->lun, fcport->tgt_id,
25077b833558SOleksandr Khoshaba lscsi_status, cp->cmnd, scsi_bufflen(cp),
2508c3ff356dSBart Van Assche rsp_info, resid_len, fw_resid_len, sense_len,
25098ae6d9c7SGiridhar Malavali par_sense_len, rsp_info_len);
25108ae6d9c7SGiridhar Malavali
25118ae6d9c7SGiridhar Malavali if (rsp->status_srb == NULL)
251225ff6af1SJoe Carnuccio sp->done(sp, res);
251388263208SBart Van Assche else
251488263208SBart Van Assche WARN_ON_ONCE(true);
25158ae6d9c7SGiridhar Malavali }
25168ae6d9c7SGiridhar Malavali
25178ae6d9c7SGiridhar Malavali /**
25188ae6d9c7SGiridhar Malavali * qlafx00_status_cont_entry() - Process a Status Continuations entry.
25192db6228dSBart Van Assche * @rsp: response queue
25208ae6d9c7SGiridhar Malavali * @pkt: Entry pointer
25218ae6d9c7SGiridhar Malavali *
25228ae6d9c7SGiridhar Malavali * Extended sense data.
25238ae6d9c7SGiridhar Malavali */
25248ae6d9c7SGiridhar Malavali static void
qlafx00_status_cont_entry(struct rsp_que * rsp,sts_cont_entry_t * pkt)25258ae6d9c7SGiridhar Malavali qlafx00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt)
25268ae6d9c7SGiridhar Malavali {
25278ae6d9c7SGiridhar Malavali uint8_t sense_sz = 0;
25288ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = rsp->hw;
25298ae6d9c7SGiridhar Malavali struct scsi_qla_host *vha = pci_get_drvdata(ha->pdev);
25308ae6d9c7SGiridhar Malavali srb_t *sp = rsp->status_srb;
25318ae6d9c7SGiridhar Malavali struct scsi_cmnd *cp;
25328ae6d9c7SGiridhar Malavali uint32_t sense_len;
25338ae6d9c7SGiridhar Malavali uint8_t *sense_ptr;
25348ae6d9c7SGiridhar Malavali
25358ae6d9c7SGiridhar Malavali if (!sp) {
25368ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, vha, 0x3037,
25378ae6d9c7SGiridhar Malavali "no SP, sp = %p\n", sp);
25388ae6d9c7SGiridhar Malavali return;
25398ae6d9c7SGiridhar Malavali }
25408ae6d9c7SGiridhar Malavali
25418ae6d9c7SGiridhar Malavali if (!GET_FW_SENSE_LEN(sp)) {
25428ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, vha, 0x304b,
25438ae6d9c7SGiridhar Malavali "no fw sense data, sp = %p\n", sp);
25448ae6d9c7SGiridhar Malavali return;
25458ae6d9c7SGiridhar Malavali }
25468ae6d9c7SGiridhar Malavali cp = GET_CMD_SP(sp);
25478ae6d9c7SGiridhar Malavali if (cp == NULL) {
25488ae6d9c7SGiridhar Malavali ql_log(ql_log_warn, vha, 0x303b,
25498ae6d9c7SGiridhar Malavali "cmd is NULL: already returned to OS (sp=%p).\n", sp);
25508ae6d9c7SGiridhar Malavali
25518ae6d9c7SGiridhar Malavali rsp->status_srb = NULL;
25528ae6d9c7SGiridhar Malavali return;
25538ae6d9c7SGiridhar Malavali }
25548ae6d9c7SGiridhar Malavali
25558ae6d9c7SGiridhar Malavali if (!GET_CMD_SENSE_LEN(sp)) {
25568ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, vha, 0x304c,
25578ae6d9c7SGiridhar Malavali "no sense data, sp = %p\n", sp);
25588ae6d9c7SGiridhar Malavali } else {
25598ae6d9c7SGiridhar Malavali sense_len = GET_CMD_SENSE_LEN(sp);
25608ae6d9c7SGiridhar Malavali sense_ptr = GET_CMD_SENSE_PTR(sp);
25618ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, vha, 0x304f,
25628ae6d9c7SGiridhar Malavali "sp=%p sense_len=0x%x sense_ptr=%p.\n",
25638ae6d9c7SGiridhar Malavali sp, sense_len, sense_ptr);
25648ae6d9c7SGiridhar Malavali
25658ae6d9c7SGiridhar Malavali if (sense_len > sizeof(pkt->data))
25668ae6d9c7SGiridhar Malavali sense_sz = sizeof(pkt->data);
25678ae6d9c7SGiridhar Malavali else
25688ae6d9c7SGiridhar Malavali sense_sz = sense_len;
25698ae6d9c7SGiridhar Malavali
25708ae6d9c7SGiridhar Malavali /* Move sense data. */
25718ae6d9c7SGiridhar Malavali ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x304e,
2572f8f97b0cSJoe Carnuccio pkt, sizeof(*pkt));
25738ae6d9c7SGiridhar Malavali memcpy(sense_ptr, pkt->data, sense_sz);
25748ae6d9c7SGiridhar Malavali ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x304a,
25758ae6d9c7SGiridhar Malavali sense_ptr, sense_sz);
25768ae6d9c7SGiridhar Malavali
25778ae6d9c7SGiridhar Malavali sense_len -= sense_sz;
25788ae6d9c7SGiridhar Malavali sense_ptr += sense_sz;
25798ae6d9c7SGiridhar Malavali
25808ae6d9c7SGiridhar Malavali SET_CMD_SENSE_PTR(sp, sense_ptr);
25818ae6d9c7SGiridhar Malavali SET_CMD_SENSE_LEN(sp, sense_len);
25828ae6d9c7SGiridhar Malavali }
25838ae6d9c7SGiridhar Malavali sense_len = GET_FW_SENSE_LEN(sp);
25848ae6d9c7SGiridhar Malavali sense_len = (sense_len > sizeof(pkt->data)) ?
25858ae6d9c7SGiridhar Malavali (sense_len - sizeof(pkt->data)) : 0;
25868ae6d9c7SGiridhar Malavali SET_FW_SENSE_LEN(sp, sense_len);
25878ae6d9c7SGiridhar Malavali
25888ae6d9c7SGiridhar Malavali /* Place command on done queue. */
25898ae6d9c7SGiridhar Malavali if (sense_len == 0) {
25908ae6d9c7SGiridhar Malavali rsp->status_srb = NULL;
259125ff6af1SJoe Carnuccio sp->done(sp, cp->result);
259288263208SBart Van Assche } else {
259388263208SBart Van Assche WARN_ON_ONCE(true);
25948ae6d9c7SGiridhar Malavali }
25958ae6d9c7SGiridhar Malavali }
25968ae6d9c7SGiridhar Malavali
25978ae6d9c7SGiridhar Malavali /**
25988ae6d9c7SGiridhar Malavali * qlafx00_multistatus_entry() - Process Multi response queue entries.
25992db6228dSBart Van Assche * @vha: SCSI driver HA context
26002db6228dSBart Van Assche * @rsp: response queue
2601807eb907SBart Van Assche * @pkt: received packet
26028ae6d9c7SGiridhar Malavali */
26038ae6d9c7SGiridhar Malavali static void
qlafx00_multistatus_entry(struct scsi_qla_host * vha,struct rsp_que * rsp,void * pkt)26048ae6d9c7SGiridhar Malavali qlafx00_multistatus_entry(struct scsi_qla_host *vha,
26058ae6d9c7SGiridhar Malavali struct rsp_que *rsp, void *pkt)
26068ae6d9c7SGiridhar Malavali {
26078ae6d9c7SGiridhar Malavali srb_t *sp;
26088ae6d9c7SGiridhar Malavali struct multi_sts_entry_fx00 *stsmfx;
26098ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
26108ae6d9c7SGiridhar Malavali uint32_t handle, hindex, handle_count, i;
26118ae6d9c7SGiridhar Malavali uint16_t que;
26128ae6d9c7SGiridhar Malavali struct req_que *req;
26131f8deefeSSaurav Kashyap __le32 *handle_ptr;
26148ae6d9c7SGiridhar Malavali
26158ae6d9c7SGiridhar Malavali stsmfx = (struct multi_sts_entry_fx00 *) pkt;
26168ae6d9c7SGiridhar Malavali
26178ae6d9c7SGiridhar Malavali handle_count = stsmfx->handle_count;
26188ae6d9c7SGiridhar Malavali
26198ae6d9c7SGiridhar Malavali if (handle_count > MAX_HANDLE_COUNT) {
26208ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, vha, 0x3035,
26218ae6d9c7SGiridhar Malavali "Invalid handle count (0x%x).\n", handle_count);
26228ae6d9c7SGiridhar Malavali set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
26238ae6d9c7SGiridhar Malavali qla2xxx_wake_dpc(vha);
26248ae6d9c7SGiridhar Malavali return;
26258ae6d9c7SGiridhar Malavali }
26268ae6d9c7SGiridhar Malavali
26271f8deefeSSaurav Kashyap handle_ptr = &stsmfx->handles[0];
26288ae6d9c7SGiridhar Malavali
26298ae6d9c7SGiridhar Malavali for (i = 0; i < handle_count; i++) {
26308ae6d9c7SGiridhar Malavali hindex = le32_to_cpu(*handle_ptr);
26318ae6d9c7SGiridhar Malavali handle = LSW(hindex);
26328ae6d9c7SGiridhar Malavali que = MSW(hindex);
26338ae6d9c7SGiridhar Malavali req = ha->req_q_map[que];
26348ae6d9c7SGiridhar Malavali
26358ae6d9c7SGiridhar Malavali /* Validate handle. */
26368ae6d9c7SGiridhar Malavali if (handle < req->num_outstanding_cmds)
26378ae6d9c7SGiridhar Malavali sp = req->outstanding_cmds[handle];
26388ae6d9c7SGiridhar Malavali else
26398ae6d9c7SGiridhar Malavali sp = NULL;
26408ae6d9c7SGiridhar Malavali
26418ae6d9c7SGiridhar Malavali if (sp == NULL) {
26428ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_io, vha, 0x3044,
26438ae6d9c7SGiridhar Malavali "Invalid status handle (0x%x).\n", handle);
26448ae6d9c7SGiridhar Malavali set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
26458ae6d9c7SGiridhar Malavali qla2xxx_wake_dpc(vha);
26468ae6d9c7SGiridhar Malavali return;
26478ae6d9c7SGiridhar Malavali }
26488ae6d9c7SGiridhar Malavali qla2x00_process_completed_request(vha, req, handle);
26498ae6d9c7SGiridhar Malavali handle_ptr++;
26508ae6d9c7SGiridhar Malavali }
26518ae6d9c7SGiridhar Malavali }
26528ae6d9c7SGiridhar Malavali
26538ae6d9c7SGiridhar Malavali /**
26548ae6d9c7SGiridhar Malavali * qlafx00_error_entry() - Process an error entry.
26552db6228dSBart Van Assche * @vha: SCSI driver HA context
26562db6228dSBart Van Assche * @rsp: response queue
26578ae6d9c7SGiridhar Malavali * @pkt: Entry pointer
26588ae6d9c7SGiridhar Malavali */
26598ae6d9c7SGiridhar Malavali static void
qlafx00_error_entry(scsi_qla_host_t * vha,struct rsp_que * rsp,struct sts_entry_fx00 * pkt)26608ae6d9c7SGiridhar Malavali qlafx00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp,
26612c309aeeSBart Van Assche struct sts_entry_fx00 *pkt)
26628ae6d9c7SGiridhar Malavali {
26638ae6d9c7SGiridhar Malavali srb_t *sp;
26648ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
26658ae6d9c7SGiridhar Malavali const char func[] = "ERROR-IOCB";
2666d550dd27SSaurav Kashyap uint16_t que = 0;
26678ae6d9c7SGiridhar Malavali struct req_que *req = NULL;
26688ae6d9c7SGiridhar Malavali int res = DID_ERROR << 16;
26698ae6d9c7SGiridhar Malavali
26708ae6d9c7SGiridhar Malavali req = ha->req_q_map[que];
26718ae6d9c7SGiridhar Malavali
26728ae6d9c7SGiridhar Malavali sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
26738ae6d9c7SGiridhar Malavali if (sp) {
267425ff6af1SJoe Carnuccio sp->done(sp, res);
26758ae6d9c7SGiridhar Malavali return;
26768ae6d9c7SGiridhar Malavali }
26778ae6d9c7SGiridhar Malavali
26788ae6d9c7SGiridhar Malavali set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
26798ae6d9c7SGiridhar Malavali qla2xxx_wake_dpc(vha);
26808ae6d9c7SGiridhar Malavali }
26818ae6d9c7SGiridhar Malavali
26828ae6d9c7SGiridhar Malavali /**
26838ae6d9c7SGiridhar Malavali * qlafx00_process_response_queue() - Process response queue entries.
26842db6228dSBart Van Assche * @vha: SCSI driver HA context
26852db6228dSBart Van Assche * @rsp: response queue
26868ae6d9c7SGiridhar Malavali */
26878ae6d9c7SGiridhar Malavali static void
qlafx00_process_response_queue(struct scsi_qla_host * vha,struct rsp_que * rsp)26888ae6d9c7SGiridhar Malavali qlafx00_process_response_queue(struct scsi_qla_host *vha,
26898ae6d9c7SGiridhar Malavali struct rsp_que *rsp)
26908ae6d9c7SGiridhar Malavali {
26918ae6d9c7SGiridhar Malavali struct sts_entry_fx00 *pkt;
26928ae6d9c7SGiridhar Malavali response_t *lptr;
26936ac1f3b5SSaurav Kashyap uint16_t lreq_q_in = 0;
26946ac1f3b5SSaurav Kashyap uint16_t lreq_q_out = 0;
26958ae6d9c7SGiridhar Malavali
269604474d3aSBart Van Assche lreq_q_in = rd_reg_dword(rsp->rsp_q_in);
26979929c478SArmen Baloyan lreq_q_out = rsp->ring_index;
26986ac1f3b5SSaurav Kashyap
26996ac1f3b5SSaurav Kashyap while (lreq_q_in != lreq_q_out) {
27008ae6d9c7SGiridhar Malavali lptr = rsp->ring_ptr;
27011f8deefeSSaurav Kashyap memcpy_fromio(rsp->rsp_pkt, (void __iomem *)lptr,
27021f8deefeSSaurav Kashyap sizeof(rsp->rsp_pkt));
27038ae6d9c7SGiridhar Malavali pkt = (struct sts_entry_fx00 *)rsp->rsp_pkt;
27048ae6d9c7SGiridhar Malavali
27058ae6d9c7SGiridhar Malavali rsp->ring_index++;
27066ac1f3b5SSaurav Kashyap lreq_q_out++;
27078ae6d9c7SGiridhar Malavali if (rsp->ring_index == rsp->length) {
27086ac1f3b5SSaurav Kashyap lreq_q_out = 0;
27098ae6d9c7SGiridhar Malavali rsp->ring_index = 0;
27108ae6d9c7SGiridhar Malavali rsp->ring_ptr = rsp->ring;
27118ae6d9c7SGiridhar Malavali } else {
27128ae6d9c7SGiridhar Malavali rsp->ring_ptr++;
27138ae6d9c7SGiridhar Malavali }
27148ae6d9c7SGiridhar Malavali
27158ae6d9c7SGiridhar Malavali if (pkt->entry_status != 0 &&
27168ae6d9c7SGiridhar Malavali pkt->entry_type != IOCTL_IOSB_TYPE_FX00) {
27172c309aeeSBart Van Assche ql_dbg(ql_dbg_async, vha, 0x507f,
27182c309aeeSBart Van Assche "type of error status in response: 0x%x\n",
27192c309aeeSBart Van Assche pkt->entry_status);
27208ae6d9c7SGiridhar Malavali qlafx00_error_entry(vha, rsp,
27212c309aeeSBart Van Assche (struct sts_entry_fx00 *)pkt);
27228ae6d9c7SGiridhar Malavali continue;
27238ae6d9c7SGiridhar Malavali }
27248ae6d9c7SGiridhar Malavali
27258ae6d9c7SGiridhar Malavali switch (pkt->entry_type) {
27268ae6d9c7SGiridhar Malavali case STATUS_TYPE_FX00:
27278ae6d9c7SGiridhar Malavali qlafx00_status_entry(vha, rsp, pkt);
27288ae6d9c7SGiridhar Malavali break;
27298ae6d9c7SGiridhar Malavali
27308ae6d9c7SGiridhar Malavali case STATUS_CONT_TYPE_FX00:
27318ae6d9c7SGiridhar Malavali qlafx00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt);
27328ae6d9c7SGiridhar Malavali break;
27338ae6d9c7SGiridhar Malavali
27348ae6d9c7SGiridhar Malavali case MULTI_STATUS_TYPE_FX00:
27358ae6d9c7SGiridhar Malavali qlafx00_multistatus_entry(vha, rsp, pkt);
27368ae6d9c7SGiridhar Malavali break;
27378ae6d9c7SGiridhar Malavali
27388ae6d9c7SGiridhar Malavali case ABORT_IOCB_TYPE_FX00:
27398ae6d9c7SGiridhar Malavali qlafx00_abort_iocb_entry(vha, rsp->req,
27408ae6d9c7SGiridhar Malavali (struct abort_iocb_entry_fx00 *)pkt);
27418ae6d9c7SGiridhar Malavali break;
27428ae6d9c7SGiridhar Malavali
27438ae6d9c7SGiridhar Malavali case IOCTL_IOSB_TYPE_FX00:
27448ae6d9c7SGiridhar Malavali qlafx00_ioctl_iosb_entry(vha, rsp->req,
27458ae6d9c7SGiridhar Malavali (struct ioctl_iocb_entry_fx00 *)pkt);
27468ae6d9c7SGiridhar Malavali break;
27478ae6d9c7SGiridhar Malavali default:
27488ae6d9c7SGiridhar Malavali /* Type Not Supported. */
27498ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_async, vha, 0x5081,
27508ae6d9c7SGiridhar Malavali "Received unknown response pkt type %x "
27518ae6d9c7SGiridhar Malavali "entry status=%x.\n",
27528ae6d9c7SGiridhar Malavali pkt->entry_type, pkt->entry_status);
27538ae6d9c7SGiridhar Malavali break;
27548ae6d9c7SGiridhar Malavali }
27558ae6d9c7SGiridhar Malavali }
27568ae6d9c7SGiridhar Malavali
27578ae6d9c7SGiridhar Malavali /* Adjust ring index */
275804474d3aSBart Van Assche wrt_reg_dword(rsp->rsp_q_out, rsp->ring_index);
27598ae6d9c7SGiridhar Malavali }
27608ae6d9c7SGiridhar Malavali
27618ae6d9c7SGiridhar Malavali /**
27628ae6d9c7SGiridhar Malavali * qlafx00_async_event() - Process aynchronous events.
27632db6228dSBart Van Assche * @vha: SCSI driver HA context
27648ae6d9c7SGiridhar Malavali */
27658ae6d9c7SGiridhar Malavali static void
qlafx00_async_event(scsi_qla_host_t * vha)27668ae6d9c7SGiridhar Malavali qlafx00_async_event(scsi_qla_host_t *vha)
27678ae6d9c7SGiridhar Malavali {
27688ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
27698ae6d9c7SGiridhar Malavali struct device_reg_fx00 __iomem *reg;
27708ae6d9c7SGiridhar Malavali int data_size = 1;
27718ae6d9c7SGiridhar Malavali
27728ae6d9c7SGiridhar Malavali reg = &ha->iobase->ispfx00;
27738ae6d9c7SGiridhar Malavali /* Setup to process RIO completion. */
27748ae6d9c7SGiridhar Malavali switch (ha->aenmb[0]) {
27758ae6d9c7SGiridhar Malavali case QLAFX00_MBA_SYSTEM_ERR: /* System Error */
27768ae6d9c7SGiridhar Malavali ql_log(ql_log_warn, vha, 0x5079,
27778ae6d9c7SGiridhar Malavali "ISP System Error - mbx1=%x\n", ha->aenmb[0]);
27788ae6d9c7SGiridhar Malavali set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
27798ae6d9c7SGiridhar Malavali break;
27808ae6d9c7SGiridhar Malavali
27818ae6d9c7SGiridhar Malavali case QLAFX00_MBA_SHUTDOWN_RQSTD: /* Shutdown requested */
27828ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_async, vha, 0x5076,
27838ae6d9c7SGiridhar Malavali "Asynchronous FW shutdown requested.\n");
27848ae6d9c7SGiridhar Malavali set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
27858ae6d9c7SGiridhar Malavali qla2xxx_wake_dpc(vha);
27868ae6d9c7SGiridhar Malavali break;
27878ae6d9c7SGiridhar Malavali
27888ae6d9c7SGiridhar Malavali case QLAFX00_MBA_PORT_UPDATE: /* Port database update */
278904474d3aSBart Van Assche ha->aenmb[1] = rd_reg_dword(®->aenmailbox1);
279004474d3aSBart Van Assche ha->aenmb[2] = rd_reg_dword(®->aenmailbox2);
279104474d3aSBart Van Assche ha->aenmb[3] = rd_reg_dword(®->aenmailbox3);
27928ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_async, vha, 0x5077,
27938ae6d9c7SGiridhar Malavali "Asynchronous port Update received "
27948ae6d9c7SGiridhar Malavali "aenmb[0]: %x, aenmb[1]: %x, aenmb[2]: %x, aenmb[3]: %x\n",
27958ae6d9c7SGiridhar Malavali ha->aenmb[0], ha->aenmb[1], ha->aenmb[2], ha->aenmb[3]);
27968ae6d9c7SGiridhar Malavali data_size = 4;
27978ae6d9c7SGiridhar Malavali break;
279871e56003SArmen Baloyan
279971e56003SArmen Baloyan case QLAFX00_MBA_TEMP_OVER: /* Over temperature event */
28004881d095SArmen Baloyan ql_log(ql_log_info, vha, 0x5085,
28014881d095SArmen Baloyan "Asynchronous over temperature event received "
28024881d095SArmen Baloyan "aenmb[0]: %x\n",
28034881d095SArmen Baloyan ha->aenmb[0]);
28044881d095SArmen Baloyan break;
28054881d095SArmen Baloyan
28064881d095SArmen Baloyan case QLAFX00_MBA_TEMP_NORM: /* Normal temperature event */
28074881d095SArmen Baloyan ql_log(ql_log_info, vha, 0x5086,
28084881d095SArmen Baloyan "Asynchronous normal temperature event received "
28094881d095SArmen Baloyan "aenmb[0]: %x\n",
28104881d095SArmen Baloyan ha->aenmb[0]);
28114881d095SArmen Baloyan break;
28124881d095SArmen Baloyan
281371e56003SArmen Baloyan case QLAFX00_MBA_TEMP_CRIT: /* Critical temperature event */
281471e56003SArmen Baloyan ql_log(ql_log_info, vha, 0x5083,
281571e56003SArmen Baloyan "Asynchronous critical temperature event received "
281671e56003SArmen Baloyan "aenmb[0]: %x\n",
281771e56003SArmen Baloyan ha->aenmb[0]);
281871e56003SArmen Baloyan break;
281971e56003SArmen Baloyan
28208ae6d9c7SGiridhar Malavali default:
282104474d3aSBart Van Assche ha->aenmb[1] = rd_reg_dword(®->aenmailbox1);
282204474d3aSBart Van Assche ha->aenmb[2] = rd_reg_dword(®->aenmailbox2);
282304474d3aSBart Van Assche ha->aenmb[3] = rd_reg_dword(®->aenmailbox3);
282404474d3aSBart Van Assche ha->aenmb[4] = rd_reg_dword(®->aenmailbox4);
282504474d3aSBart Van Assche ha->aenmb[5] = rd_reg_dword(®->aenmailbox5);
282604474d3aSBart Van Assche ha->aenmb[6] = rd_reg_dword(®->aenmailbox6);
282704474d3aSBart Van Assche ha->aenmb[7] = rd_reg_dword(®->aenmailbox7);
28288ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_async, vha, 0x5078,
28298ae6d9c7SGiridhar Malavali "AEN:%04x %04x %04x %04x :%04x %04x %04x %04x\n",
28308ae6d9c7SGiridhar Malavali ha->aenmb[0], ha->aenmb[1], ha->aenmb[2], ha->aenmb[3],
28318ae6d9c7SGiridhar Malavali ha->aenmb[4], ha->aenmb[5], ha->aenmb[6], ha->aenmb[7]);
28328ae6d9c7SGiridhar Malavali break;
28338ae6d9c7SGiridhar Malavali }
28348ae6d9c7SGiridhar Malavali qlafx00_post_aenfx_work(vha, ha->aenmb[0],
28358ae6d9c7SGiridhar Malavali (uint32_t *)ha->aenmb, data_size);
28368ae6d9c7SGiridhar Malavali }
28378ae6d9c7SGiridhar Malavali
28388ae6d9c7SGiridhar Malavali /**
283938109566SLee Jones * qlafx00_mbx_completion() - Process mailbox command completions.
28402db6228dSBart Van Assche * @vha: SCSI driver HA context
2841807eb907SBart Van Assche * @mb0: value to be written into mailbox register 0
28428ae6d9c7SGiridhar Malavali */
28438ae6d9c7SGiridhar Malavali static void
qlafx00_mbx_completion(scsi_qla_host_t * vha,uint32_t mb0)28448ae6d9c7SGiridhar Malavali qlafx00_mbx_completion(scsi_qla_host_t *vha, uint32_t mb0)
28458ae6d9c7SGiridhar Malavali {
28468ae6d9c7SGiridhar Malavali uint16_t cnt;
284737139da1SBart Van Assche __le32 __iomem *wptr;
28488ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
28498ae6d9c7SGiridhar Malavali struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00;
28508ae6d9c7SGiridhar Malavali
28518ae6d9c7SGiridhar Malavali if (!ha->mcp32)
28528ae6d9c7SGiridhar Malavali ql_dbg(ql_dbg_async, vha, 0x507e, "MBX pointer ERROR.\n");
28538ae6d9c7SGiridhar Malavali
28548ae6d9c7SGiridhar Malavali /* Load return mailbox registers. */
28558ae6d9c7SGiridhar Malavali ha->flags.mbox_int = 1;
28568ae6d9c7SGiridhar Malavali ha->mailbox_out32[0] = mb0;
285737139da1SBart Van Assche wptr = ®->mailbox17;
28588ae6d9c7SGiridhar Malavali
28598ae6d9c7SGiridhar Malavali for (cnt = 1; cnt < ha->mbx_count; cnt++) {
286004474d3aSBart Van Assche ha->mailbox_out32[cnt] = rd_reg_dword(wptr);
28618ae6d9c7SGiridhar Malavali wptr++;
28628ae6d9c7SGiridhar Malavali }
28638ae6d9c7SGiridhar Malavali }
28648ae6d9c7SGiridhar Malavali
28658ae6d9c7SGiridhar Malavali /**
28668ae6d9c7SGiridhar Malavali * qlafx00_intr_handler() - Process interrupts for the ISPFX00.
2867807eb907SBart Van Assche * @irq: interrupt number
28688ae6d9c7SGiridhar Malavali * @dev_id: SCSI driver HA context
28698ae6d9c7SGiridhar Malavali *
28708ae6d9c7SGiridhar Malavali * Called by system whenever the host adapter generates an interrupt.
28718ae6d9c7SGiridhar Malavali *
28728ae6d9c7SGiridhar Malavali * Returns handled flag.
28738ae6d9c7SGiridhar Malavali */
28748ae6d9c7SGiridhar Malavali irqreturn_t
qlafx00_intr_handler(int irq,void * dev_id)28758ae6d9c7SGiridhar Malavali qlafx00_intr_handler(int irq, void *dev_id)
28768ae6d9c7SGiridhar Malavali {
28778ae6d9c7SGiridhar Malavali scsi_qla_host_t *vha;
28788ae6d9c7SGiridhar Malavali struct qla_hw_data *ha;
28798ae6d9c7SGiridhar Malavali struct device_reg_fx00 __iomem *reg;
28808ae6d9c7SGiridhar Malavali int status;
28818ae6d9c7SGiridhar Malavali unsigned long iter;
28828ae6d9c7SGiridhar Malavali uint32_t stat;
28838ae6d9c7SGiridhar Malavali uint32_t mb[8];
28848ae6d9c7SGiridhar Malavali struct rsp_que *rsp;
28858ae6d9c7SGiridhar Malavali unsigned long flags;
28868ae6d9c7SGiridhar Malavali uint32_t clr_intr = 0;
2887fbe9c54bSSaurav Kashyap uint32_t intr_stat = 0;
28888ae6d9c7SGiridhar Malavali
28898ae6d9c7SGiridhar Malavali rsp = (struct rsp_que *) dev_id;
28908ae6d9c7SGiridhar Malavali if (!rsp) {
28918ae6d9c7SGiridhar Malavali ql_log(ql_log_info, NULL, 0x507d,
28928ae6d9c7SGiridhar Malavali "%s: NULL response queue pointer.\n", __func__);
28938ae6d9c7SGiridhar Malavali return IRQ_NONE;
28948ae6d9c7SGiridhar Malavali }
28958ae6d9c7SGiridhar Malavali
28968ae6d9c7SGiridhar Malavali ha = rsp->hw;
28978ae6d9c7SGiridhar Malavali reg = &ha->iobase->ispfx00;
28988ae6d9c7SGiridhar Malavali status = 0;
28998ae6d9c7SGiridhar Malavali
29008ae6d9c7SGiridhar Malavali if (unlikely(pci_channel_offline(ha->pdev)))
29018ae6d9c7SGiridhar Malavali return IRQ_HANDLED;
29028ae6d9c7SGiridhar Malavali
29038ae6d9c7SGiridhar Malavali spin_lock_irqsave(&ha->hardware_lock, flags);
29048ae6d9c7SGiridhar Malavali vha = pci_get_drvdata(ha->pdev);
29058ae6d9c7SGiridhar Malavali for (iter = 50; iter--; clr_intr = 0) {
29068ae6d9c7SGiridhar Malavali stat = QLAFX00_RD_INTR_REG(ha);
2907c821e0d5SJoe Lawrence if (qla2x00_check_reg32_for_disconnect(vha, stat))
2908f3ddac19SChad Dupuis break;
2909fbe9c54bSSaurav Kashyap intr_stat = stat & QLAFX00_HST_INT_STS_BITS;
2910fbe9c54bSSaurav Kashyap if (!intr_stat)
29118ae6d9c7SGiridhar Malavali break;
29128ae6d9c7SGiridhar Malavali
2913fbe9c54bSSaurav Kashyap if (stat & QLAFX00_INTR_MB_CMPLT) {
291404474d3aSBart Van Assche mb[0] = rd_reg_dword(®->mailbox16);
29158ae6d9c7SGiridhar Malavali qlafx00_mbx_completion(vha, mb[0]);
29168ae6d9c7SGiridhar Malavali status |= MBX_INTERRUPT;
29178ae6d9c7SGiridhar Malavali clr_intr |= QLAFX00_INTR_MB_CMPLT;
2918fbe9c54bSSaurav Kashyap }
2919fbe9c54bSSaurav Kashyap if (intr_stat & QLAFX00_INTR_ASYNC_CMPLT) {
292004474d3aSBart Van Assche ha->aenmb[0] = rd_reg_dword(®->aenmailbox0);
29218ae6d9c7SGiridhar Malavali qlafx00_async_event(vha);
29228ae6d9c7SGiridhar Malavali clr_intr |= QLAFX00_INTR_ASYNC_CMPLT;
2923fbe9c54bSSaurav Kashyap }
2924fbe9c54bSSaurav Kashyap if (intr_stat & QLAFX00_INTR_RSP_CMPLT) {
29258ae6d9c7SGiridhar Malavali qlafx00_process_response_queue(vha, rsp);
29268ae6d9c7SGiridhar Malavali clr_intr |= QLAFX00_INTR_RSP_CMPLT;
29278ae6d9c7SGiridhar Malavali }
2928fbe9c54bSSaurav Kashyap
29298ae6d9c7SGiridhar Malavali QLAFX00_CLR_INTR_REG(ha, clr_intr);
29308ae6d9c7SGiridhar Malavali QLAFX00_RD_INTR_REG(ha);
29318ae6d9c7SGiridhar Malavali }
293236439832Sgurinder.shergill@hp.com
293336439832Sgurinder.shergill@hp.com qla2x00_handle_mbx_completion(ha, status);
29348ae6d9c7SGiridhar Malavali spin_unlock_irqrestore(&ha->hardware_lock, flags);
29358ae6d9c7SGiridhar Malavali
29368ae6d9c7SGiridhar Malavali return IRQ_HANDLED;
29378ae6d9c7SGiridhar Malavali }
29388ae6d9c7SGiridhar Malavali
29398ae6d9c7SGiridhar Malavali /** QLAFX00 specific IOCB implementation functions */
29408ae6d9c7SGiridhar Malavali
29418ae6d9c7SGiridhar Malavali static inline cont_a64_entry_t *
qlafx00_prep_cont_type1_iocb(struct req_que * req,cont_a64_entry_t * lcont_pkt)29428ae6d9c7SGiridhar Malavali qlafx00_prep_cont_type1_iocb(struct req_que *req,
29438ae6d9c7SGiridhar Malavali cont_a64_entry_t *lcont_pkt)
29448ae6d9c7SGiridhar Malavali {
29458ae6d9c7SGiridhar Malavali cont_a64_entry_t *cont_pkt;
29468ae6d9c7SGiridhar Malavali
29478ae6d9c7SGiridhar Malavali /* Adjust ring index. */
29488ae6d9c7SGiridhar Malavali req->ring_index++;
29498ae6d9c7SGiridhar Malavali if (req->ring_index == req->length) {
29508ae6d9c7SGiridhar Malavali req->ring_index = 0;
29518ae6d9c7SGiridhar Malavali req->ring_ptr = req->ring;
29528ae6d9c7SGiridhar Malavali } else {
29538ae6d9c7SGiridhar Malavali req->ring_ptr++;
29548ae6d9c7SGiridhar Malavali }
29558ae6d9c7SGiridhar Malavali
29568ae6d9c7SGiridhar Malavali cont_pkt = (cont_a64_entry_t *)req->ring_ptr;
29578ae6d9c7SGiridhar Malavali
29588ae6d9c7SGiridhar Malavali /* Load packet defaults. */
29591f8deefeSSaurav Kashyap lcont_pkt->entry_type = CONTINUE_A64_TYPE_FX00;
29608ae6d9c7SGiridhar Malavali
29618ae6d9c7SGiridhar Malavali return cont_pkt;
29628ae6d9c7SGiridhar Malavali }
29638ae6d9c7SGiridhar Malavali
29648ae6d9c7SGiridhar Malavali static inline void
qlafx00_build_scsi_iocbs(srb_t * sp,struct cmd_type_7_fx00 * cmd_pkt,uint16_t tot_dsds,struct cmd_type_7_fx00 * lcmd_pkt)29658ae6d9c7SGiridhar Malavali qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt,
29668ae6d9c7SGiridhar Malavali uint16_t tot_dsds, struct cmd_type_7_fx00 *lcmd_pkt)
29678ae6d9c7SGiridhar Malavali {
29688ae6d9c7SGiridhar Malavali uint16_t avail_dsds;
296915b7a68cSBart Van Assche struct dsd64 *cur_dsd;
29708ae6d9c7SGiridhar Malavali scsi_qla_host_t *vha;
29718ae6d9c7SGiridhar Malavali struct scsi_cmnd *cmd;
29728ae6d9c7SGiridhar Malavali struct scatterlist *sg;
29738ae6d9c7SGiridhar Malavali int i, cont;
29748ae6d9c7SGiridhar Malavali struct req_que *req;
29758ae6d9c7SGiridhar Malavali cont_a64_entry_t lcont_pkt;
29768ae6d9c7SGiridhar Malavali cont_a64_entry_t *cont_pkt;
29778ae6d9c7SGiridhar Malavali
297825ff6af1SJoe Carnuccio vha = sp->vha;
29798ae6d9c7SGiridhar Malavali req = vha->req;
29808ae6d9c7SGiridhar Malavali
29818ae6d9c7SGiridhar Malavali cmd = GET_CMD_SP(sp);
29828ae6d9c7SGiridhar Malavali cont = 0;
29838ae6d9c7SGiridhar Malavali cont_pkt = NULL;
29848ae6d9c7SGiridhar Malavali
29858ae6d9c7SGiridhar Malavali /* Update entry type to indicate Command Type 3 IOCB */
29861f8deefeSSaurav Kashyap lcmd_pkt->entry_type = FX00_COMMAND_TYPE_7;
29878ae6d9c7SGiridhar Malavali
29888ae6d9c7SGiridhar Malavali /* No data transfer */
29898ae6d9c7SGiridhar Malavali if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
2990ad950360SBart Van Assche lcmd_pkt->byte_count = cpu_to_le32(0);
29918ae6d9c7SGiridhar Malavali return;
29928ae6d9c7SGiridhar Malavali }
29938ae6d9c7SGiridhar Malavali
29948ae6d9c7SGiridhar Malavali /* Set transfer direction */
29958ae6d9c7SGiridhar Malavali if (cmd->sc_data_direction == DMA_TO_DEVICE) {
2996378c538dSArmen Baloyan lcmd_pkt->cntrl_flags = TMF_WRITE_DATA;
29978ae6d9c7SGiridhar Malavali vha->qla_stats.output_bytes += scsi_bufflen(cmd);
29988ae6d9c7SGiridhar Malavali } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
2999378c538dSArmen Baloyan lcmd_pkt->cntrl_flags = TMF_READ_DATA;
30008ae6d9c7SGiridhar Malavali vha->qla_stats.input_bytes += scsi_bufflen(cmd);
30018ae6d9c7SGiridhar Malavali }
30028ae6d9c7SGiridhar Malavali
30038ae6d9c7SGiridhar Malavali /* One DSD is available in the Command Type 3 IOCB */
30048ae6d9c7SGiridhar Malavali avail_dsds = 1;
300515b7a68cSBart Van Assche cur_dsd = &lcmd_pkt->dsd;
30068ae6d9c7SGiridhar Malavali
30078ae6d9c7SGiridhar Malavali /* Load data segments */
30088ae6d9c7SGiridhar Malavali scsi_for_each_sg(cmd, sg, tot_dsds, i) {
30098ae6d9c7SGiridhar Malavali /* Allocate additional continuation packets? */
30108ae6d9c7SGiridhar Malavali if (avail_dsds == 0) {
30118ae6d9c7SGiridhar Malavali /*
30128ae6d9c7SGiridhar Malavali * Five DSDs are available in the Continuation
30138ae6d9c7SGiridhar Malavali * Type 1 IOCB.
30148ae6d9c7SGiridhar Malavali */
30158ae6d9c7SGiridhar Malavali memset(&lcont_pkt, 0, REQUEST_ENTRY_SIZE);
30168ae6d9c7SGiridhar Malavali cont_pkt =
30178ae6d9c7SGiridhar Malavali qlafx00_prep_cont_type1_iocb(req, &lcont_pkt);
301815b7a68cSBart Van Assche cur_dsd = lcont_pkt.dsd;
30198ae6d9c7SGiridhar Malavali avail_dsds = 5;
30208ae6d9c7SGiridhar Malavali cont = 1;
30218ae6d9c7SGiridhar Malavali }
30228ae6d9c7SGiridhar Malavali
302315b7a68cSBart Van Assche append_dsd64(&cur_dsd, sg);
30248ae6d9c7SGiridhar Malavali avail_dsds--;
30258ae6d9c7SGiridhar Malavali if (avail_dsds == 0 && cont == 1) {
30268ae6d9c7SGiridhar Malavali cont = 0;
30278ae6d9c7SGiridhar Malavali memcpy_toio((void __iomem *)cont_pkt, &lcont_pkt,
3028f8f97b0cSJoe Carnuccio sizeof(lcont_pkt));
30298ae6d9c7SGiridhar Malavali }
30308ae6d9c7SGiridhar Malavali
30318ae6d9c7SGiridhar Malavali }
30328ae6d9c7SGiridhar Malavali if (avail_dsds != 0 && cont == 1) {
30338ae6d9c7SGiridhar Malavali memcpy_toio((void __iomem *)cont_pkt, &lcont_pkt,
3034f8f97b0cSJoe Carnuccio sizeof(lcont_pkt));
30358ae6d9c7SGiridhar Malavali }
30368ae6d9c7SGiridhar Malavali }
30378ae6d9c7SGiridhar Malavali
30388ae6d9c7SGiridhar Malavali /**
30398ae6d9c7SGiridhar Malavali * qlafx00_start_scsi() - Send a SCSI command to the ISP
30408ae6d9c7SGiridhar Malavali * @sp: command to send to the ISP
30418ae6d9c7SGiridhar Malavali *
30428ae6d9c7SGiridhar Malavali * Returns non-zero if a failure occurred, else zero.
30438ae6d9c7SGiridhar Malavali */
30448ae6d9c7SGiridhar Malavali int
qlafx00_start_scsi(srb_t * sp)30458ae6d9c7SGiridhar Malavali qlafx00_start_scsi(srb_t *sp)
30468ae6d9c7SGiridhar Malavali {
304752c82823SBart Van Assche int nseg;
30488ae6d9c7SGiridhar Malavali unsigned long flags;
30498ae6d9c7SGiridhar Malavali uint32_t handle;
30508ae6d9c7SGiridhar Malavali uint16_t cnt;
30518ae6d9c7SGiridhar Malavali uint16_t req_cnt;
30528ae6d9c7SGiridhar Malavali uint16_t tot_dsds;
30538ae6d9c7SGiridhar Malavali struct req_que *req = NULL;
30548ae6d9c7SGiridhar Malavali struct rsp_que *rsp = NULL;
30558ae6d9c7SGiridhar Malavali struct scsi_cmnd *cmd = GET_CMD_SP(sp);
305625ff6af1SJoe Carnuccio struct scsi_qla_host *vha = sp->vha;
30578ae6d9c7SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
30588ae6d9c7SGiridhar Malavali struct cmd_type_7_fx00 *cmd_pkt;
30598ae6d9c7SGiridhar Malavali struct cmd_type_7_fx00 lcmd_pkt;
30608ae6d9c7SGiridhar Malavali struct scsi_lun llun;
30618ae6d9c7SGiridhar Malavali
30628ae6d9c7SGiridhar Malavali /* Setup device pointers. */
30638ae6d9c7SGiridhar Malavali rsp = ha->rsp_q_map[0];
30648ae6d9c7SGiridhar Malavali req = vha->req;
30658ae6d9c7SGiridhar Malavali
30668ae6d9c7SGiridhar Malavali /* So we know we haven't pci_map'ed anything yet */
30678ae6d9c7SGiridhar Malavali tot_dsds = 0;
30688ae6d9c7SGiridhar Malavali
30698ae6d9c7SGiridhar Malavali /* Acquire ring specific lock */
30708ae6d9c7SGiridhar Malavali spin_lock_irqsave(&ha->hardware_lock, flags);
30718ae6d9c7SGiridhar Malavali
3072bcc85657SBart Van Assche handle = qla2xxx_get_next_handle(req);
3073bcc85657SBart Van Assche if (handle == 0)
30748ae6d9c7SGiridhar Malavali goto queuing_error;
30758ae6d9c7SGiridhar Malavali
30768ae6d9c7SGiridhar Malavali /* Map the sg table so we have an accurate count of sg entries needed */
30778ae6d9c7SGiridhar Malavali if (scsi_sg_count(cmd)) {
30788ae6d9c7SGiridhar Malavali nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd),
30798ae6d9c7SGiridhar Malavali scsi_sg_count(cmd), cmd->sc_data_direction);
30808ae6d9c7SGiridhar Malavali if (unlikely(!nseg))
30818ae6d9c7SGiridhar Malavali goto queuing_error;
30828ae6d9c7SGiridhar Malavali } else
30838ae6d9c7SGiridhar Malavali nseg = 0;
30848ae6d9c7SGiridhar Malavali
30858ae6d9c7SGiridhar Malavali tot_dsds = nseg;
30868ae6d9c7SGiridhar Malavali req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
30878ae6d9c7SGiridhar Malavali if (req->cnt < (req_cnt + 2)) {
308804474d3aSBart Van Assche cnt = rd_reg_dword_relaxed(req->req_q_out);
30898ae6d9c7SGiridhar Malavali
30908ae6d9c7SGiridhar Malavali if (req->ring_index < cnt)
30918ae6d9c7SGiridhar Malavali req->cnt = cnt - req->ring_index;
30928ae6d9c7SGiridhar Malavali else
30938ae6d9c7SGiridhar Malavali req->cnt = req->length -
30948ae6d9c7SGiridhar Malavali (req->ring_index - cnt);
30958ae6d9c7SGiridhar Malavali if (req->cnt < (req_cnt + 2))
30968ae6d9c7SGiridhar Malavali goto queuing_error;
30978ae6d9c7SGiridhar Malavali }
30988ae6d9c7SGiridhar Malavali
30998ae6d9c7SGiridhar Malavali /* Build command packet. */
31008ae6d9c7SGiridhar Malavali req->current_outstanding_cmd = handle;
31018ae6d9c7SGiridhar Malavali req->outstanding_cmds[handle] = sp;
31028ae6d9c7SGiridhar Malavali sp->handle = handle;
31038ae6d9c7SGiridhar Malavali cmd->host_scribble = (unsigned char *)(unsigned long)handle;
31048ae6d9c7SGiridhar Malavali req->cnt -= req_cnt;
31058ae6d9c7SGiridhar Malavali
31068ae6d9c7SGiridhar Malavali cmd_pkt = (struct cmd_type_7_fx00 *)req->ring_ptr;
31078ae6d9c7SGiridhar Malavali
31088ae6d9c7SGiridhar Malavali memset(&lcmd_pkt, 0, REQUEST_ENTRY_SIZE);
31098ae6d9c7SGiridhar Malavali
3110c25eb70aSBart Van Assche lcmd_pkt.handle = make_handle(req->id, sp->handle);
3111d68b3e01SArmen Baloyan lcmd_pkt.reserved_0 = 0;
3112d68b3e01SArmen Baloyan lcmd_pkt.port_path_ctrl = 0;
3113d68b3e01SArmen Baloyan lcmd_pkt.reserved_1 = 0;
31148ae6d9c7SGiridhar Malavali lcmd_pkt.dseg_count = cpu_to_le16(tot_dsds);
31158ae6d9c7SGiridhar Malavali lcmd_pkt.tgt_idx = cpu_to_le16(sp->fcport->tgt_id);
31168ae6d9c7SGiridhar Malavali
31178ae6d9c7SGiridhar Malavali int_to_scsilun(cmd->device->lun, &llun);
31188ae6d9c7SGiridhar Malavali host_to_adap((uint8_t *)&llun, (uint8_t *)&lcmd_pkt.lun,
31198ae6d9c7SGiridhar Malavali sizeof(lcmd_pkt.lun));
31208ae6d9c7SGiridhar Malavali
31218ae6d9c7SGiridhar Malavali /* Load SCSI command packet. */
31228ae6d9c7SGiridhar Malavali host_to_adap(cmd->cmnd, lcmd_pkt.fcp_cdb, sizeof(lcmd_pkt.fcp_cdb));
31238ae6d9c7SGiridhar Malavali lcmd_pkt.byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd));
31248ae6d9c7SGiridhar Malavali
31258ae6d9c7SGiridhar Malavali /* Build IOCB segments */
31268ae6d9c7SGiridhar Malavali qlafx00_build_scsi_iocbs(sp, cmd_pkt, tot_dsds, &lcmd_pkt);
31278ae6d9c7SGiridhar Malavali
31288ae6d9c7SGiridhar Malavali /* Set total data segment count. */
31298ae6d9c7SGiridhar Malavali lcmd_pkt.entry_count = (uint8_t)req_cnt;
31308ae6d9c7SGiridhar Malavali
31318ae6d9c7SGiridhar Malavali /* Specify response queue number where completion should happen */
31328ae6d9c7SGiridhar Malavali lcmd_pkt.entry_status = (uint8_t) rsp->id;
31338ae6d9c7SGiridhar Malavali
31348ae6d9c7SGiridhar Malavali ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302e,
3135f8f97b0cSJoe Carnuccio cmd->cmnd, cmd->cmd_len);
31368ae6d9c7SGiridhar Malavali ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x3032,
3137f8f97b0cSJoe Carnuccio &lcmd_pkt, sizeof(lcmd_pkt));
31388ae6d9c7SGiridhar Malavali
31398ae6d9c7SGiridhar Malavali memcpy_toio((void __iomem *)cmd_pkt, &lcmd_pkt, REQUEST_ENTRY_SIZE);
31408ae6d9c7SGiridhar Malavali wmb();
31418ae6d9c7SGiridhar Malavali
31428ae6d9c7SGiridhar Malavali /* Adjust ring index. */
31438ae6d9c7SGiridhar Malavali req->ring_index++;
31448ae6d9c7SGiridhar Malavali if (req->ring_index == req->length) {
31458ae6d9c7SGiridhar Malavali req->ring_index = 0;
31468ae6d9c7SGiridhar Malavali req->ring_ptr = req->ring;
31478ae6d9c7SGiridhar Malavali } else
31488ae6d9c7SGiridhar Malavali req->ring_ptr++;
31498ae6d9c7SGiridhar Malavali
31508ae6d9c7SGiridhar Malavali sp->flags |= SRB_DMA_VALID;
31518ae6d9c7SGiridhar Malavali
31528ae6d9c7SGiridhar Malavali /* Set chip new ring index. */
315304474d3aSBart Van Assche wrt_reg_dword(req->req_q_in, req->ring_index);
31548ae6d9c7SGiridhar Malavali QLAFX00_SET_HST_INTR(ha, ha->rqstq_intr_code);
31558ae6d9c7SGiridhar Malavali
31568ae6d9c7SGiridhar Malavali spin_unlock_irqrestore(&ha->hardware_lock, flags);
31578ae6d9c7SGiridhar Malavali return QLA_SUCCESS;
31588ae6d9c7SGiridhar Malavali
31598ae6d9c7SGiridhar Malavali queuing_error:
31608ae6d9c7SGiridhar Malavali if (tot_dsds)
31618ae6d9c7SGiridhar Malavali scsi_dma_unmap(cmd);
31628ae6d9c7SGiridhar Malavali
31638ae6d9c7SGiridhar Malavali spin_unlock_irqrestore(&ha->hardware_lock, flags);
31648ae6d9c7SGiridhar Malavali
31658ae6d9c7SGiridhar Malavali return QLA_FUNCTION_FAILED;
31668ae6d9c7SGiridhar Malavali }
31678ae6d9c7SGiridhar Malavali
31688ae6d9c7SGiridhar Malavali void
qlafx00_tm_iocb(srb_t * sp,struct tsk_mgmt_entry_fx00 * ptm_iocb)31698ae6d9c7SGiridhar Malavali qlafx00_tm_iocb(srb_t *sp, struct tsk_mgmt_entry_fx00 *ptm_iocb)
31708ae6d9c7SGiridhar Malavali {
31718ae6d9c7SGiridhar Malavali struct srb_iocb *fxio = &sp->u.iocb_cmd;
317225ff6af1SJoe Carnuccio scsi_qla_host_t *vha = sp->vha;
31738ae6d9c7SGiridhar Malavali struct req_que *req = vha->req;
31748ae6d9c7SGiridhar Malavali struct tsk_mgmt_entry_fx00 tm_iocb;
31758ae6d9c7SGiridhar Malavali struct scsi_lun llun;
31768ae6d9c7SGiridhar Malavali
31778ae6d9c7SGiridhar Malavali memset(&tm_iocb, 0, sizeof(struct tsk_mgmt_entry_fx00));
31788ae6d9c7SGiridhar Malavali tm_iocb.entry_type = TSK_MGMT_IOCB_TYPE_FX00;
31798ae6d9c7SGiridhar Malavali tm_iocb.entry_count = 1;
31807ffa5b93SBart Van Assche tm_iocb.handle = make_handle(req->id, sp->handle);
3181d68b3e01SArmen Baloyan tm_iocb.reserved_0 = 0;
31828ae6d9c7SGiridhar Malavali tm_iocb.tgt_id = cpu_to_le16(sp->fcport->tgt_id);
31838ae6d9c7SGiridhar Malavali tm_iocb.control_flags = cpu_to_le32(fxio->u.tmf.flags);
31841f8deefeSSaurav Kashyap if (tm_iocb.control_flags == cpu_to_le32((uint32_t)TCF_LUN_RESET)) {
31858ae6d9c7SGiridhar Malavali int_to_scsilun(fxio->u.tmf.lun, &llun);
31868ae6d9c7SGiridhar Malavali host_to_adap((uint8_t *)&llun, (uint8_t *)&tm_iocb.lun,
31878ae6d9c7SGiridhar Malavali sizeof(struct scsi_lun));
31888ae6d9c7SGiridhar Malavali }
31898ae6d9c7SGiridhar Malavali
3190ab053c09SBart Van Assche memcpy(ptm_iocb, &tm_iocb,
31918ae6d9c7SGiridhar Malavali sizeof(struct tsk_mgmt_entry_fx00));
31928ae6d9c7SGiridhar Malavali wmb();
31938ae6d9c7SGiridhar Malavali }
31948ae6d9c7SGiridhar Malavali
31958ae6d9c7SGiridhar Malavali void
qlafx00_abort_iocb(srb_t * sp,struct abort_iocb_entry_fx00 * pabt_iocb)31968ae6d9c7SGiridhar Malavali qlafx00_abort_iocb(srb_t *sp, struct abort_iocb_entry_fx00 *pabt_iocb)
31978ae6d9c7SGiridhar Malavali {
31988ae6d9c7SGiridhar Malavali struct srb_iocb *fxio = &sp->u.iocb_cmd;
319925ff6af1SJoe Carnuccio scsi_qla_host_t *vha = sp->vha;
32008ae6d9c7SGiridhar Malavali struct req_que *req = vha->req;
32018ae6d9c7SGiridhar Malavali struct abort_iocb_entry_fx00 abt_iocb;
32028ae6d9c7SGiridhar Malavali
32038ae6d9c7SGiridhar Malavali memset(&abt_iocb, 0, sizeof(struct abort_iocb_entry_fx00));
32048ae6d9c7SGiridhar Malavali abt_iocb.entry_type = ABORT_IOCB_TYPE_FX00;
32058ae6d9c7SGiridhar Malavali abt_iocb.entry_count = 1;
32067ffa5b93SBart Van Assche abt_iocb.handle = make_handle(req->id, sp->handle);
32077ffa5b93SBart Van Assche abt_iocb.abort_handle = make_handle(req->id, fxio->u.abt.cmd_hndl);
32088ae6d9c7SGiridhar Malavali abt_iocb.tgt_id_sts = cpu_to_le16(sp->fcport->tgt_id);
32098ae6d9c7SGiridhar Malavali abt_iocb.req_que_no = cpu_to_le16(req->id);
32108ae6d9c7SGiridhar Malavali
3211ab053c09SBart Van Assche memcpy(pabt_iocb, &abt_iocb,
32128ae6d9c7SGiridhar Malavali sizeof(struct abort_iocb_entry_fx00));
32138ae6d9c7SGiridhar Malavali wmb();
32148ae6d9c7SGiridhar Malavali }
32158ae6d9c7SGiridhar Malavali
32168ae6d9c7SGiridhar Malavali void
qlafx00_fxdisc_iocb(srb_t * sp,struct fxdisc_entry_fx00 * pfxiocb)32178ae6d9c7SGiridhar Malavali qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb)
32188ae6d9c7SGiridhar Malavali {
32198ae6d9c7SGiridhar Malavali struct srb_iocb *fxio = &sp->u.iocb_cmd;
32208ae6d9c7SGiridhar Malavali struct qla_mt_iocb_rqst_fx00 *piocb_rqst;
322175cc8cfcSJohannes Thumshirn struct bsg_job *bsg_job;
322201e0e15cSJohannes Thumshirn struct fc_bsg_request *bsg_request;
32238ae6d9c7SGiridhar Malavali struct fxdisc_entry_fx00 fx_iocb;
32248ae6d9c7SGiridhar Malavali uint8_t entry_cnt = 1;
32258ae6d9c7SGiridhar Malavali
32268ae6d9c7SGiridhar Malavali memset(&fx_iocb, 0, sizeof(struct fxdisc_entry_fx00));
32278ae6d9c7SGiridhar Malavali fx_iocb.entry_type = FX00_IOCB_TYPE;
32287ffa5b93SBart Van Assche fx_iocb.handle = sp->handle;
32298ae6d9c7SGiridhar Malavali fx_iocb.entry_count = entry_cnt;
32308ae6d9c7SGiridhar Malavali
32318ae6d9c7SGiridhar Malavali if (sp->type == SRB_FXIOCB_DCMD) {
32328ae6d9c7SGiridhar Malavali fx_iocb.func_num =
32331f8deefeSSaurav Kashyap sp->u.iocb_cmd.u.fxiocb.req_func_type;
32341f8deefeSSaurav Kashyap fx_iocb.adapid = fxio->u.fxiocb.adapter_id;
32351f8deefeSSaurav Kashyap fx_iocb.adapid_hi = fxio->u.fxiocb.adapter_id_hi;
32361f8deefeSSaurav Kashyap fx_iocb.reserved_0 = fxio->u.fxiocb.reserved_0;
32371f8deefeSSaurav Kashyap fx_iocb.reserved_1 = fxio->u.fxiocb.reserved_1;
32381f8deefeSSaurav Kashyap fx_iocb.dataword_extra = fxio->u.fxiocb.req_data_extra;
32398ae6d9c7SGiridhar Malavali
32408ae6d9c7SGiridhar Malavali if (fxio->u.fxiocb.flags & SRB_FXDISC_REQ_DMA_VALID) {
32418ae6d9c7SGiridhar Malavali fx_iocb.req_dsdcnt = cpu_to_le16(1);
32428ae6d9c7SGiridhar Malavali fx_iocb.req_xfrcnt =
32438ae6d9c7SGiridhar Malavali cpu_to_le16(fxio->u.fxiocb.req_len);
3244d4556a49SBart Van Assche put_unaligned_le64(fxio->u.fxiocb.req_dma_handle,
324517603237SBart Van Assche &fx_iocb.dseg_rq[0].address);
324617603237SBart Van Assche fx_iocb.dseg_rq[0].length =
32478ae6d9c7SGiridhar Malavali cpu_to_le32(fxio->u.fxiocb.req_len);
32488ae6d9c7SGiridhar Malavali }
32498ae6d9c7SGiridhar Malavali
32508ae6d9c7SGiridhar Malavali if (fxio->u.fxiocb.flags & SRB_FXDISC_RESP_DMA_VALID) {
32518ae6d9c7SGiridhar Malavali fx_iocb.rsp_dsdcnt = cpu_to_le16(1);
32528ae6d9c7SGiridhar Malavali fx_iocb.rsp_xfrcnt =
32538ae6d9c7SGiridhar Malavali cpu_to_le16(fxio->u.fxiocb.rsp_len);
3254d4556a49SBart Van Assche put_unaligned_le64(fxio->u.fxiocb.rsp_dma_handle,
325517603237SBart Van Assche &fx_iocb.dseg_rsp[0].address);
325617603237SBart Van Assche fx_iocb.dseg_rsp[0].length =
32578ae6d9c7SGiridhar Malavali cpu_to_le32(fxio->u.fxiocb.rsp_len);
32588ae6d9c7SGiridhar Malavali }
32598ae6d9c7SGiridhar Malavali
32608ae6d9c7SGiridhar Malavali if (fxio->u.fxiocb.flags & SRB_FXDISC_REQ_DWRD_VALID) {
32611f8deefeSSaurav Kashyap fx_iocb.dataword = fxio->u.fxiocb.req_data;
32628ae6d9c7SGiridhar Malavali }
32638ae6d9c7SGiridhar Malavali fx_iocb.flags = fxio->u.fxiocb.flags;
32648ae6d9c7SGiridhar Malavali } else {
32658ae6d9c7SGiridhar Malavali struct scatterlist *sg;
3266bd432bb5SBart Van Assche
32678ae6d9c7SGiridhar Malavali bsg_job = sp->u.bsg_job;
326801e0e15cSJohannes Thumshirn bsg_request = bsg_job->request;
32698ae6d9c7SGiridhar Malavali piocb_rqst = (struct qla_mt_iocb_rqst_fx00 *)
327001e0e15cSJohannes Thumshirn &bsg_request->rqst_data.h_vendor.vendor_cmd[1];
32718ae6d9c7SGiridhar Malavali
32728ae6d9c7SGiridhar Malavali fx_iocb.func_num = piocb_rqst->func_type;
32738ae6d9c7SGiridhar Malavali fx_iocb.adapid = piocb_rqst->adapid;
32748ae6d9c7SGiridhar Malavali fx_iocb.adapid_hi = piocb_rqst->adapid_hi;
32758ae6d9c7SGiridhar Malavali fx_iocb.reserved_0 = piocb_rqst->reserved_0;
32768ae6d9c7SGiridhar Malavali fx_iocb.reserved_1 = piocb_rqst->reserved_1;
32778ae6d9c7SGiridhar Malavali fx_iocb.dataword_extra = piocb_rqst->dataword_extra;
32788ae6d9c7SGiridhar Malavali fx_iocb.dataword = piocb_rqst->dataword;
32791f8deefeSSaurav Kashyap fx_iocb.req_xfrcnt = piocb_rqst->req_len;
32801f8deefeSSaurav Kashyap fx_iocb.rsp_xfrcnt = piocb_rqst->rsp_len;
32818ae6d9c7SGiridhar Malavali
32828ae6d9c7SGiridhar Malavali if (piocb_rqst->flags & SRB_FXDISC_REQ_DMA_VALID) {
32838ae6d9c7SGiridhar Malavali int avail_dsds, tot_dsds;
32848ae6d9c7SGiridhar Malavali cont_a64_entry_t lcont_pkt;
32858ae6d9c7SGiridhar Malavali cont_a64_entry_t *cont_pkt = NULL;
328615b7a68cSBart Van Assche struct dsd64 *cur_dsd;
32878ae6d9c7SGiridhar Malavali int index = 0, cont = 0;
32888ae6d9c7SGiridhar Malavali
32898ae6d9c7SGiridhar Malavali fx_iocb.req_dsdcnt =
32908ae6d9c7SGiridhar Malavali cpu_to_le16(bsg_job->request_payload.sg_cnt);
32918ae6d9c7SGiridhar Malavali tot_dsds =
32921f8deefeSSaurav Kashyap bsg_job->request_payload.sg_cnt;
329317603237SBart Van Assche cur_dsd = &fx_iocb.dseg_rq[0];
32948ae6d9c7SGiridhar Malavali avail_dsds = 1;
32958ae6d9c7SGiridhar Malavali for_each_sg(bsg_job->request_payload.sg_list, sg,
32968ae6d9c7SGiridhar Malavali tot_dsds, index) {
32978ae6d9c7SGiridhar Malavali /* Allocate additional continuation packets? */
32988ae6d9c7SGiridhar Malavali if (avail_dsds == 0) {
32998ae6d9c7SGiridhar Malavali /*
33008ae6d9c7SGiridhar Malavali * Five DSDs are available in the Cont.
33018ae6d9c7SGiridhar Malavali * Type 1 IOCB.
33028ae6d9c7SGiridhar Malavali */
33038ae6d9c7SGiridhar Malavali memset(&lcont_pkt, 0,
33048ae6d9c7SGiridhar Malavali REQUEST_ENTRY_SIZE);
33058ae6d9c7SGiridhar Malavali cont_pkt =
33068ae6d9c7SGiridhar Malavali qlafx00_prep_cont_type1_iocb(
330725ff6af1SJoe Carnuccio sp->vha->req, &lcont_pkt);
330815b7a68cSBart Van Assche cur_dsd = lcont_pkt.dsd;
33098ae6d9c7SGiridhar Malavali avail_dsds = 5;
33108ae6d9c7SGiridhar Malavali cont = 1;
33118ae6d9c7SGiridhar Malavali entry_cnt++;
33128ae6d9c7SGiridhar Malavali }
33138ae6d9c7SGiridhar Malavali
331415b7a68cSBart Van Assche append_dsd64(&cur_dsd, sg);
33158ae6d9c7SGiridhar Malavali avail_dsds--;
33168ae6d9c7SGiridhar Malavali
33178ae6d9c7SGiridhar Malavali if (avail_dsds == 0 && cont == 1) {
33188ae6d9c7SGiridhar Malavali cont = 0;
33198ae6d9c7SGiridhar Malavali memcpy_toio(
33208ae6d9c7SGiridhar Malavali (void __iomem *)cont_pkt,
33218ae6d9c7SGiridhar Malavali &lcont_pkt, REQUEST_ENTRY_SIZE);
33228ae6d9c7SGiridhar Malavali ql_dump_buffer(
33238ae6d9c7SGiridhar Malavali ql_dbg_user + ql_dbg_verbose,
332425ff6af1SJoe Carnuccio sp->vha, 0x3042,
33258ae6d9c7SGiridhar Malavali (uint8_t *)&lcont_pkt,
33268ae6d9c7SGiridhar Malavali REQUEST_ENTRY_SIZE);
33278ae6d9c7SGiridhar Malavali }
33288ae6d9c7SGiridhar Malavali }
33298ae6d9c7SGiridhar Malavali if (avail_dsds != 0 && cont == 1) {
33308ae6d9c7SGiridhar Malavali memcpy_toio((void __iomem *)cont_pkt,
33318ae6d9c7SGiridhar Malavali &lcont_pkt, REQUEST_ENTRY_SIZE);
33328ae6d9c7SGiridhar Malavali ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
333325ff6af1SJoe Carnuccio sp->vha, 0x3043,
33348ae6d9c7SGiridhar Malavali (uint8_t *)&lcont_pkt, REQUEST_ENTRY_SIZE);
33358ae6d9c7SGiridhar Malavali }
33368ae6d9c7SGiridhar Malavali }
33378ae6d9c7SGiridhar Malavali
33388ae6d9c7SGiridhar Malavali if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID) {
33398ae6d9c7SGiridhar Malavali int avail_dsds, tot_dsds;
33408ae6d9c7SGiridhar Malavali cont_a64_entry_t lcont_pkt;
33418ae6d9c7SGiridhar Malavali cont_a64_entry_t *cont_pkt = NULL;
334215b7a68cSBart Van Assche struct dsd64 *cur_dsd;
33438ae6d9c7SGiridhar Malavali int index = 0, cont = 0;
33448ae6d9c7SGiridhar Malavali
33458ae6d9c7SGiridhar Malavali fx_iocb.rsp_dsdcnt =
33468ae6d9c7SGiridhar Malavali cpu_to_le16(bsg_job->reply_payload.sg_cnt);
33471f8deefeSSaurav Kashyap tot_dsds = bsg_job->reply_payload.sg_cnt;
334817603237SBart Van Assche cur_dsd = &fx_iocb.dseg_rsp[0];
33498ae6d9c7SGiridhar Malavali avail_dsds = 1;
33508ae6d9c7SGiridhar Malavali
33518ae6d9c7SGiridhar Malavali for_each_sg(bsg_job->reply_payload.sg_list, sg,
33528ae6d9c7SGiridhar Malavali tot_dsds, index) {
33538ae6d9c7SGiridhar Malavali /* Allocate additional continuation packets? */
33548ae6d9c7SGiridhar Malavali if (avail_dsds == 0) {
33558ae6d9c7SGiridhar Malavali /*
33568ae6d9c7SGiridhar Malavali * Five DSDs are available in the Cont.
33578ae6d9c7SGiridhar Malavali * Type 1 IOCB.
33588ae6d9c7SGiridhar Malavali */
33598ae6d9c7SGiridhar Malavali memset(&lcont_pkt, 0,
33608ae6d9c7SGiridhar Malavali REQUEST_ENTRY_SIZE);
33618ae6d9c7SGiridhar Malavali cont_pkt =
33628ae6d9c7SGiridhar Malavali qlafx00_prep_cont_type1_iocb(
336325ff6af1SJoe Carnuccio sp->vha->req, &lcont_pkt);
336415b7a68cSBart Van Assche cur_dsd = lcont_pkt.dsd;
33658ae6d9c7SGiridhar Malavali avail_dsds = 5;
33668ae6d9c7SGiridhar Malavali cont = 1;
33678ae6d9c7SGiridhar Malavali entry_cnt++;
33688ae6d9c7SGiridhar Malavali }
33698ae6d9c7SGiridhar Malavali
337015b7a68cSBart Van Assche append_dsd64(&cur_dsd, sg);
33718ae6d9c7SGiridhar Malavali avail_dsds--;
33728ae6d9c7SGiridhar Malavali
33738ae6d9c7SGiridhar Malavali if (avail_dsds == 0 && cont == 1) {
33748ae6d9c7SGiridhar Malavali cont = 0;
33758ae6d9c7SGiridhar Malavali memcpy_toio((void __iomem *)cont_pkt,
33768ae6d9c7SGiridhar Malavali &lcont_pkt,
33778ae6d9c7SGiridhar Malavali REQUEST_ENTRY_SIZE);
33788ae6d9c7SGiridhar Malavali ql_dump_buffer(
33798ae6d9c7SGiridhar Malavali ql_dbg_user + ql_dbg_verbose,
338025ff6af1SJoe Carnuccio sp->vha, 0x3045,
33818ae6d9c7SGiridhar Malavali (uint8_t *)&lcont_pkt,
33828ae6d9c7SGiridhar Malavali REQUEST_ENTRY_SIZE);
33838ae6d9c7SGiridhar Malavali }
33848ae6d9c7SGiridhar Malavali }
33858ae6d9c7SGiridhar Malavali if (avail_dsds != 0 && cont == 1) {
33868ae6d9c7SGiridhar Malavali memcpy_toio((void __iomem *)cont_pkt,
33878ae6d9c7SGiridhar Malavali &lcont_pkt, REQUEST_ENTRY_SIZE);
33888ae6d9c7SGiridhar Malavali ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
338925ff6af1SJoe Carnuccio sp->vha, 0x3046,
33908ae6d9c7SGiridhar Malavali (uint8_t *)&lcont_pkt, REQUEST_ENTRY_SIZE);
33918ae6d9c7SGiridhar Malavali }
33928ae6d9c7SGiridhar Malavali }
33938ae6d9c7SGiridhar Malavali
33948ae6d9c7SGiridhar Malavali if (piocb_rqst->flags & SRB_FXDISC_REQ_DWRD_VALID)
33951f8deefeSSaurav Kashyap fx_iocb.dataword = piocb_rqst->dataword;
33968ae6d9c7SGiridhar Malavali fx_iocb.flags = piocb_rqst->flags;
33978ae6d9c7SGiridhar Malavali fx_iocb.entry_count = entry_cnt;
33988ae6d9c7SGiridhar Malavali }
33998ae6d9c7SGiridhar Malavali
34008ae6d9c7SGiridhar Malavali ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
3401f8f97b0cSJoe Carnuccio sp->vha, 0x3047, &fx_iocb, sizeof(fx_iocb));
34028ae6d9c7SGiridhar Malavali
3403f8f97b0cSJoe Carnuccio memcpy_toio((void __iomem *)pfxiocb, &fx_iocb, sizeof(fx_iocb));
34048ae6d9c7SGiridhar Malavali wmb();
34058ae6d9c7SGiridhar Malavali }
3406