xref: /linux/drivers/scsi/qla2xxx/qla_mr.c (revision 621cde16e49b3ecf7d59a8106a20aaebfb4a59a9)
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 = &reg->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(&reg->req_q_in, 0);
67904474d3aSBart Van Assche 	wrt_reg_dword(&reg->req_q_out, 0);
6808ae6d9c7SGiridhar Malavali 
68104474d3aSBart Van Assche 	wrt_reg_dword(&reg->rsp_q_in, 0);
68204474d3aSBart Van Assche 	wrt_reg_dword(&reg->rsp_q_out, 0);
6838ae6d9c7SGiridhar Malavali 
6848ae6d9c7SGiridhar Malavali 	/* PCI posting */
68504474d3aSBart Van Assche 	rd_reg_dword(&reg->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(&reg->pseudoaen);
892f9a2a543SArmen Baloyan 	if (pseudo_aen == 1) {
89304474d3aSBart Van Assche 		aenmbx7 = rd_reg_dword(&reg->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(&reg->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(&reg->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(&reg->aenmailbox1);
92704474d3aSBart Van Assche 			ha->rsp_que_off = rd_reg_dword(&reg->aenmailbox3);
92804474d3aSBart Van Assche 			ha->req_que_len = rd_reg_dword(&reg->aenmailbox5);
92904474d3aSBart Van Assche 			ha->rsp_que_len = rd_reg_dword(&reg->aenmailbox6);
93004474d3aSBart Van Assche 			wrt_reg_dword(&reg->aenmailbox0, 0);
93104474d3aSBart Van Assche 			rd_reg_dword_relaxed(&reg->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(&reg->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(&reg->initval1);
96504474d3aSBart Van Assche 			ha->rsp_que_off = rd_reg_dword(&reg->initval3);
96604474d3aSBart Van Assche 			ha->req_que_len = rd_reg_dword(&reg->initval5);
96704474d3aSBart Van Assche 			ha->rsp_que_len = rd_reg_dword(&reg->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(&reg->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(&reg->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(&reg->aenmailbox1);
142704474d3aSBart Van Assche 	ha->rsp_que_off = rd_reg_dword(&reg->aenmailbox3);
142804474d3aSBart Van Assche 	ha->req_que_len = rd_reg_dword(&reg->aenmailbox5);
142904474d3aSBart Van Assche 	ha->rsp_que_len = rd_reg_dword(&reg->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(&reg->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(&reg->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(&reg->aenmailbox1);
279004474d3aSBart Van Assche 		ha->aenmb[2] = rd_reg_dword(&reg->aenmailbox2);
279104474d3aSBart Van Assche 		ha->aenmb[3] = rd_reg_dword(&reg->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(&reg->aenmailbox1);
282204474d3aSBart Van Assche 		ha->aenmb[2] = rd_reg_dword(&reg->aenmailbox2);
282304474d3aSBart Van Assche 		ha->aenmb[3] = rd_reg_dword(&reg->aenmailbox3);
282404474d3aSBart Van Assche 		ha->aenmb[4] = rd_reg_dword(&reg->aenmailbox4);
282504474d3aSBart Van Assche 		ha->aenmb[5] = rd_reg_dword(&reg->aenmailbox5);
282604474d3aSBart Van Assche 		ha->aenmb[6] = rd_reg_dword(&reg->aenmailbox6);
282704474d3aSBart Van Assche 		ha->aenmb[7] = rd_reg_dword(&reg->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 = &reg->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(&reg->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(&reg->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