162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * QLogic Fibre Channel HBA Driver
462306a36Sopenharmony_ci * Copyright (c)  2003-2014 QLogic Corporation
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci#include "qla_def.h"
762306a36Sopenharmony_ci#include "qla_target.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/delay.h>
1062306a36Sopenharmony_ci#include <linux/gfp.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#ifdef CONFIG_PPC
1362306a36Sopenharmony_ci#define IS_PPCARCH      true
1462306a36Sopenharmony_ci#else
1562306a36Sopenharmony_ci#define IS_PPCARCH      false
1662306a36Sopenharmony_ci#endif
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistatic struct mb_cmd_name {
1962306a36Sopenharmony_ci	uint16_t cmd;
2062306a36Sopenharmony_ci	const char *str;
2162306a36Sopenharmony_ci} mb_str[] = {
2262306a36Sopenharmony_ci	{MBC_GET_PORT_DATABASE,		"GPDB"},
2362306a36Sopenharmony_ci	{MBC_GET_ID_LIST,		"GIDList"},
2462306a36Sopenharmony_ci	{MBC_GET_LINK_PRIV_STATS,	"Stats"},
2562306a36Sopenharmony_ci	{MBC_GET_RESOURCE_COUNTS,	"ResCnt"},
2662306a36Sopenharmony_ci};
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic const char *mb_to_str(uint16_t cmd)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	int i;
3162306a36Sopenharmony_ci	struct mb_cmd_name *e;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(mb_str); i++) {
3462306a36Sopenharmony_ci		e = mb_str + i;
3562306a36Sopenharmony_ci		if (cmd == e->cmd)
3662306a36Sopenharmony_ci			return e->str;
3762306a36Sopenharmony_ci	}
3862306a36Sopenharmony_ci	return "unknown";
3962306a36Sopenharmony_ci}
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistatic struct rom_cmd {
4262306a36Sopenharmony_ci	uint16_t cmd;
4362306a36Sopenharmony_ci} rom_cmds[] = {
4462306a36Sopenharmony_ci	{ MBC_LOAD_RAM },
4562306a36Sopenharmony_ci	{ MBC_EXECUTE_FIRMWARE },
4662306a36Sopenharmony_ci	{ MBC_READ_RAM_WORD },
4762306a36Sopenharmony_ci	{ MBC_MAILBOX_REGISTER_TEST },
4862306a36Sopenharmony_ci	{ MBC_VERIFY_CHECKSUM },
4962306a36Sopenharmony_ci	{ MBC_GET_FIRMWARE_VERSION },
5062306a36Sopenharmony_ci	{ MBC_LOAD_RISC_RAM },
5162306a36Sopenharmony_ci	{ MBC_DUMP_RISC_RAM },
5262306a36Sopenharmony_ci	{ MBC_LOAD_RISC_RAM_EXTENDED },
5362306a36Sopenharmony_ci	{ MBC_DUMP_RISC_RAM_EXTENDED },
5462306a36Sopenharmony_ci	{ MBC_WRITE_RAM_WORD_EXTENDED },
5562306a36Sopenharmony_ci	{ MBC_READ_RAM_EXTENDED },
5662306a36Sopenharmony_ci	{ MBC_GET_RESOURCE_COUNTS },
5762306a36Sopenharmony_ci	{ MBC_SET_FIRMWARE_OPTION },
5862306a36Sopenharmony_ci	{ MBC_MID_INITIALIZE_FIRMWARE },
5962306a36Sopenharmony_ci	{ MBC_GET_FIRMWARE_STATE },
6062306a36Sopenharmony_ci	{ MBC_GET_MEM_OFFLOAD_CNTRL_STAT },
6162306a36Sopenharmony_ci	{ MBC_GET_RETRY_COUNT },
6262306a36Sopenharmony_ci	{ MBC_TRACE_CONTROL },
6362306a36Sopenharmony_ci	{ MBC_INITIALIZE_MULTIQ },
6462306a36Sopenharmony_ci	{ MBC_IOCB_COMMAND_A64 },
6562306a36Sopenharmony_ci	{ MBC_GET_ADAPTER_LOOP_ID },
6662306a36Sopenharmony_ci	{ MBC_READ_SFP },
6762306a36Sopenharmony_ci	{ MBC_SET_RNID_PARAMS },
6862306a36Sopenharmony_ci	{ MBC_GET_RNID_PARAMS },
6962306a36Sopenharmony_ci	{ MBC_GET_SET_ZIO_THRESHOLD },
7062306a36Sopenharmony_ci};
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistatic int is_rom_cmd(uint16_t cmd)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	int i;
7562306a36Sopenharmony_ci	struct  rom_cmd *wc;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(rom_cmds); i++) {
7862306a36Sopenharmony_ci		wc = rom_cmds + i;
7962306a36Sopenharmony_ci		if (wc->cmd == cmd)
8062306a36Sopenharmony_ci			return 1;
8162306a36Sopenharmony_ci	}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	return 0;
8462306a36Sopenharmony_ci}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci/*
8762306a36Sopenharmony_ci * qla2x00_mailbox_command
8862306a36Sopenharmony_ci *	Issue mailbox command and waits for completion.
8962306a36Sopenharmony_ci *
9062306a36Sopenharmony_ci * Input:
9162306a36Sopenharmony_ci *	ha = adapter block pointer.
9262306a36Sopenharmony_ci *	mcp = driver internal mbx struct pointer.
9362306a36Sopenharmony_ci *
9462306a36Sopenharmony_ci * Output:
9562306a36Sopenharmony_ci *	mb[MAX_MAILBOX_REGISTER_COUNT] = returned mailbox data.
9662306a36Sopenharmony_ci *
9762306a36Sopenharmony_ci * Returns:
9862306a36Sopenharmony_ci *	0 : QLA_SUCCESS = cmd performed success
9962306a36Sopenharmony_ci *	1 : QLA_FUNCTION_FAILED   (error encountered)
10062306a36Sopenharmony_ci *	6 : QLA_FUNCTION_TIMEOUT (timeout condition encountered)
10162306a36Sopenharmony_ci *
10262306a36Sopenharmony_ci * Context:
10362306a36Sopenharmony_ci *	Kernel context.
10462306a36Sopenharmony_ci */
10562306a36Sopenharmony_cistatic int
10662306a36Sopenharmony_ciqla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	int		rval, i;
10962306a36Sopenharmony_ci	unsigned long    flags = 0;
11062306a36Sopenharmony_ci	device_reg_t *reg;
11162306a36Sopenharmony_ci	uint8_t		abort_active, eeh_delay;
11262306a36Sopenharmony_ci	uint8_t		io_lock_on;
11362306a36Sopenharmony_ci	uint16_t	command = 0;
11462306a36Sopenharmony_ci	uint16_t	*iptr;
11562306a36Sopenharmony_ci	__le16 __iomem  *optr;
11662306a36Sopenharmony_ci	uint32_t	cnt;
11762306a36Sopenharmony_ci	uint32_t	mboxes;
11862306a36Sopenharmony_ci	unsigned long	wait_time;
11962306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
12062306a36Sopenharmony_ci	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
12162306a36Sopenharmony_ci	u32 chip_reset;
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx, vha, 0x1000, "Entered %s.\n", __func__);
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	if (ha->pdev->error_state == pci_channel_io_perm_failure) {
12762306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x1001,
12862306a36Sopenharmony_ci		    "PCI channel failed permanently, exiting.\n");
12962306a36Sopenharmony_ci		return QLA_FUNCTION_TIMEOUT;
13062306a36Sopenharmony_ci	}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	if (vha->device_flags & DFLG_DEV_FAILED) {
13362306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x1002,
13462306a36Sopenharmony_ci		    "Device in failed state, exiting.\n");
13562306a36Sopenharmony_ci		return QLA_FUNCTION_TIMEOUT;
13662306a36Sopenharmony_ci	}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	/* if PCI error, then avoid mbx processing.*/
13962306a36Sopenharmony_ci	if (test_bit(PFLG_DISCONNECTED, &base_vha->dpc_flags) &&
14062306a36Sopenharmony_ci	    test_bit(UNLOADING, &base_vha->dpc_flags)) {
14162306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0xd04e,
14262306a36Sopenharmony_ci		    "PCI error, exiting.\n");
14362306a36Sopenharmony_ci		return QLA_FUNCTION_TIMEOUT;
14462306a36Sopenharmony_ci	}
14562306a36Sopenharmony_ci	eeh_delay = 0;
14662306a36Sopenharmony_ci	reg = ha->iobase;
14762306a36Sopenharmony_ci	io_lock_on = base_vha->flags.init_done;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	rval = QLA_SUCCESS;
15062306a36Sopenharmony_ci	abort_active = test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
15162306a36Sopenharmony_ci	chip_reset = ha->chip_reset;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	if (ha->flags.pci_channel_io_perm_failure) {
15462306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x1003,
15562306a36Sopenharmony_ci		    "Perm failure on EEH timeout MBX, exiting.\n");
15662306a36Sopenharmony_ci		return QLA_FUNCTION_TIMEOUT;
15762306a36Sopenharmony_ci	}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	if (IS_P3P_TYPE(ha) && ha->flags.isp82xx_fw_hung) {
16062306a36Sopenharmony_ci		/* Setting Link-Down error */
16162306a36Sopenharmony_ci		mcp->mb[0] = MBS_LINK_DOWN_ERROR;
16262306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x1004,
16362306a36Sopenharmony_ci		    "FW hung = %d.\n", ha->flags.isp82xx_fw_hung);
16462306a36Sopenharmony_ci		return QLA_FUNCTION_TIMEOUT;
16562306a36Sopenharmony_ci	}
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	/* check if ISP abort is active and return cmd with timeout */
16862306a36Sopenharmony_ci	if (((test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
16962306a36Sopenharmony_ci	      test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
17062306a36Sopenharmony_ci	      test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) &&
17162306a36Sopenharmony_ci	      !is_rom_cmd(mcp->mb[0])) || ha->flags.eeh_busy) {
17262306a36Sopenharmony_ci		ql_log(ql_log_info, vha, 0x1005,
17362306a36Sopenharmony_ci		    "Cmd 0x%x aborted with timeout since ISP Abort is pending\n",
17462306a36Sopenharmony_ci		    mcp->mb[0]);
17562306a36Sopenharmony_ci		return QLA_FUNCTION_TIMEOUT;
17662306a36Sopenharmony_ci	}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	atomic_inc(&ha->num_pend_mbx_stage1);
17962306a36Sopenharmony_ci	/*
18062306a36Sopenharmony_ci	 * Wait for active mailbox commands to finish by waiting at most tov
18162306a36Sopenharmony_ci	 * seconds. This is to serialize actual issuing of mailbox cmds during
18262306a36Sopenharmony_ci	 * non ISP abort time.
18362306a36Sopenharmony_ci	 */
18462306a36Sopenharmony_ci	if (!wait_for_completion_timeout(&ha->mbx_cmd_comp, mcp->tov * HZ)) {
18562306a36Sopenharmony_ci		/* Timeout occurred. Return error. */
18662306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0xd035,
18762306a36Sopenharmony_ci		    "Cmd access timeout, cmd=0x%x, Exiting.\n",
18862306a36Sopenharmony_ci		    mcp->mb[0]);
18962306a36Sopenharmony_ci		vha->hw_err_cnt++;
19062306a36Sopenharmony_ci		atomic_dec(&ha->num_pend_mbx_stage1);
19162306a36Sopenharmony_ci		return QLA_FUNCTION_TIMEOUT;
19262306a36Sopenharmony_ci	}
19362306a36Sopenharmony_ci	atomic_dec(&ha->num_pend_mbx_stage1);
19462306a36Sopenharmony_ci	if (ha->flags.purge_mbox || chip_reset != ha->chip_reset ||
19562306a36Sopenharmony_ci	    ha->flags.eeh_busy) {
19662306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0xd035,
19762306a36Sopenharmony_ci		       "Error detected: purge[%d] eeh[%d] cmd=0x%x, Exiting.\n",
19862306a36Sopenharmony_ci		       ha->flags.purge_mbox, ha->flags.eeh_busy, mcp->mb[0]);
19962306a36Sopenharmony_ci		rval = QLA_ABORTED;
20062306a36Sopenharmony_ci		goto premature_exit;
20162306a36Sopenharmony_ci	}
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	/* Save mailbox command for debug */
20562306a36Sopenharmony_ci	ha->mcp = mcp;
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx, vha, 0x1006,
20862306a36Sopenharmony_ci	    "Prepare to issue mbox cmd=0x%x.\n", mcp->mb[0]);
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	spin_lock_irqsave(&ha->hardware_lock, flags);
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	if (ha->flags.purge_mbox || chip_reset != ha->chip_reset ||
21362306a36Sopenharmony_ci	    ha->flags.mbox_busy) {
21462306a36Sopenharmony_ci		rval = QLA_ABORTED;
21562306a36Sopenharmony_ci		spin_unlock_irqrestore(&ha->hardware_lock, flags);
21662306a36Sopenharmony_ci		goto premature_exit;
21762306a36Sopenharmony_ci	}
21862306a36Sopenharmony_ci	ha->flags.mbox_busy = 1;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	/* Load mailbox registers. */
22162306a36Sopenharmony_ci	if (IS_P3P_TYPE(ha))
22262306a36Sopenharmony_ci		optr = &reg->isp82.mailbox_in[0];
22362306a36Sopenharmony_ci	else if (IS_FWI2_CAPABLE(ha) && !(IS_P3P_TYPE(ha)))
22462306a36Sopenharmony_ci		optr = &reg->isp24.mailbox0;
22562306a36Sopenharmony_ci	else
22662306a36Sopenharmony_ci		optr = MAILBOX_REG(ha, &reg->isp, 0);
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	iptr = mcp->mb;
22962306a36Sopenharmony_ci	command = mcp->mb[0];
23062306a36Sopenharmony_ci	mboxes = mcp->out_mb;
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx, vha, 0x1111,
23362306a36Sopenharmony_ci	    "Mailbox registers (OUT):\n");
23462306a36Sopenharmony_ci	for (cnt = 0; cnt < ha->mbx_count; cnt++) {
23562306a36Sopenharmony_ci		if (IS_QLA2200(ha) && cnt == 8)
23662306a36Sopenharmony_ci			optr = MAILBOX_REG(ha, &reg->isp, 8);
23762306a36Sopenharmony_ci		if (mboxes & BIT_0) {
23862306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x1112,
23962306a36Sopenharmony_ci			    "mbox[%d]<-0x%04x\n", cnt, *iptr);
24062306a36Sopenharmony_ci			wrt_reg_word(optr, *iptr);
24162306a36Sopenharmony_ci		} else {
24262306a36Sopenharmony_ci			wrt_reg_word(optr, 0);
24362306a36Sopenharmony_ci		}
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci		mboxes >>= 1;
24662306a36Sopenharmony_ci		optr++;
24762306a36Sopenharmony_ci		iptr++;
24862306a36Sopenharmony_ci	}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1117,
25162306a36Sopenharmony_ci	    "I/O Address = %p.\n", optr);
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	/* Issue set host interrupt command to send cmd out. */
25462306a36Sopenharmony_ci	ha->flags.mbox_int = 0;
25562306a36Sopenharmony_ci	clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	/* Unlock mbx registers and wait for interrupt */
25862306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx, vha, 0x100f,
25962306a36Sopenharmony_ci	    "Going to unlock irq & waiting for interrupts. "
26062306a36Sopenharmony_ci	    "jiffies=%lx.\n", jiffies);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	/* Wait for mbx cmd completion until timeout */
26362306a36Sopenharmony_ci	atomic_inc(&ha->num_pend_mbx_stage2);
26462306a36Sopenharmony_ci	if ((!abort_active && io_lock_on) || IS_NOPOLLING_TYPE(ha)) {
26562306a36Sopenharmony_ci		set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci		if (IS_P3P_TYPE(ha))
26862306a36Sopenharmony_ci			wrt_reg_dword(&reg->isp82.hint, HINT_MBX_INT_PENDING);
26962306a36Sopenharmony_ci		else if (IS_FWI2_CAPABLE(ha))
27062306a36Sopenharmony_ci			wrt_reg_dword(&reg->isp24.hccr, HCCRX_SET_HOST_INT);
27162306a36Sopenharmony_ci		else
27262306a36Sopenharmony_ci			wrt_reg_word(&reg->isp.hccr, HCCR_SET_HOST_INT);
27362306a36Sopenharmony_ci		spin_unlock_irqrestore(&ha->hardware_lock, flags);
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci		wait_time = jiffies;
27662306a36Sopenharmony_ci		if (!wait_for_completion_timeout(&ha->mbx_intr_comp,
27762306a36Sopenharmony_ci		    mcp->tov * HZ)) {
27862306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x117a,
27962306a36Sopenharmony_ci			    "cmd=%x Timeout.\n", command);
28062306a36Sopenharmony_ci			spin_lock_irqsave(&ha->hardware_lock, flags);
28162306a36Sopenharmony_ci			clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
28262306a36Sopenharmony_ci			spin_unlock_irqrestore(&ha->hardware_lock, flags);
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci			if (chip_reset != ha->chip_reset) {
28562306a36Sopenharmony_ci				eeh_delay = ha->flags.eeh_busy ? 1 : 0;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci				spin_lock_irqsave(&ha->hardware_lock, flags);
28862306a36Sopenharmony_ci				ha->flags.mbox_busy = 0;
28962306a36Sopenharmony_ci				spin_unlock_irqrestore(&ha->hardware_lock,
29062306a36Sopenharmony_ci				    flags);
29162306a36Sopenharmony_ci				atomic_dec(&ha->num_pend_mbx_stage2);
29262306a36Sopenharmony_ci				rval = QLA_ABORTED;
29362306a36Sopenharmony_ci				goto premature_exit;
29462306a36Sopenharmony_ci			}
29562306a36Sopenharmony_ci		} else if (ha->flags.purge_mbox ||
29662306a36Sopenharmony_ci		    chip_reset != ha->chip_reset) {
29762306a36Sopenharmony_ci			eeh_delay = ha->flags.eeh_busy ? 1 : 0;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci			spin_lock_irqsave(&ha->hardware_lock, flags);
30062306a36Sopenharmony_ci			ha->flags.mbox_busy = 0;
30162306a36Sopenharmony_ci			spin_unlock_irqrestore(&ha->hardware_lock, flags);
30262306a36Sopenharmony_ci			atomic_dec(&ha->num_pend_mbx_stage2);
30362306a36Sopenharmony_ci			rval = QLA_ABORTED;
30462306a36Sopenharmony_ci			goto premature_exit;
30562306a36Sopenharmony_ci		}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci		if (time_after(jiffies, wait_time + 5 * HZ))
30862306a36Sopenharmony_ci			ql_log(ql_log_warn, vha, 0x1015, "cmd=0x%x, waited %d msecs\n",
30962306a36Sopenharmony_ci			    command, jiffies_to_msecs(jiffies - wait_time));
31062306a36Sopenharmony_ci	} else {
31162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1011,
31262306a36Sopenharmony_ci		    "Cmd=%x Polling Mode.\n", command);
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci		if (IS_P3P_TYPE(ha)) {
31562306a36Sopenharmony_ci			if (rd_reg_dword(&reg->isp82.hint) &
31662306a36Sopenharmony_ci				HINT_MBX_INT_PENDING) {
31762306a36Sopenharmony_ci				ha->flags.mbox_busy = 0;
31862306a36Sopenharmony_ci				spin_unlock_irqrestore(&ha->hardware_lock,
31962306a36Sopenharmony_ci					flags);
32062306a36Sopenharmony_ci				atomic_dec(&ha->num_pend_mbx_stage2);
32162306a36Sopenharmony_ci				ql_dbg(ql_dbg_mbx, vha, 0x1012,
32262306a36Sopenharmony_ci				    "Pending mailbox timeout, exiting.\n");
32362306a36Sopenharmony_ci				vha->hw_err_cnt++;
32462306a36Sopenharmony_ci				rval = QLA_FUNCTION_TIMEOUT;
32562306a36Sopenharmony_ci				goto premature_exit;
32662306a36Sopenharmony_ci			}
32762306a36Sopenharmony_ci			wrt_reg_dword(&reg->isp82.hint, HINT_MBX_INT_PENDING);
32862306a36Sopenharmony_ci		} else if (IS_FWI2_CAPABLE(ha))
32962306a36Sopenharmony_ci			wrt_reg_dword(&reg->isp24.hccr, HCCRX_SET_HOST_INT);
33062306a36Sopenharmony_ci		else
33162306a36Sopenharmony_ci			wrt_reg_word(&reg->isp.hccr, HCCR_SET_HOST_INT);
33262306a36Sopenharmony_ci		spin_unlock_irqrestore(&ha->hardware_lock, flags);
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci		wait_time = jiffies + mcp->tov * HZ; /* wait at most tov secs */
33562306a36Sopenharmony_ci		while (!ha->flags.mbox_int) {
33662306a36Sopenharmony_ci			if (ha->flags.purge_mbox ||
33762306a36Sopenharmony_ci			    chip_reset != ha->chip_reset) {
33862306a36Sopenharmony_ci				eeh_delay = ha->flags.eeh_busy ? 1 : 0;
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci				spin_lock_irqsave(&ha->hardware_lock, flags);
34162306a36Sopenharmony_ci				ha->flags.mbox_busy = 0;
34262306a36Sopenharmony_ci				spin_unlock_irqrestore(&ha->hardware_lock,
34362306a36Sopenharmony_ci				    flags);
34462306a36Sopenharmony_ci				atomic_dec(&ha->num_pend_mbx_stage2);
34562306a36Sopenharmony_ci				rval = QLA_ABORTED;
34662306a36Sopenharmony_ci				goto premature_exit;
34762306a36Sopenharmony_ci			}
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci			if (time_after(jiffies, wait_time))
35062306a36Sopenharmony_ci				break;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci			/* Check for pending interrupts. */
35362306a36Sopenharmony_ci			qla2x00_poll(ha->rsp_q_map[0]);
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci			if (!ha->flags.mbox_int &&
35662306a36Sopenharmony_ci			    !(IS_QLA2200(ha) &&
35762306a36Sopenharmony_ci			    command == MBC_LOAD_RISC_RAM_EXTENDED))
35862306a36Sopenharmony_ci				msleep(10);
35962306a36Sopenharmony_ci		} /* while */
36062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1013,
36162306a36Sopenharmony_ci		    "Waited %d sec.\n",
36262306a36Sopenharmony_ci		    (uint)((jiffies - (wait_time - (mcp->tov * HZ)))/HZ));
36362306a36Sopenharmony_ci	}
36462306a36Sopenharmony_ci	atomic_dec(&ha->num_pend_mbx_stage2);
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	/* Check whether we timed out */
36762306a36Sopenharmony_ci	if (ha->flags.mbox_int) {
36862306a36Sopenharmony_ci		uint16_t *iptr2;
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1014,
37162306a36Sopenharmony_ci		    "Cmd=%x completed.\n", command);
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci		/* Got interrupt. Clear the flag. */
37462306a36Sopenharmony_ci		ha->flags.mbox_int = 0;
37562306a36Sopenharmony_ci		clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci		if (IS_P3P_TYPE(ha) && ha->flags.isp82xx_fw_hung) {
37862306a36Sopenharmony_ci			spin_lock_irqsave(&ha->hardware_lock, flags);
37962306a36Sopenharmony_ci			ha->flags.mbox_busy = 0;
38062306a36Sopenharmony_ci			spin_unlock_irqrestore(&ha->hardware_lock, flags);
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci			/* Setting Link-Down error */
38362306a36Sopenharmony_ci			mcp->mb[0] = MBS_LINK_DOWN_ERROR;
38462306a36Sopenharmony_ci			ha->mcp = NULL;
38562306a36Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
38662306a36Sopenharmony_ci			ql_log(ql_log_warn, vha, 0xd048,
38762306a36Sopenharmony_ci			    "FW hung = %d.\n", ha->flags.isp82xx_fw_hung);
38862306a36Sopenharmony_ci			goto premature_exit;
38962306a36Sopenharmony_ci		}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci		if (ha->mailbox_out[0] != MBS_COMMAND_COMPLETE) {
39262306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x11ff,
39362306a36Sopenharmony_ci			       "mb_out[0] = %#x <> %#x\n", ha->mailbox_out[0],
39462306a36Sopenharmony_ci			       MBS_COMMAND_COMPLETE);
39562306a36Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
39662306a36Sopenharmony_ci		}
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci		/* Load return mailbox registers. */
39962306a36Sopenharmony_ci		iptr2 = mcp->mb;
40062306a36Sopenharmony_ci		iptr = (uint16_t *)&ha->mailbox_out[0];
40162306a36Sopenharmony_ci		mboxes = mcp->in_mb;
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1113,
40462306a36Sopenharmony_ci		    "Mailbox registers (IN):\n");
40562306a36Sopenharmony_ci		for (cnt = 0; cnt < ha->mbx_count; cnt++) {
40662306a36Sopenharmony_ci			if (mboxes & BIT_0) {
40762306a36Sopenharmony_ci				*iptr2 = *iptr;
40862306a36Sopenharmony_ci				ql_dbg(ql_dbg_mbx, vha, 0x1114,
40962306a36Sopenharmony_ci				    "mbox[%d]->0x%04x\n", cnt, *iptr2);
41062306a36Sopenharmony_ci			}
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci			mboxes >>= 1;
41362306a36Sopenharmony_ci			iptr2++;
41462306a36Sopenharmony_ci			iptr++;
41562306a36Sopenharmony_ci		}
41662306a36Sopenharmony_ci	} else {
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci		uint16_t mb[8];
41962306a36Sopenharmony_ci		uint32_t ictrl, host_status, hccr;
42062306a36Sopenharmony_ci		uint16_t        w;
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci		if (IS_FWI2_CAPABLE(ha)) {
42362306a36Sopenharmony_ci			mb[0] = rd_reg_word(&reg->isp24.mailbox0);
42462306a36Sopenharmony_ci			mb[1] = rd_reg_word(&reg->isp24.mailbox1);
42562306a36Sopenharmony_ci			mb[2] = rd_reg_word(&reg->isp24.mailbox2);
42662306a36Sopenharmony_ci			mb[3] = rd_reg_word(&reg->isp24.mailbox3);
42762306a36Sopenharmony_ci			mb[7] = rd_reg_word(&reg->isp24.mailbox7);
42862306a36Sopenharmony_ci			ictrl = rd_reg_dword(&reg->isp24.ictrl);
42962306a36Sopenharmony_ci			host_status = rd_reg_dword(&reg->isp24.host_status);
43062306a36Sopenharmony_ci			hccr = rd_reg_dword(&reg->isp24.hccr);
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci			ql_log(ql_log_warn, vha, 0xd04c,
43362306a36Sopenharmony_ci			    "MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx "
43462306a36Sopenharmony_ci			    "mb[0-3]=[0x%x 0x%x 0x%x 0x%x] mb7 0x%x host_status 0x%x hccr 0x%x\n",
43562306a36Sopenharmony_ci			    command, ictrl, jiffies, mb[0], mb[1], mb[2], mb[3],
43662306a36Sopenharmony_ci			    mb[7], host_status, hccr);
43762306a36Sopenharmony_ci			vha->hw_err_cnt++;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci		} else {
44062306a36Sopenharmony_ci			mb[0] = RD_MAILBOX_REG(ha, &reg->isp, 0);
44162306a36Sopenharmony_ci			ictrl = rd_reg_word(&reg->isp.ictrl);
44262306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1119,
44362306a36Sopenharmony_ci			    "MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx "
44462306a36Sopenharmony_ci			    "mb[0]=0x%x\n", command, ictrl, jiffies, mb[0]);
44562306a36Sopenharmony_ci			vha->hw_err_cnt++;
44662306a36Sopenharmony_ci		}
44762306a36Sopenharmony_ci		ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1019);
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci		/* Capture FW dump only, if PCI device active */
45062306a36Sopenharmony_ci		if (!pci_channel_offline(vha->hw->pdev)) {
45162306a36Sopenharmony_ci			pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
45262306a36Sopenharmony_ci			if (w == 0xffff || ictrl == 0xffffffff ||
45362306a36Sopenharmony_ci			    (chip_reset != ha->chip_reset)) {
45462306a36Sopenharmony_ci				/* This is special case if there is unload
45562306a36Sopenharmony_ci				 * of driver happening and if PCI device go
45662306a36Sopenharmony_ci				 * into bad state due to PCI error condition
45762306a36Sopenharmony_ci				 * then only PCI ERR flag would be set.
45862306a36Sopenharmony_ci				 * we will do premature exit for above case.
45962306a36Sopenharmony_ci				 */
46062306a36Sopenharmony_ci				spin_lock_irqsave(&ha->hardware_lock, flags);
46162306a36Sopenharmony_ci				ha->flags.mbox_busy = 0;
46262306a36Sopenharmony_ci				spin_unlock_irqrestore(&ha->hardware_lock,
46362306a36Sopenharmony_ci				    flags);
46462306a36Sopenharmony_ci				rval = QLA_FUNCTION_TIMEOUT;
46562306a36Sopenharmony_ci				goto premature_exit;
46662306a36Sopenharmony_ci			}
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci			/* Attempt to capture firmware dump for further
46962306a36Sopenharmony_ci			 * anallysis of the current formware state. we do not
47062306a36Sopenharmony_ci			 * need to do this if we are intentionally generating
47162306a36Sopenharmony_ci			 * a dump
47262306a36Sopenharmony_ci			 */
47362306a36Sopenharmony_ci			if (mcp->mb[0] != MBC_GEN_SYSTEM_ERROR)
47462306a36Sopenharmony_ci				qla2xxx_dump_fw(vha);
47562306a36Sopenharmony_ci			rval = QLA_FUNCTION_TIMEOUT;
47662306a36Sopenharmony_ci		 }
47762306a36Sopenharmony_ci	}
47862306a36Sopenharmony_ci	spin_lock_irqsave(&ha->hardware_lock, flags);
47962306a36Sopenharmony_ci	ha->flags.mbox_busy = 0;
48062306a36Sopenharmony_ci	spin_unlock_irqrestore(&ha->hardware_lock, flags);
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	/* Clean up */
48362306a36Sopenharmony_ci	ha->mcp = NULL;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	if ((abort_active || !io_lock_on) && !IS_NOPOLLING_TYPE(ha)) {
48662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x101a,
48762306a36Sopenharmony_ci		    "Checking for additional resp interrupt.\n");
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci		/* polling mode for non isp_abort commands. */
49062306a36Sopenharmony_ci		qla2x00_poll(ha->rsp_q_map[0]);
49162306a36Sopenharmony_ci	}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	if (rval == QLA_FUNCTION_TIMEOUT &&
49462306a36Sopenharmony_ci	    mcp->mb[0] != MBC_GEN_SYSTEM_ERROR) {
49562306a36Sopenharmony_ci		if (!io_lock_on || (mcp->flags & IOCTL_CMD) ||
49662306a36Sopenharmony_ci		    ha->flags.eeh_busy) {
49762306a36Sopenharmony_ci			/* not in dpc. schedule it for dpc to take over. */
49862306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x101b,
49962306a36Sopenharmony_ci			    "Timeout, schedule isp_abort_needed.\n");
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci			if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) &&
50262306a36Sopenharmony_ci			    !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
50362306a36Sopenharmony_ci			    !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
50462306a36Sopenharmony_ci				if (IS_QLA82XX(ha)) {
50562306a36Sopenharmony_ci					ql_dbg(ql_dbg_mbx, vha, 0x112a,
50662306a36Sopenharmony_ci					    "disabling pause transmit on port "
50762306a36Sopenharmony_ci					    "0 & 1.\n");
50862306a36Sopenharmony_ci					qla82xx_wr_32(ha,
50962306a36Sopenharmony_ci					    QLA82XX_CRB_NIU + 0x98,
51062306a36Sopenharmony_ci					    CRB_NIU_XG_PAUSE_CTL_P0|
51162306a36Sopenharmony_ci					    CRB_NIU_XG_PAUSE_CTL_P1);
51262306a36Sopenharmony_ci				}
51362306a36Sopenharmony_ci				ql_log(ql_log_info, base_vha, 0x101c,
51462306a36Sopenharmony_ci				    "Mailbox cmd timeout occurred, cmd=0x%x, "
51562306a36Sopenharmony_ci				    "mb[0]=0x%x, eeh_busy=0x%x. Scheduling ISP "
51662306a36Sopenharmony_ci				    "abort.\n", command, mcp->mb[0],
51762306a36Sopenharmony_ci				    ha->flags.eeh_busy);
51862306a36Sopenharmony_ci				vha->hw_err_cnt++;
51962306a36Sopenharmony_ci				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
52062306a36Sopenharmony_ci				qla2xxx_wake_dpc(vha);
52162306a36Sopenharmony_ci			}
52262306a36Sopenharmony_ci		} else if (current == ha->dpc_thread) {
52362306a36Sopenharmony_ci			/* call abort directly since we are in the DPC thread */
52462306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x101d,
52562306a36Sopenharmony_ci			    "Timeout, calling abort_isp.\n");
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci			if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) &&
52862306a36Sopenharmony_ci			    !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
52962306a36Sopenharmony_ci			    !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
53062306a36Sopenharmony_ci				if (IS_QLA82XX(ha)) {
53162306a36Sopenharmony_ci					ql_dbg(ql_dbg_mbx, vha, 0x112b,
53262306a36Sopenharmony_ci					    "disabling pause transmit on port "
53362306a36Sopenharmony_ci					    "0 & 1.\n");
53462306a36Sopenharmony_ci					qla82xx_wr_32(ha,
53562306a36Sopenharmony_ci					    QLA82XX_CRB_NIU + 0x98,
53662306a36Sopenharmony_ci					    CRB_NIU_XG_PAUSE_CTL_P0|
53762306a36Sopenharmony_ci					    CRB_NIU_XG_PAUSE_CTL_P1);
53862306a36Sopenharmony_ci				}
53962306a36Sopenharmony_ci				ql_log(ql_log_info, base_vha, 0x101e,
54062306a36Sopenharmony_ci				    "Mailbox cmd timeout occurred, cmd=0x%x, "
54162306a36Sopenharmony_ci				    "mb[0]=0x%x. Scheduling ISP abort ",
54262306a36Sopenharmony_ci				    command, mcp->mb[0]);
54362306a36Sopenharmony_ci				vha->hw_err_cnt++;
54462306a36Sopenharmony_ci				set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
54562306a36Sopenharmony_ci				clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
54662306a36Sopenharmony_ci				/* Allow next mbx cmd to come in. */
54762306a36Sopenharmony_ci				complete(&ha->mbx_cmd_comp);
54862306a36Sopenharmony_ci				if (ha->isp_ops->abort_isp(vha) &&
54962306a36Sopenharmony_ci				    !ha->flags.eeh_busy) {
55062306a36Sopenharmony_ci					/* Failed. retry later. */
55162306a36Sopenharmony_ci					set_bit(ISP_ABORT_NEEDED,
55262306a36Sopenharmony_ci					    &vha->dpc_flags);
55362306a36Sopenharmony_ci				}
55462306a36Sopenharmony_ci				clear_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
55562306a36Sopenharmony_ci				ql_dbg(ql_dbg_mbx, vha, 0x101f,
55662306a36Sopenharmony_ci				    "Finished abort_isp.\n");
55762306a36Sopenharmony_ci				goto mbx_done;
55862306a36Sopenharmony_ci			}
55962306a36Sopenharmony_ci		}
56062306a36Sopenharmony_ci	}
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_cipremature_exit:
56362306a36Sopenharmony_ci	/* Allow next mbx cmd to come in. */
56462306a36Sopenharmony_ci	complete(&ha->mbx_cmd_comp);
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_cimbx_done:
56762306a36Sopenharmony_ci	if (rval == QLA_ABORTED) {
56862306a36Sopenharmony_ci		ql_log(ql_log_info, vha, 0xd035,
56962306a36Sopenharmony_ci		    "Chip Reset in progress. Purging Mbox cmd=0x%x.\n",
57062306a36Sopenharmony_ci		    mcp->mb[0]);
57162306a36Sopenharmony_ci	} else if (rval) {
57262306a36Sopenharmony_ci		if (ql2xextended_error_logging & (ql_dbg_disc|ql_dbg_mbx)) {
57362306a36Sopenharmony_ci			pr_warn("%s [%s]-%04x:%ld: **** Failed=%x", QL_MSGHDR,
57462306a36Sopenharmony_ci			    dev_name(&ha->pdev->dev), 0x1020+0x800,
57562306a36Sopenharmony_ci			    vha->host_no, rval);
57662306a36Sopenharmony_ci			mboxes = mcp->in_mb;
57762306a36Sopenharmony_ci			cnt = 4;
57862306a36Sopenharmony_ci			for (i = 0; i < ha->mbx_count && cnt; i++, mboxes >>= 1)
57962306a36Sopenharmony_ci				if (mboxes & BIT_0) {
58062306a36Sopenharmony_ci					printk(" mb[%u]=%x", i, mcp->mb[i]);
58162306a36Sopenharmony_ci					cnt--;
58262306a36Sopenharmony_ci				}
58362306a36Sopenharmony_ci			pr_warn(" cmd=%x ****\n", command);
58462306a36Sopenharmony_ci		}
58562306a36Sopenharmony_ci		if (IS_FWI2_CAPABLE(ha) && !(IS_P3P_TYPE(ha))) {
58662306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x1198,
58762306a36Sopenharmony_ci			    "host_status=%#x intr_ctrl=%#x intr_status=%#x\n",
58862306a36Sopenharmony_ci			    rd_reg_dword(&reg->isp24.host_status),
58962306a36Sopenharmony_ci			    rd_reg_dword(&reg->isp24.ictrl),
59062306a36Sopenharmony_ci			    rd_reg_dword(&reg->isp24.istatus));
59162306a36Sopenharmony_ci		} else {
59262306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x1206,
59362306a36Sopenharmony_ci			    "ctrl_status=%#x ictrl=%#x istatus=%#x\n",
59462306a36Sopenharmony_ci			    rd_reg_word(&reg->isp.ctrl_status),
59562306a36Sopenharmony_ci			    rd_reg_word(&reg->isp.ictrl),
59662306a36Sopenharmony_ci			    rd_reg_word(&reg->isp.istatus));
59762306a36Sopenharmony_ci		}
59862306a36Sopenharmony_ci	} else {
59962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, base_vha, 0x1021, "Done %s.\n", __func__);
60062306a36Sopenharmony_ci	}
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	i = 500;
60362306a36Sopenharmony_ci	while (i && eeh_delay && (ha->pci_error_state < QLA_PCI_SLOT_RESET)) {
60462306a36Sopenharmony_ci		/*
60562306a36Sopenharmony_ci		 * The caller of this mailbox encounter pci error.
60662306a36Sopenharmony_ci		 * Hold the thread until PCIE link reset complete to make
60762306a36Sopenharmony_ci		 * sure caller does not unmap dma while recovery is
60862306a36Sopenharmony_ci		 * in progress.
60962306a36Sopenharmony_ci		 */
61062306a36Sopenharmony_ci		msleep(1);
61162306a36Sopenharmony_ci		i--;
61262306a36Sopenharmony_ci	}
61362306a36Sopenharmony_ci	return rval;
61462306a36Sopenharmony_ci}
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ciint
61762306a36Sopenharmony_ciqla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr,
61862306a36Sopenharmony_ci    uint32_t risc_code_size)
61962306a36Sopenharmony_ci{
62062306a36Sopenharmony_ci	int rval;
62162306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
62262306a36Sopenharmony_ci	mbx_cmd_t mc;
62362306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1022,
62662306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	if (MSW(risc_addr) || IS_FWI2_CAPABLE(ha)) {
62962306a36Sopenharmony_ci		mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
63062306a36Sopenharmony_ci		mcp->mb[8] = MSW(risc_addr);
63162306a36Sopenharmony_ci		mcp->out_mb = MBX_8|MBX_0;
63262306a36Sopenharmony_ci	} else {
63362306a36Sopenharmony_ci		mcp->mb[0] = MBC_LOAD_RISC_RAM;
63462306a36Sopenharmony_ci		mcp->out_mb = MBX_0;
63562306a36Sopenharmony_ci	}
63662306a36Sopenharmony_ci	mcp->mb[1] = LSW(risc_addr);
63762306a36Sopenharmony_ci	mcp->mb[2] = MSW(req_dma);
63862306a36Sopenharmony_ci	mcp->mb[3] = LSW(req_dma);
63962306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(req_dma));
64062306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(req_dma));
64162306a36Sopenharmony_ci	mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1;
64262306a36Sopenharmony_ci	if (IS_FWI2_CAPABLE(ha)) {
64362306a36Sopenharmony_ci		mcp->mb[4] = MSW(risc_code_size);
64462306a36Sopenharmony_ci		mcp->mb[5] = LSW(risc_code_size);
64562306a36Sopenharmony_ci		mcp->out_mb |= MBX_5|MBX_4;
64662306a36Sopenharmony_ci	} else {
64762306a36Sopenharmony_ci		mcp->mb[4] = LSW(risc_code_size);
64862306a36Sopenharmony_ci		mcp->out_mb |= MBX_4;
64962306a36Sopenharmony_ci	}
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
65262306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
65362306a36Sopenharmony_ci	mcp->flags = 0;
65462306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
65762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1023,
65862306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x.\n",
65962306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1]);
66062306a36Sopenharmony_ci		vha->hw_err_cnt++;
66162306a36Sopenharmony_ci	} else {
66262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1024,
66362306a36Sopenharmony_ci		    "Done %s.\n", __func__);
66462306a36Sopenharmony_ci	}
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	return rval;
66762306a36Sopenharmony_ci}
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci#define	NVME_ENABLE_FLAG	BIT_3
67062306a36Sopenharmony_ci#define	EDIF_HW_SUPPORT		BIT_10
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci/*
67362306a36Sopenharmony_ci * qla2x00_execute_fw
67462306a36Sopenharmony_ci *     Start adapter firmware.
67562306a36Sopenharmony_ci *
67662306a36Sopenharmony_ci * Input:
67762306a36Sopenharmony_ci *     ha = adapter block pointer.
67862306a36Sopenharmony_ci *     TARGET_QUEUE_LOCK must be released.
67962306a36Sopenharmony_ci *     ADAPTER_STATE_LOCK must be released.
68062306a36Sopenharmony_ci *
68162306a36Sopenharmony_ci * Returns:
68262306a36Sopenharmony_ci *     qla2x00 local function return status code.
68362306a36Sopenharmony_ci *
68462306a36Sopenharmony_ci * Context:
68562306a36Sopenharmony_ci *     Kernel context.
68662306a36Sopenharmony_ci */
68762306a36Sopenharmony_ciint
68862306a36Sopenharmony_ciqla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
68962306a36Sopenharmony_ci{
69062306a36Sopenharmony_ci	int rval;
69162306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
69262306a36Sopenharmony_ci	mbx_cmd_t mc;
69362306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
69462306a36Sopenharmony_ci	u8 semaphore = 0;
69562306a36Sopenharmony_ci#define EXE_FW_FORCE_SEMAPHORE BIT_7
69662306a36Sopenharmony_ci	u8 retry = 5;
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1025,
69962306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ciagain:
70262306a36Sopenharmony_ci	mcp->mb[0] = MBC_EXECUTE_FIRMWARE;
70362306a36Sopenharmony_ci	mcp->out_mb = MBX_0;
70462306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
70562306a36Sopenharmony_ci	if (IS_FWI2_CAPABLE(ha)) {
70662306a36Sopenharmony_ci		mcp->mb[1] = MSW(risc_addr);
70762306a36Sopenharmony_ci		mcp->mb[2] = LSW(risc_addr);
70862306a36Sopenharmony_ci		mcp->mb[3] = 0;
70962306a36Sopenharmony_ci		mcp->mb[4] = 0;
71062306a36Sopenharmony_ci		mcp->mb[11] = 0;
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci		/* Enable BPM? */
71362306a36Sopenharmony_ci		if (ha->flags.lr_detected) {
71462306a36Sopenharmony_ci			mcp->mb[4] = BIT_0;
71562306a36Sopenharmony_ci			if (IS_BPM_RANGE_CAPABLE(ha))
71662306a36Sopenharmony_ci				mcp->mb[4] |=
71762306a36Sopenharmony_ci				    ha->lr_distance << LR_DIST_FW_POS;
71862306a36Sopenharmony_ci		}
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci		if (ql2xnvmeenable && (IS_QLA27XX(ha) || IS_QLA28XX(ha)))
72162306a36Sopenharmony_ci			mcp->mb[4] |= NVME_ENABLE_FLAG;
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_ci		if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
72462306a36Sopenharmony_ci			struct nvram_81xx *nv = ha->nvram;
72562306a36Sopenharmony_ci			/* set minimum speed if specified in nvram */
72662306a36Sopenharmony_ci			if (nv->min_supported_speed >= 2 &&
72762306a36Sopenharmony_ci			    nv->min_supported_speed <= 5) {
72862306a36Sopenharmony_ci				mcp->mb[4] |= BIT_4;
72962306a36Sopenharmony_ci				mcp->mb[11] |= nv->min_supported_speed & 0xF;
73062306a36Sopenharmony_ci				mcp->out_mb |= MBX_11;
73162306a36Sopenharmony_ci				mcp->in_mb |= BIT_5;
73262306a36Sopenharmony_ci				vha->min_supported_speed =
73362306a36Sopenharmony_ci				    nv->min_supported_speed;
73462306a36Sopenharmony_ci			}
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci			if (IS_PPCARCH)
73762306a36Sopenharmony_ci				mcp->mb[11] |= BIT_4;
73862306a36Sopenharmony_ci		}
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci		if (ha->flags.exlogins_enabled)
74162306a36Sopenharmony_ci			mcp->mb[4] |= ENABLE_EXTENDED_LOGIN;
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci		if (ha->flags.exchoffld_enabled)
74462306a36Sopenharmony_ci			mcp->mb[4] |= ENABLE_EXCHANGE_OFFLD;
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci		if (semaphore)
74762306a36Sopenharmony_ci			mcp->mb[11] |= EXE_FW_FORCE_SEMAPHORE;
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci		mcp->out_mb |= MBX_4 | MBX_3 | MBX_2 | MBX_1 | MBX_11;
75062306a36Sopenharmony_ci		mcp->in_mb |= MBX_5 | MBX_3 | MBX_2 | MBX_1;
75162306a36Sopenharmony_ci	} else {
75262306a36Sopenharmony_ci		mcp->mb[1] = LSW(risc_addr);
75362306a36Sopenharmony_ci		mcp->out_mb |= MBX_1;
75462306a36Sopenharmony_ci		if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
75562306a36Sopenharmony_ci			mcp->mb[2] = 0;
75662306a36Sopenharmony_ci			mcp->out_mb |= MBX_2;
75762306a36Sopenharmony_ci		}
75862306a36Sopenharmony_ci	}
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
76162306a36Sopenharmony_ci	mcp->flags = 0;
76262306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
76562306a36Sopenharmony_ci		if (IS_QLA28XX(ha) && rval == QLA_COMMAND_ERROR &&
76662306a36Sopenharmony_ci		    mcp->mb[1] == 0x27 && retry) {
76762306a36Sopenharmony_ci			semaphore = 1;
76862306a36Sopenharmony_ci			retry--;
76962306a36Sopenharmony_ci			ql_dbg(ql_dbg_async, vha, 0x1026,
77062306a36Sopenharmony_ci			    "Exe FW: force semaphore.\n");
77162306a36Sopenharmony_ci			goto again;
77262306a36Sopenharmony_ci		}
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci		if (retry) {
77562306a36Sopenharmony_ci			retry--;
77662306a36Sopenharmony_ci			ql_dbg(ql_dbg_async, vha, 0x509d,
77762306a36Sopenharmony_ci			    "Exe FW retry: mb[0]=%x retry[%d]\n", mcp->mb[0], retry);
77862306a36Sopenharmony_ci			goto again;
77962306a36Sopenharmony_ci		}
78062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1026,
78162306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
78262306a36Sopenharmony_ci		vha->hw_err_cnt++;
78362306a36Sopenharmony_ci		return rval;
78462306a36Sopenharmony_ci	}
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	if (!IS_FWI2_CAPABLE(ha))
78762306a36Sopenharmony_ci		goto done;
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci	ha->fw_ability_mask = mcp->mb[3] << 16 | mcp->mb[2];
79062306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx, vha, 0x119a,
79162306a36Sopenharmony_ci	    "fw_ability_mask=%x.\n", ha->fw_ability_mask);
79262306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx, vha, 0x1027, "exchanges=%x.\n", mcp->mb[1]);
79362306a36Sopenharmony_ci	if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
79462306a36Sopenharmony_ci		ha->max_supported_speed = mcp->mb[2] & (BIT_0|BIT_1);
79562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x119b, "max_supported_speed=%s.\n",
79662306a36Sopenharmony_ci		    ha->max_supported_speed == 0 ? "16Gps" :
79762306a36Sopenharmony_ci		    ha->max_supported_speed == 1 ? "32Gps" :
79862306a36Sopenharmony_ci		    ha->max_supported_speed == 2 ? "64Gps" : "unknown");
79962306a36Sopenharmony_ci		if (vha->min_supported_speed) {
80062306a36Sopenharmony_ci			ha->min_supported_speed = mcp->mb[5] &
80162306a36Sopenharmony_ci			    (BIT_0 | BIT_1 | BIT_2);
80262306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x119c,
80362306a36Sopenharmony_ci			    "min_supported_speed=%s.\n",
80462306a36Sopenharmony_ci			    ha->min_supported_speed == 6 ? "64Gps" :
80562306a36Sopenharmony_ci			    ha->min_supported_speed == 5 ? "32Gps" :
80662306a36Sopenharmony_ci			    ha->min_supported_speed == 4 ? "16Gps" :
80762306a36Sopenharmony_ci			    ha->min_supported_speed == 3 ? "8Gps" :
80862306a36Sopenharmony_ci			    ha->min_supported_speed == 2 ? "4Gps" : "unknown");
80962306a36Sopenharmony_ci		}
81062306a36Sopenharmony_ci	}
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci	if (IS_QLA28XX(ha) && (mcp->mb[5] & EDIF_HW_SUPPORT)) {
81362306a36Sopenharmony_ci		ha->flags.edif_hw = 1;
81462306a36Sopenharmony_ci		ql_log(ql_log_info, vha, 0xffff,
81562306a36Sopenharmony_ci		    "%s: edif HW\n", __func__);
81662306a36Sopenharmony_ci	}
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_cidone:
81962306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1028,
82062306a36Sopenharmony_ci	    "Done %s.\n", __func__);
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci	return rval;
82362306a36Sopenharmony_ci}
82462306a36Sopenharmony_ci
82562306a36Sopenharmony_ci/*
82662306a36Sopenharmony_ci * qla_get_exlogin_status
82762306a36Sopenharmony_ci *	Get extended login status
82862306a36Sopenharmony_ci *	uses the memory offload control/status Mailbox
82962306a36Sopenharmony_ci *
83062306a36Sopenharmony_ci * Input:
83162306a36Sopenharmony_ci *	ha:		adapter state pointer.
83262306a36Sopenharmony_ci *	fwopt:		firmware options
83362306a36Sopenharmony_ci *
83462306a36Sopenharmony_ci * Returns:
83562306a36Sopenharmony_ci *	qla2x00 local function status
83662306a36Sopenharmony_ci *
83762306a36Sopenharmony_ci * Context:
83862306a36Sopenharmony_ci *	Kernel context.
83962306a36Sopenharmony_ci */
84062306a36Sopenharmony_ci#define	FETCH_XLOGINS_STAT	0x8
84162306a36Sopenharmony_ciint
84262306a36Sopenharmony_ciqla_get_exlogin_status(scsi_qla_host_t *vha, uint16_t *buf_sz,
84362306a36Sopenharmony_ci	uint16_t *ex_logins_cnt)
84462306a36Sopenharmony_ci{
84562306a36Sopenharmony_ci	int rval;
84662306a36Sopenharmony_ci	mbx_cmd_t	mc;
84762306a36Sopenharmony_ci	mbx_cmd_t	*mcp = &mc;
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118f,
85062306a36Sopenharmony_ci	    "Entered %s\n", __func__);
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ci	memset(mcp->mb, 0 , sizeof(mcp->mb));
85362306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT;
85462306a36Sopenharmony_ci	mcp->mb[1] = FETCH_XLOGINS_STAT;
85562306a36Sopenharmony_ci	mcp->out_mb = MBX_1|MBX_0;
85662306a36Sopenharmony_ci	mcp->in_mb = MBX_10|MBX_4|MBX_0;
85762306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
85862306a36Sopenharmony_ci	mcp->flags = 0;
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
86162306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
86262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1115, "Failed=%x.\n", rval);
86362306a36Sopenharmony_ci	} else {
86462306a36Sopenharmony_ci		*buf_sz = mcp->mb[4];
86562306a36Sopenharmony_ci		*ex_logins_cnt = mcp->mb[10];
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci		ql_log(ql_log_info, vha, 0x1190,
86862306a36Sopenharmony_ci		    "buffer size 0x%x, exchange login count=%d\n",
86962306a36Sopenharmony_ci		    mcp->mb[4], mcp->mb[10]);
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1116,
87262306a36Sopenharmony_ci		    "Done %s.\n", __func__);
87362306a36Sopenharmony_ci	}
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci	return rval;
87662306a36Sopenharmony_ci}
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci/*
87962306a36Sopenharmony_ci * qla_set_exlogin_mem_cfg
88062306a36Sopenharmony_ci *	set extended login memory configuration
88162306a36Sopenharmony_ci *	Mbx needs to be issues before init_cb is set
88262306a36Sopenharmony_ci *
88362306a36Sopenharmony_ci * Input:
88462306a36Sopenharmony_ci *	ha:		adapter state pointer.
88562306a36Sopenharmony_ci *	buffer:		buffer pointer
88662306a36Sopenharmony_ci *	phys_addr:	physical address of buffer
88762306a36Sopenharmony_ci *	size:		size of buffer
88862306a36Sopenharmony_ci *	TARGET_QUEUE_LOCK must be released
88962306a36Sopenharmony_ci *	ADAPTER_STATE_LOCK must be release
89062306a36Sopenharmony_ci *
89162306a36Sopenharmony_ci * Returns:
89262306a36Sopenharmony_ci *	qla2x00 local funxtion status code.
89362306a36Sopenharmony_ci *
89462306a36Sopenharmony_ci * Context:
89562306a36Sopenharmony_ci *	Kernel context.
89662306a36Sopenharmony_ci */
89762306a36Sopenharmony_ci#define CONFIG_XLOGINS_MEM	0x9
89862306a36Sopenharmony_ciint
89962306a36Sopenharmony_ciqla_set_exlogin_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr)
90062306a36Sopenharmony_ci{
90162306a36Sopenharmony_ci	int		rval;
90262306a36Sopenharmony_ci	mbx_cmd_t	mc;
90362306a36Sopenharmony_ci	mbx_cmd_t	*mcp = &mc;
90462306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x111a,
90762306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci	memset(mcp->mb, 0 , sizeof(mcp->mb));
91062306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT;
91162306a36Sopenharmony_ci	mcp->mb[1] = CONFIG_XLOGINS_MEM;
91262306a36Sopenharmony_ci	mcp->mb[2] = MSW(phys_addr);
91362306a36Sopenharmony_ci	mcp->mb[3] = LSW(phys_addr);
91462306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(phys_addr));
91562306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(phys_addr));
91662306a36Sopenharmony_ci	mcp->mb[8] = MSW(ha->exlogin_size);
91762306a36Sopenharmony_ci	mcp->mb[9] = LSW(ha->exlogin_size);
91862306a36Sopenharmony_ci	mcp->out_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
91962306a36Sopenharmony_ci	mcp->in_mb = MBX_11|MBX_0;
92062306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
92162306a36Sopenharmony_ci	mcp->flags = 0;
92262306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
92362306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
92462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x111b,
92562306a36Sopenharmony_ci		       "EXlogin Failed=%x. MB0=%x MB11=%x\n",
92662306a36Sopenharmony_ci		       rval, mcp->mb[0], mcp->mb[11]);
92762306a36Sopenharmony_ci	} else {
92862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118c,
92962306a36Sopenharmony_ci		    "Done %s.\n", __func__);
93062306a36Sopenharmony_ci	}
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci	return rval;
93362306a36Sopenharmony_ci}
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci/*
93662306a36Sopenharmony_ci * qla_get_exchoffld_status
93762306a36Sopenharmony_ci *	Get exchange offload status
93862306a36Sopenharmony_ci *	uses the memory offload control/status Mailbox
93962306a36Sopenharmony_ci *
94062306a36Sopenharmony_ci * Input:
94162306a36Sopenharmony_ci *	ha:		adapter state pointer.
94262306a36Sopenharmony_ci *	fwopt:		firmware options
94362306a36Sopenharmony_ci *
94462306a36Sopenharmony_ci * Returns:
94562306a36Sopenharmony_ci *	qla2x00 local function status
94662306a36Sopenharmony_ci *
94762306a36Sopenharmony_ci * Context:
94862306a36Sopenharmony_ci *	Kernel context.
94962306a36Sopenharmony_ci */
95062306a36Sopenharmony_ci#define	FETCH_XCHOFFLD_STAT	0x2
95162306a36Sopenharmony_ciint
95262306a36Sopenharmony_ciqla_get_exchoffld_status(scsi_qla_host_t *vha, uint16_t *buf_sz,
95362306a36Sopenharmony_ci	uint16_t *ex_logins_cnt)
95462306a36Sopenharmony_ci{
95562306a36Sopenharmony_ci	int rval;
95662306a36Sopenharmony_ci	mbx_cmd_t	mc;
95762306a36Sopenharmony_ci	mbx_cmd_t	*mcp = &mc;
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1019,
96062306a36Sopenharmony_ci	    "Entered %s\n", __func__);
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci	memset(mcp->mb, 0 , sizeof(mcp->mb));
96362306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT;
96462306a36Sopenharmony_ci	mcp->mb[1] = FETCH_XCHOFFLD_STAT;
96562306a36Sopenharmony_ci	mcp->out_mb = MBX_1|MBX_0;
96662306a36Sopenharmony_ci	mcp->in_mb = MBX_10|MBX_4|MBX_0;
96762306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
96862306a36Sopenharmony_ci	mcp->flags = 0;
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
97162306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
97262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1155, "Failed=%x.\n", rval);
97362306a36Sopenharmony_ci	} else {
97462306a36Sopenharmony_ci		*buf_sz = mcp->mb[4];
97562306a36Sopenharmony_ci		*ex_logins_cnt = mcp->mb[10];
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci		ql_log(ql_log_info, vha, 0x118e,
97862306a36Sopenharmony_ci		    "buffer size 0x%x, exchange offload count=%d\n",
97962306a36Sopenharmony_ci		    mcp->mb[4], mcp->mb[10]);
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1156,
98262306a36Sopenharmony_ci		    "Done %s.\n", __func__);
98362306a36Sopenharmony_ci	}
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci	return rval;
98662306a36Sopenharmony_ci}
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci/*
98962306a36Sopenharmony_ci * qla_set_exchoffld_mem_cfg
99062306a36Sopenharmony_ci *	Set exchange offload memory configuration
99162306a36Sopenharmony_ci *	Mbx needs to be issues before init_cb is set
99262306a36Sopenharmony_ci *
99362306a36Sopenharmony_ci * Input:
99462306a36Sopenharmony_ci *	ha:		adapter state pointer.
99562306a36Sopenharmony_ci *	buffer:		buffer pointer
99662306a36Sopenharmony_ci *	phys_addr:	physical address of buffer
99762306a36Sopenharmony_ci *	size:		size of buffer
99862306a36Sopenharmony_ci *	TARGET_QUEUE_LOCK must be released
99962306a36Sopenharmony_ci *	ADAPTER_STATE_LOCK must be release
100062306a36Sopenharmony_ci *
100162306a36Sopenharmony_ci * Returns:
100262306a36Sopenharmony_ci *	qla2x00 local funxtion status code.
100362306a36Sopenharmony_ci *
100462306a36Sopenharmony_ci * Context:
100562306a36Sopenharmony_ci *	Kernel context.
100662306a36Sopenharmony_ci */
100762306a36Sopenharmony_ci#define CONFIG_XCHOFFLD_MEM	0x3
100862306a36Sopenharmony_ciint
100962306a36Sopenharmony_ciqla_set_exchoffld_mem_cfg(scsi_qla_host_t *vha)
101062306a36Sopenharmony_ci{
101162306a36Sopenharmony_ci	int		rval;
101262306a36Sopenharmony_ci	mbx_cmd_t	mc;
101362306a36Sopenharmony_ci	mbx_cmd_t	*mcp = &mc;
101462306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1157,
101762306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	memset(mcp->mb, 0 , sizeof(mcp->mb));
102062306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT;
102162306a36Sopenharmony_ci	mcp->mb[1] = CONFIG_XCHOFFLD_MEM;
102262306a36Sopenharmony_ci	mcp->mb[2] = MSW(ha->exchoffld_buf_dma);
102362306a36Sopenharmony_ci	mcp->mb[3] = LSW(ha->exchoffld_buf_dma);
102462306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(ha->exchoffld_buf_dma));
102562306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(ha->exchoffld_buf_dma));
102662306a36Sopenharmony_ci	mcp->mb[8] = MSW(ha->exchoffld_size);
102762306a36Sopenharmony_ci	mcp->mb[9] = LSW(ha->exchoffld_size);
102862306a36Sopenharmony_ci	mcp->out_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
102962306a36Sopenharmony_ci	mcp->in_mb = MBX_11|MBX_0;
103062306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
103162306a36Sopenharmony_ci	mcp->flags = 0;
103262306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
103362306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
103462306a36Sopenharmony_ci		/*EMPTY*/
103562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1158, "Failed=%x.\n", rval);
103662306a36Sopenharmony_ci	} else {
103762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1192,
103862306a36Sopenharmony_ci		    "Done %s.\n", __func__);
103962306a36Sopenharmony_ci	}
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	return rval;
104262306a36Sopenharmony_ci}
104362306a36Sopenharmony_ci
104462306a36Sopenharmony_ci/*
104562306a36Sopenharmony_ci * qla2x00_get_fw_version
104662306a36Sopenharmony_ci *	Get firmware version.
104762306a36Sopenharmony_ci *
104862306a36Sopenharmony_ci * Input:
104962306a36Sopenharmony_ci *	ha:		adapter state pointer.
105062306a36Sopenharmony_ci *	major:		pointer for major number.
105162306a36Sopenharmony_ci *	minor:		pointer for minor number.
105262306a36Sopenharmony_ci *	subminor:	pointer for subminor number.
105362306a36Sopenharmony_ci *
105462306a36Sopenharmony_ci * Returns:
105562306a36Sopenharmony_ci *	qla2x00 local function return status code.
105662306a36Sopenharmony_ci *
105762306a36Sopenharmony_ci * Context:
105862306a36Sopenharmony_ci *	Kernel context.
105962306a36Sopenharmony_ci */
106062306a36Sopenharmony_ciint
106162306a36Sopenharmony_ciqla2x00_get_fw_version(scsi_qla_host_t *vha)
106262306a36Sopenharmony_ci{
106362306a36Sopenharmony_ci	int		rval;
106462306a36Sopenharmony_ci	mbx_cmd_t	mc;
106562306a36Sopenharmony_ci	mbx_cmd_t	*mcp = &mc;
106662306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1029,
106962306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_FIRMWARE_VERSION;
107262306a36Sopenharmony_ci	mcp->out_mb = MBX_0;
107362306a36Sopenharmony_ci	mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
107462306a36Sopenharmony_ci	if (IS_QLA81XX(vha->hw) || IS_QLA8031(ha) || IS_QLA8044(ha))
107562306a36Sopenharmony_ci		mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8;
107662306a36Sopenharmony_ci	if (IS_FWI2_CAPABLE(ha))
107762306a36Sopenharmony_ci		mcp->in_mb |= MBX_17|MBX_16|MBX_15;
107862306a36Sopenharmony_ci	if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
107962306a36Sopenharmony_ci		mcp->in_mb |=
108062306a36Sopenharmony_ci		    MBX_25|MBX_24|MBX_23|MBX_22|MBX_21|MBX_20|MBX_19|MBX_18|
108162306a36Sopenharmony_ci		    MBX_14|MBX_13|MBX_11|MBX_10|MBX_9|MBX_8|MBX_7;
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	mcp->flags = 0;
108462306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
108562306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
108662306a36Sopenharmony_ci	if (rval != QLA_SUCCESS)
108762306a36Sopenharmony_ci		goto failed;
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ci	/* Return mailbox data. */
109062306a36Sopenharmony_ci	ha->fw_major_version = mcp->mb[1];
109162306a36Sopenharmony_ci	ha->fw_minor_version = mcp->mb[2];
109262306a36Sopenharmony_ci	ha->fw_subminor_version = mcp->mb[3];
109362306a36Sopenharmony_ci	ha->fw_attributes = mcp->mb[6];
109462306a36Sopenharmony_ci	if (IS_QLA2100(vha->hw) || IS_QLA2200(vha->hw))
109562306a36Sopenharmony_ci		ha->fw_memory_size = 0x1FFFF;		/* Defaults to 128KB. */
109662306a36Sopenharmony_ci	else
109762306a36Sopenharmony_ci		ha->fw_memory_size = (mcp->mb[5] << 16) | mcp->mb[4];
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_ci	if (IS_QLA81XX(vha->hw) || IS_QLA8031(vha->hw) || IS_QLA8044(ha)) {
110062306a36Sopenharmony_ci		ha->mpi_version[0] = mcp->mb[10] & 0xff;
110162306a36Sopenharmony_ci		ha->mpi_version[1] = mcp->mb[11] >> 8;
110262306a36Sopenharmony_ci		ha->mpi_version[2] = mcp->mb[11] & 0xff;
110362306a36Sopenharmony_ci		ha->mpi_capabilities = (mcp->mb[12] << 16) | mcp->mb[13];
110462306a36Sopenharmony_ci		ha->phy_version[0] = mcp->mb[8] & 0xff;
110562306a36Sopenharmony_ci		ha->phy_version[1] = mcp->mb[9] >> 8;
110662306a36Sopenharmony_ci		ha->phy_version[2] = mcp->mb[9] & 0xff;
110762306a36Sopenharmony_ci	}
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci	if (IS_FWI2_CAPABLE(ha)) {
111062306a36Sopenharmony_ci		ha->fw_attributes_h = mcp->mb[15];
111162306a36Sopenharmony_ci		ha->fw_attributes_ext[0] = mcp->mb[16];
111262306a36Sopenharmony_ci		ha->fw_attributes_ext[1] = mcp->mb[17];
111362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1139,
111462306a36Sopenharmony_ci		    "%s: FW_attributes Upper: 0x%x, Lower: 0x%x.\n",
111562306a36Sopenharmony_ci		    __func__, mcp->mb[15], mcp->mb[6]);
111662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x112f,
111762306a36Sopenharmony_ci		    "%s: Ext_FwAttributes Upper: 0x%x, Lower: 0x%x.\n",
111862306a36Sopenharmony_ci		    __func__, mcp->mb[17], mcp->mb[16]);
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci		if (ha->fw_attributes_h & 0x4)
112162306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118d,
112262306a36Sopenharmony_ci			    "%s: Firmware supports Extended Login 0x%x\n",
112362306a36Sopenharmony_ci			    __func__, ha->fw_attributes_h);
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci		if (ha->fw_attributes_h & 0x8)
112662306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1191,
112762306a36Sopenharmony_ci			    "%s: Firmware supports Exchange Offload 0x%x\n",
112862306a36Sopenharmony_ci			    __func__, ha->fw_attributes_h);
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci		/*
113162306a36Sopenharmony_ci		 * FW supports nvme and driver load parameter requested nvme.
113262306a36Sopenharmony_ci		 * BIT 26 of fw_attributes indicates NVMe support.
113362306a36Sopenharmony_ci		 */
113462306a36Sopenharmony_ci		if ((ha->fw_attributes_h &
113562306a36Sopenharmony_ci		    (FW_ATTR_H_NVME | FW_ATTR_H_NVME_UPDATED)) &&
113662306a36Sopenharmony_ci			ql2xnvmeenable) {
113762306a36Sopenharmony_ci			if (ha->fw_attributes_h & FW_ATTR_H_NVME_FBURST)
113862306a36Sopenharmony_ci				vha->flags.nvme_first_burst = 1;
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci			vha->flags.nvme_enabled = 1;
114162306a36Sopenharmony_ci			ql_log(ql_log_info, vha, 0xd302,
114262306a36Sopenharmony_ci			    "%s: FC-NVMe is Enabled (0x%x)\n",
114362306a36Sopenharmony_ci			     __func__, ha->fw_attributes_h);
114462306a36Sopenharmony_ci		}
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci		/* BIT_13 of Extended FW Attributes informs about NVMe2 support */
114762306a36Sopenharmony_ci		if (ha->fw_attributes_ext[0] & FW_ATTR_EXT0_NVME2) {
114862306a36Sopenharmony_ci			ql_log(ql_log_info, vha, 0xd302,
114962306a36Sopenharmony_ci			       "Firmware supports NVMe2 0x%x\n",
115062306a36Sopenharmony_ci			       ha->fw_attributes_ext[0]);
115162306a36Sopenharmony_ci			vha->flags.nvme2_enabled = 1;
115262306a36Sopenharmony_ci		}
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_ci		if (IS_QLA28XX(ha) && ha->flags.edif_hw && ql2xsecenable &&
115562306a36Sopenharmony_ci		    (ha->fw_attributes_ext[0] & FW_ATTR_EXT0_EDIF)) {
115662306a36Sopenharmony_ci			ha->flags.edif_enabled = 1;
115762306a36Sopenharmony_ci			ql_log(ql_log_info, vha, 0xffff,
115862306a36Sopenharmony_ci			       "%s: edif is enabled\n", __func__);
115962306a36Sopenharmony_ci		}
116062306a36Sopenharmony_ci	}
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci	if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
116362306a36Sopenharmony_ci		ha->serdes_version[0] = mcp->mb[7] & 0xff;
116462306a36Sopenharmony_ci		ha->serdes_version[1] = mcp->mb[8] >> 8;
116562306a36Sopenharmony_ci		ha->serdes_version[2] = mcp->mb[8] & 0xff;
116662306a36Sopenharmony_ci		ha->mpi_version[0] = mcp->mb[10] & 0xff;
116762306a36Sopenharmony_ci		ha->mpi_version[1] = mcp->mb[11] >> 8;
116862306a36Sopenharmony_ci		ha->mpi_version[2] = mcp->mb[11] & 0xff;
116962306a36Sopenharmony_ci		ha->pep_version[0] = mcp->mb[13] & 0xff;
117062306a36Sopenharmony_ci		ha->pep_version[1] = mcp->mb[14] >> 8;
117162306a36Sopenharmony_ci		ha->pep_version[2] = mcp->mb[14] & 0xff;
117262306a36Sopenharmony_ci		ha->fw_shared_ram_start = (mcp->mb[19] << 16) | mcp->mb[18];
117362306a36Sopenharmony_ci		ha->fw_shared_ram_end = (mcp->mb[21] << 16) | mcp->mb[20];
117462306a36Sopenharmony_ci		ha->fw_ddr_ram_start = (mcp->mb[23] << 16) | mcp->mb[22];
117562306a36Sopenharmony_ci		ha->fw_ddr_ram_end = (mcp->mb[25] << 16) | mcp->mb[24];
117662306a36Sopenharmony_ci		if (IS_QLA28XX(ha)) {
117762306a36Sopenharmony_ci			if (mcp->mb[16] & BIT_10)
117862306a36Sopenharmony_ci				ha->flags.secure_fw = 1;
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci			ql_log(ql_log_info, vha, 0xffff,
118162306a36Sopenharmony_ci			    "Secure Flash Update in FW: %s\n",
118262306a36Sopenharmony_ci			    (ha->flags.secure_fw) ? "Supported" :
118362306a36Sopenharmony_ci			    "Not Supported");
118462306a36Sopenharmony_ci		}
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci		if (ha->flags.scm_supported_a &&
118762306a36Sopenharmony_ci		    (ha->fw_attributes_ext[0] & FW_ATTR_EXT0_SCM_SUPPORTED)) {
118862306a36Sopenharmony_ci			ha->flags.scm_supported_f = 1;
118962306a36Sopenharmony_ci			ha->sf_init_cb->flags |= cpu_to_le16(BIT_13);
119062306a36Sopenharmony_ci		}
119162306a36Sopenharmony_ci		ql_log(ql_log_info, vha, 0x11a3, "SCM in FW: %s\n",
119262306a36Sopenharmony_ci		       (ha->flags.scm_supported_f) ? "Supported" :
119362306a36Sopenharmony_ci		       "Not Supported");
119462306a36Sopenharmony_ci
119562306a36Sopenharmony_ci		if (vha->flags.nvme2_enabled) {
119662306a36Sopenharmony_ci			/* set BIT_15 of special feature control block for SLER */
119762306a36Sopenharmony_ci			ha->sf_init_cb->flags |= cpu_to_le16(BIT_15);
119862306a36Sopenharmony_ci			/* set BIT_14 of special feature control block for PI CTRL*/
119962306a36Sopenharmony_ci			ha->sf_init_cb->flags |= cpu_to_le16(BIT_14);
120062306a36Sopenharmony_ci		}
120162306a36Sopenharmony_ci	}
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_cifailed:
120462306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
120562306a36Sopenharmony_ci		/*EMPTY*/
120662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x102a, "Failed=%x.\n", rval);
120762306a36Sopenharmony_ci	} else {
120862306a36Sopenharmony_ci		/*EMPTY*/
120962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102b,
121062306a36Sopenharmony_ci		    "Done %s.\n", __func__);
121162306a36Sopenharmony_ci	}
121262306a36Sopenharmony_ci	return rval;
121362306a36Sopenharmony_ci}
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci/*
121662306a36Sopenharmony_ci * qla2x00_get_fw_options
121762306a36Sopenharmony_ci *	Set firmware options.
121862306a36Sopenharmony_ci *
121962306a36Sopenharmony_ci * Input:
122062306a36Sopenharmony_ci *	ha = adapter block pointer.
122162306a36Sopenharmony_ci *	fwopt = pointer for firmware options.
122262306a36Sopenharmony_ci *
122362306a36Sopenharmony_ci * Returns:
122462306a36Sopenharmony_ci *	qla2x00 local function return status code.
122562306a36Sopenharmony_ci *
122662306a36Sopenharmony_ci * Context:
122762306a36Sopenharmony_ci *	Kernel context.
122862306a36Sopenharmony_ci */
122962306a36Sopenharmony_ciint
123062306a36Sopenharmony_ciqla2x00_get_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts)
123162306a36Sopenharmony_ci{
123262306a36Sopenharmony_ci	int rval;
123362306a36Sopenharmony_ci	mbx_cmd_t mc;
123462306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102c,
123762306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_FIRMWARE_OPTION;
124062306a36Sopenharmony_ci	mcp->out_mb = MBX_0;
124162306a36Sopenharmony_ci	mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
124262306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
124362306a36Sopenharmony_ci	mcp->flags = 0;
124462306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
124562306a36Sopenharmony_ci
124662306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
124762306a36Sopenharmony_ci		/*EMPTY*/
124862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x102d, "Failed=%x.\n", rval);
124962306a36Sopenharmony_ci	} else {
125062306a36Sopenharmony_ci		fwopts[0] = mcp->mb[0];
125162306a36Sopenharmony_ci		fwopts[1] = mcp->mb[1];
125262306a36Sopenharmony_ci		fwopts[2] = mcp->mb[2];
125362306a36Sopenharmony_ci		fwopts[3] = mcp->mb[3];
125462306a36Sopenharmony_ci
125562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102e,
125662306a36Sopenharmony_ci		    "Done %s.\n", __func__);
125762306a36Sopenharmony_ci	}
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	return rval;
126062306a36Sopenharmony_ci}
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_ci/*
126462306a36Sopenharmony_ci * qla2x00_set_fw_options
126562306a36Sopenharmony_ci *	Set firmware options.
126662306a36Sopenharmony_ci *
126762306a36Sopenharmony_ci * Input:
126862306a36Sopenharmony_ci *	ha = adapter block pointer.
126962306a36Sopenharmony_ci *	fwopt = pointer for firmware options.
127062306a36Sopenharmony_ci *
127162306a36Sopenharmony_ci * Returns:
127262306a36Sopenharmony_ci *	qla2x00 local function return status code.
127362306a36Sopenharmony_ci *
127462306a36Sopenharmony_ci * Context:
127562306a36Sopenharmony_ci *	Kernel context.
127662306a36Sopenharmony_ci */
127762306a36Sopenharmony_ciint
127862306a36Sopenharmony_ciqla2x00_set_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts)
127962306a36Sopenharmony_ci{
128062306a36Sopenharmony_ci	int rval;
128162306a36Sopenharmony_ci	mbx_cmd_t mc;
128262306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
128362306a36Sopenharmony_ci
128462306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102f,
128562306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
128662306a36Sopenharmony_ci
128762306a36Sopenharmony_ci	mcp->mb[0] = MBC_SET_FIRMWARE_OPTION;
128862306a36Sopenharmony_ci	mcp->mb[1] = fwopts[1];
128962306a36Sopenharmony_ci	mcp->mb[2] = fwopts[2];
129062306a36Sopenharmony_ci	mcp->mb[3] = fwopts[3];
129162306a36Sopenharmony_ci	mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
129262306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
129362306a36Sopenharmony_ci	if (IS_FWI2_CAPABLE(vha->hw)) {
129462306a36Sopenharmony_ci		mcp->in_mb |= MBX_1;
129562306a36Sopenharmony_ci		mcp->mb[10] = fwopts[10];
129662306a36Sopenharmony_ci		mcp->out_mb |= MBX_10;
129762306a36Sopenharmony_ci	} else {
129862306a36Sopenharmony_ci		mcp->mb[10] = fwopts[10];
129962306a36Sopenharmony_ci		mcp->mb[11] = fwopts[11];
130062306a36Sopenharmony_ci		mcp->mb[12] = 0;	/* Undocumented, but used */
130162306a36Sopenharmony_ci		mcp->out_mb |= MBX_12|MBX_11|MBX_10;
130262306a36Sopenharmony_ci	}
130362306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
130462306a36Sopenharmony_ci	mcp->flags = 0;
130562306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
130662306a36Sopenharmony_ci
130762306a36Sopenharmony_ci	fwopts[0] = mcp->mb[0];
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
131062306a36Sopenharmony_ci		/*EMPTY*/
131162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1030,
131262306a36Sopenharmony_ci		    "Failed=%x (%x/%x).\n", rval, mcp->mb[0], mcp->mb[1]);
131362306a36Sopenharmony_ci	} else {
131462306a36Sopenharmony_ci		/*EMPTY*/
131562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1031,
131662306a36Sopenharmony_ci		    "Done %s.\n", __func__);
131762306a36Sopenharmony_ci	}
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci	return rval;
132062306a36Sopenharmony_ci}
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci/*
132362306a36Sopenharmony_ci * qla2x00_mbx_reg_test
132462306a36Sopenharmony_ci *	Mailbox register wrap test.
132562306a36Sopenharmony_ci *
132662306a36Sopenharmony_ci * Input:
132762306a36Sopenharmony_ci *	ha = adapter block pointer.
132862306a36Sopenharmony_ci *	TARGET_QUEUE_LOCK must be released.
132962306a36Sopenharmony_ci *	ADAPTER_STATE_LOCK must be released.
133062306a36Sopenharmony_ci *
133162306a36Sopenharmony_ci * Returns:
133262306a36Sopenharmony_ci *	qla2x00 local function return status code.
133362306a36Sopenharmony_ci *
133462306a36Sopenharmony_ci * Context:
133562306a36Sopenharmony_ci *	Kernel context.
133662306a36Sopenharmony_ci */
133762306a36Sopenharmony_ciint
133862306a36Sopenharmony_ciqla2x00_mbx_reg_test(scsi_qla_host_t *vha)
133962306a36Sopenharmony_ci{
134062306a36Sopenharmony_ci	int rval;
134162306a36Sopenharmony_ci	mbx_cmd_t mc;
134262306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1032,
134562306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci	mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST;
134862306a36Sopenharmony_ci	mcp->mb[1] = 0xAAAA;
134962306a36Sopenharmony_ci	mcp->mb[2] = 0x5555;
135062306a36Sopenharmony_ci	mcp->mb[3] = 0xAA55;
135162306a36Sopenharmony_ci	mcp->mb[4] = 0x55AA;
135262306a36Sopenharmony_ci	mcp->mb[5] = 0xA5A5;
135362306a36Sopenharmony_ci	mcp->mb[6] = 0x5A5A;
135462306a36Sopenharmony_ci	mcp->mb[7] = 0x2525;
135562306a36Sopenharmony_ci	mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
135662306a36Sopenharmony_ci	mcp->in_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
135762306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
135862306a36Sopenharmony_ci	mcp->flags = 0;
135962306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci	if (rval == QLA_SUCCESS) {
136262306a36Sopenharmony_ci		if (mcp->mb[1] != 0xAAAA || mcp->mb[2] != 0x5555 ||
136362306a36Sopenharmony_ci		    mcp->mb[3] != 0xAA55 || mcp->mb[4] != 0x55AA)
136462306a36Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
136562306a36Sopenharmony_ci		if (mcp->mb[5] != 0xA5A5 || mcp->mb[6] != 0x5A5A ||
136662306a36Sopenharmony_ci		    mcp->mb[7] != 0x2525)
136762306a36Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
136862306a36Sopenharmony_ci	}
136962306a36Sopenharmony_ci
137062306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
137162306a36Sopenharmony_ci		/*EMPTY*/
137262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1033, "Failed=%x.\n", rval);
137362306a36Sopenharmony_ci		vha->hw_err_cnt++;
137462306a36Sopenharmony_ci	} else {
137562306a36Sopenharmony_ci		/*EMPTY*/
137662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1034,
137762306a36Sopenharmony_ci		    "Done %s.\n", __func__);
137862306a36Sopenharmony_ci	}
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_ci	return rval;
138162306a36Sopenharmony_ci}
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci/*
138462306a36Sopenharmony_ci * qla2x00_verify_checksum
138562306a36Sopenharmony_ci *	Verify firmware checksum.
138662306a36Sopenharmony_ci *
138762306a36Sopenharmony_ci * Input:
138862306a36Sopenharmony_ci *	ha = adapter block pointer.
138962306a36Sopenharmony_ci *	TARGET_QUEUE_LOCK must be released.
139062306a36Sopenharmony_ci *	ADAPTER_STATE_LOCK must be released.
139162306a36Sopenharmony_ci *
139262306a36Sopenharmony_ci * Returns:
139362306a36Sopenharmony_ci *	qla2x00 local function return status code.
139462306a36Sopenharmony_ci *
139562306a36Sopenharmony_ci * Context:
139662306a36Sopenharmony_ci *	Kernel context.
139762306a36Sopenharmony_ci */
139862306a36Sopenharmony_ciint
139962306a36Sopenharmony_ciqla2x00_verify_checksum(scsi_qla_host_t *vha, uint32_t risc_addr)
140062306a36Sopenharmony_ci{
140162306a36Sopenharmony_ci	int rval;
140262306a36Sopenharmony_ci	mbx_cmd_t mc;
140362306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
140462306a36Sopenharmony_ci
140562306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1035,
140662306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_ci	mcp->mb[0] = MBC_VERIFY_CHECKSUM;
140962306a36Sopenharmony_ci	mcp->out_mb = MBX_0;
141062306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
141162306a36Sopenharmony_ci	if (IS_FWI2_CAPABLE(vha->hw)) {
141262306a36Sopenharmony_ci		mcp->mb[1] = MSW(risc_addr);
141362306a36Sopenharmony_ci		mcp->mb[2] = LSW(risc_addr);
141462306a36Sopenharmony_ci		mcp->out_mb |= MBX_2|MBX_1;
141562306a36Sopenharmony_ci		mcp->in_mb |= MBX_2|MBX_1;
141662306a36Sopenharmony_ci	} else {
141762306a36Sopenharmony_ci		mcp->mb[1] = LSW(risc_addr);
141862306a36Sopenharmony_ci		mcp->out_mb |= MBX_1;
141962306a36Sopenharmony_ci		mcp->in_mb |= MBX_1;
142062306a36Sopenharmony_ci	}
142162306a36Sopenharmony_ci
142262306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
142362306a36Sopenharmony_ci	mcp->flags = 0;
142462306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
142562306a36Sopenharmony_ci
142662306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
142762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1036,
142862306a36Sopenharmony_ci		    "Failed=%x chm sum=%x.\n", rval, IS_FWI2_CAPABLE(vha->hw) ?
142962306a36Sopenharmony_ci		    (mcp->mb[2] << 16) | mcp->mb[1] : mcp->mb[1]);
143062306a36Sopenharmony_ci	} else {
143162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1037,
143262306a36Sopenharmony_ci		    "Done %s.\n", __func__);
143362306a36Sopenharmony_ci	}
143462306a36Sopenharmony_ci
143562306a36Sopenharmony_ci	return rval;
143662306a36Sopenharmony_ci}
143762306a36Sopenharmony_ci
143862306a36Sopenharmony_ci/*
143962306a36Sopenharmony_ci * qla2x00_issue_iocb
144062306a36Sopenharmony_ci *	Issue IOCB using mailbox command
144162306a36Sopenharmony_ci *
144262306a36Sopenharmony_ci * Input:
144362306a36Sopenharmony_ci *	ha = adapter state pointer.
144462306a36Sopenharmony_ci *	buffer = buffer pointer.
144562306a36Sopenharmony_ci *	phys_addr = physical address of buffer.
144662306a36Sopenharmony_ci *	size = size of buffer.
144762306a36Sopenharmony_ci *	TARGET_QUEUE_LOCK must be released.
144862306a36Sopenharmony_ci *	ADAPTER_STATE_LOCK must be released.
144962306a36Sopenharmony_ci *
145062306a36Sopenharmony_ci * Returns:
145162306a36Sopenharmony_ci *	qla2x00 local function return status code.
145262306a36Sopenharmony_ci *
145362306a36Sopenharmony_ci * Context:
145462306a36Sopenharmony_ci *	Kernel context.
145562306a36Sopenharmony_ci */
145662306a36Sopenharmony_ciint
145762306a36Sopenharmony_ciqla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer,
145862306a36Sopenharmony_ci    dma_addr_t phys_addr, size_t size, uint32_t tov)
145962306a36Sopenharmony_ci{
146062306a36Sopenharmony_ci	int		rval;
146162306a36Sopenharmony_ci	mbx_cmd_t	mc;
146262306a36Sopenharmony_ci	mbx_cmd_t	*mcp = &mc;
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ci	if (!vha->hw->flags.fw_started)
146562306a36Sopenharmony_ci		return QLA_INVALID_COMMAND;
146662306a36Sopenharmony_ci
146762306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1038,
146862306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
146962306a36Sopenharmony_ci
147062306a36Sopenharmony_ci	mcp->mb[0] = MBC_IOCB_COMMAND_A64;
147162306a36Sopenharmony_ci	mcp->mb[1] = 0;
147262306a36Sopenharmony_ci	mcp->mb[2] = MSW(LSD(phys_addr));
147362306a36Sopenharmony_ci	mcp->mb[3] = LSW(LSD(phys_addr));
147462306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(phys_addr));
147562306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(phys_addr));
147662306a36Sopenharmony_ci	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
147762306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
147862306a36Sopenharmony_ci	mcp->tov = tov;
147962306a36Sopenharmony_ci	mcp->flags = 0;
148062306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
148362306a36Sopenharmony_ci		/*EMPTY*/
148462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1039, "Failed=%x.\n", rval);
148562306a36Sopenharmony_ci	} else {
148662306a36Sopenharmony_ci		sts_entry_t *sts_entry = buffer;
148762306a36Sopenharmony_ci
148862306a36Sopenharmony_ci		/* Mask reserved bits. */
148962306a36Sopenharmony_ci		sts_entry->entry_status &=
149062306a36Sopenharmony_ci		    IS_FWI2_CAPABLE(vha->hw) ? RF_MASK_24XX : RF_MASK;
149162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103a,
149262306a36Sopenharmony_ci		    "Done %s (status=%x).\n", __func__,
149362306a36Sopenharmony_ci		    sts_entry->entry_status);
149462306a36Sopenharmony_ci	}
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci	return rval;
149762306a36Sopenharmony_ci}
149862306a36Sopenharmony_ci
149962306a36Sopenharmony_ciint
150062306a36Sopenharmony_ciqla2x00_issue_iocb(scsi_qla_host_t *vha, void *buffer, dma_addr_t phys_addr,
150162306a36Sopenharmony_ci    size_t size)
150262306a36Sopenharmony_ci{
150362306a36Sopenharmony_ci	return qla2x00_issue_iocb_timeout(vha, buffer, phys_addr, size,
150462306a36Sopenharmony_ci	    MBX_TOV_SECONDS);
150562306a36Sopenharmony_ci}
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci/*
150862306a36Sopenharmony_ci * qla2x00_abort_command
150962306a36Sopenharmony_ci *	Abort command aborts a specified IOCB.
151062306a36Sopenharmony_ci *
151162306a36Sopenharmony_ci * Input:
151262306a36Sopenharmony_ci *	ha = adapter block pointer.
151362306a36Sopenharmony_ci *	sp = SB structure pointer.
151462306a36Sopenharmony_ci *
151562306a36Sopenharmony_ci * Returns:
151662306a36Sopenharmony_ci *	qla2x00 local function return status code.
151762306a36Sopenharmony_ci *
151862306a36Sopenharmony_ci * Context:
151962306a36Sopenharmony_ci *	Kernel context.
152062306a36Sopenharmony_ci */
152162306a36Sopenharmony_ciint
152262306a36Sopenharmony_ciqla2x00_abort_command(srb_t *sp)
152362306a36Sopenharmony_ci{
152462306a36Sopenharmony_ci	unsigned long   flags = 0;
152562306a36Sopenharmony_ci	int		rval;
152662306a36Sopenharmony_ci	uint32_t	handle = 0;
152762306a36Sopenharmony_ci	mbx_cmd_t	mc;
152862306a36Sopenharmony_ci	mbx_cmd_t	*mcp = &mc;
152962306a36Sopenharmony_ci	fc_port_t	*fcport = sp->fcport;
153062306a36Sopenharmony_ci	scsi_qla_host_t *vha = fcport->vha;
153162306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
153262306a36Sopenharmony_ci	struct req_que *req;
153362306a36Sopenharmony_ci	struct scsi_cmnd *cmd = GET_CMD_SP(sp);
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103b,
153662306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
153762306a36Sopenharmony_ci
153862306a36Sopenharmony_ci	if (sp->qpair)
153962306a36Sopenharmony_ci		req = sp->qpair->req;
154062306a36Sopenharmony_ci	else
154162306a36Sopenharmony_ci		req = vha->req;
154262306a36Sopenharmony_ci
154362306a36Sopenharmony_ci	spin_lock_irqsave(&ha->hardware_lock, flags);
154462306a36Sopenharmony_ci	for (handle = 1; handle < req->num_outstanding_cmds; handle++) {
154562306a36Sopenharmony_ci		if (req->outstanding_cmds[handle] == sp)
154662306a36Sopenharmony_ci			break;
154762306a36Sopenharmony_ci	}
154862306a36Sopenharmony_ci	spin_unlock_irqrestore(&ha->hardware_lock, flags);
154962306a36Sopenharmony_ci
155062306a36Sopenharmony_ci	if (handle == req->num_outstanding_cmds) {
155162306a36Sopenharmony_ci		/* command not found */
155262306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
155362306a36Sopenharmony_ci	}
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_ci	mcp->mb[0] = MBC_ABORT_COMMAND;
155662306a36Sopenharmony_ci	if (HAS_EXTENDED_IDS(ha))
155762306a36Sopenharmony_ci		mcp->mb[1] = fcport->loop_id;
155862306a36Sopenharmony_ci	else
155962306a36Sopenharmony_ci		mcp->mb[1] = fcport->loop_id << 8;
156062306a36Sopenharmony_ci	mcp->mb[2] = (uint16_t)handle;
156162306a36Sopenharmony_ci	mcp->mb[3] = (uint16_t)(handle >> 16);
156262306a36Sopenharmony_ci	mcp->mb[6] = (uint16_t)cmd->device->lun;
156362306a36Sopenharmony_ci	mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
156462306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
156562306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
156662306a36Sopenharmony_ci	mcp->flags = 0;
156762306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
157062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x103c, "Failed=%x.\n", rval);
157162306a36Sopenharmony_ci	} else {
157262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103d,
157362306a36Sopenharmony_ci		    "Done %s.\n", __func__);
157462306a36Sopenharmony_ci	}
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	return rval;
157762306a36Sopenharmony_ci}
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_ciint
158062306a36Sopenharmony_ciqla2x00_abort_target(struct fc_port *fcport, uint64_t l, int tag)
158162306a36Sopenharmony_ci{
158262306a36Sopenharmony_ci	int rval, rval2;
158362306a36Sopenharmony_ci	mbx_cmd_t  mc;
158462306a36Sopenharmony_ci	mbx_cmd_t  *mcp = &mc;
158562306a36Sopenharmony_ci	scsi_qla_host_t *vha;
158662306a36Sopenharmony_ci
158762306a36Sopenharmony_ci	vha = fcport->vha;
158862306a36Sopenharmony_ci
158962306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103e,
159062306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
159162306a36Sopenharmony_ci
159262306a36Sopenharmony_ci	mcp->mb[0] = MBC_ABORT_TARGET;
159362306a36Sopenharmony_ci	mcp->out_mb = MBX_9|MBX_2|MBX_1|MBX_0;
159462306a36Sopenharmony_ci	if (HAS_EXTENDED_IDS(vha->hw)) {
159562306a36Sopenharmony_ci		mcp->mb[1] = fcport->loop_id;
159662306a36Sopenharmony_ci		mcp->mb[10] = 0;
159762306a36Sopenharmony_ci		mcp->out_mb |= MBX_10;
159862306a36Sopenharmony_ci	} else {
159962306a36Sopenharmony_ci		mcp->mb[1] = fcport->loop_id << 8;
160062306a36Sopenharmony_ci	}
160162306a36Sopenharmony_ci	mcp->mb[2] = vha->hw->loop_reset_delay;
160262306a36Sopenharmony_ci	mcp->mb[9] = vha->vp_idx;
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
160562306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
160662306a36Sopenharmony_ci	mcp->flags = 0;
160762306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
160862306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
160962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103f,
161062306a36Sopenharmony_ci		    "Failed=%x.\n", rval);
161162306a36Sopenharmony_ci	}
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_ci	/* Issue marker IOCB. */
161462306a36Sopenharmony_ci	rval2 = qla2x00_marker(vha, vha->hw->base_qpair, fcport->loop_id, 0,
161562306a36Sopenharmony_ci							MK_SYNC_ID);
161662306a36Sopenharmony_ci	if (rval2 != QLA_SUCCESS) {
161762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1040,
161862306a36Sopenharmony_ci		    "Failed to issue marker IOCB (%x).\n", rval2);
161962306a36Sopenharmony_ci	} else {
162062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1041,
162162306a36Sopenharmony_ci		    "Done %s.\n", __func__);
162262306a36Sopenharmony_ci	}
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_ci	return rval;
162562306a36Sopenharmony_ci}
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_ciint
162862306a36Sopenharmony_ciqla2x00_lun_reset(struct fc_port *fcport, uint64_t l, int tag)
162962306a36Sopenharmony_ci{
163062306a36Sopenharmony_ci	int rval, rval2;
163162306a36Sopenharmony_ci	mbx_cmd_t  mc;
163262306a36Sopenharmony_ci	mbx_cmd_t  *mcp = &mc;
163362306a36Sopenharmony_ci	scsi_qla_host_t *vha;
163462306a36Sopenharmony_ci
163562306a36Sopenharmony_ci	vha = fcport->vha;
163662306a36Sopenharmony_ci
163762306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1042,
163862306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
163962306a36Sopenharmony_ci
164062306a36Sopenharmony_ci	mcp->mb[0] = MBC_LUN_RESET;
164162306a36Sopenharmony_ci	mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0;
164262306a36Sopenharmony_ci	if (HAS_EXTENDED_IDS(vha->hw))
164362306a36Sopenharmony_ci		mcp->mb[1] = fcport->loop_id;
164462306a36Sopenharmony_ci	else
164562306a36Sopenharmony_ci		mcp->mb[1] = fcport->loop_id << 8;
164662306a36Sopenharmony_ci	mcp->mb[2] = (u32)l;
164762306a36Sopenharmony_ci	mcp->mb[3] = 0;
164862306a36Sopenharmony_ci	mcp->mb[9] = vha->vp_idx;
164962306a36Sopenharmony_ci
165062306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
165162306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
165262306a36Sopenharmony_ci	mcp->flags = 0;
165362306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
165462306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
165562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1043, "Failed=%x.\n", rval);
165662306a36Sopenharmony_ci	}
165762306a36Sopenharmony_ci
165862306a36Sopenharmony_ci	/* Issue marker IOCB. */
165962306a36Sopenharmony_ci	rval2 = qla2x00_marker(vha, vha->hw->base_qpair, fcport->loop_id, l,
166062306a36Sopenharmony_ci								MK_SYNC_ID_LUN);
166162306a36Sopenharmony_ci	if (rval2 != QLA_SUCCESS) {
166262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1044,
166362306a36Sopenharmony_ci		    "Failed to issue marker IOCB (%x).\n", rval2);
166462306a36Sopenharmony_ci	} else {
166562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1045,
166662306a36Sopenharmony_ci		    "Done %s.\n", __func__);
166762306a36Sopenharmony_ci	}
166862306a36Sopenharmony_ci
166962306a36Sopenharmony_ci	return rval;
167062306a36Sopenharmony_ci}
167162306a36Sopenharmony_ci
167262306a36Sopenharmony_ci/*
167362306a36Sopenharmony_ci * qla2x00_get_adapter_id
167462306a36Sopenharmony_ci *	Get adapter ID and topology.
167562306a36Sopenharmony_ci *
167662306a36Sopenharmony_ci * Input:
167762306a36Sopenharmony_ci *	ha = adapter block pointer.
167862306a36Sopenharmony_ci *	id = pointer for loop ID.
167962306a36Sopenharmony_ci *	al_pa = pointer for AL_PA.
168062306a36Sopenharmony_ci *	area = pointer for area.
168162306a36Sopenharmony_ci *	domain = pointer for domain.
168262306a36Sopenharmony_ci *	top = pointer for topology.
168362306a36Sopenharmony_ci *	TARGET_QUEUE_LOCK must be released.
168462306a36Sopenharmony_ci *	ADAPTER_STATE_LOCK must be released.
168562306a36Sopenharmony_ci *
168662306a36Sopenharmony_ci * Returns:
168762306a36Sopenharmony_ci *	qla2x00 local function return status code.
168862306a36Sopenharmony_ci *
168962306a36Sopenharmony_ci * Context:
169062306a36Sopenharmony_ci *	Kernel context.
169162306a36Sopenharmony_ci */
169262306a36Sopenharmony_ciint
169362306a36Sopenharmony_ciqla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
169462306a36Sopenharmony_ci    uint8_t *area, uint8_t *domain, uint16_t *top, uint16_t *sw_cap)
169562306a36Sopenharmony_ci{
169662306a36Sopenharmony_ci	int rval;
169762306a36Sopenharmony_ci	mbx_cmd_t mc;
169862306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
169962306a36Sopenharmony_ci
170062306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1046,
170162306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
170262306a36Sopenharmony_ci
170362306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID;
170462306a36Sopenharmony_ci	mcp->mb[9] = vha->vp_idx;
170562306a36Sopenharmony_ci	mcp->out_mb = MBX_9|MBX_0;
170662306a36Sopenharmony_ci	mcp->in_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
170762306a36Sopenharmony_ci	if (IS_CNA_CAPABLE(vha->hw))
170862306a36Sopenharmony_ci		mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10;
170962306a36Sopenharmony_ci	if (IS_FWI2_CAPABLE(vha->hw))
171062306a36Sopenharmony_ci		mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16;
171162306a36Sopenharmony_ci	if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw))
171262306a36Sopenharmony_ci		mcp->in_mb |= MBX_15|MBX_21|MBX_22|MBX_23;
171362306a36Sopenharmony_ci
171462306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
171562306a36Sopenharmony_ci	mcp->flags = 0;
171662306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
171762306a36Sopenharmony_ci	if (mcp->mb[0] == MBS_COMMAND_ERROR)
171862306a36Sopenharmony_ci		rval = QLA_COMMAND_ERROR;
171962306a36Sopenharmony_ci	else if (mcp->mb[0] == MBS_INVALID_COMMAND)
172062306a36Sopenharmony_ci		rval = QLA_INVALID_COMMAND;
172162306a36Sopenharmony_ci
172262306a36Sopenharmony_ci	/* Return data. */
172362306a36Sopenharmony_ci	*id = mcp->mb[1];
172462306a36Sopenharmony_ci	*al_pa = LSB(mcp->mb[2]);
172562306a36Sopenharmony_ci	*area = MSB(mcp->mb[2]);
172662306a36Sopenharmony_ci	*domain	= LSB(mcp->mb[3]);
172762306a36Sopenharmony_ci	*top = mcp->mb[6];
172862306a36Sopenharmony_ci	*sw_cap = mcp->mb[7];
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
173162306a36Sopenharmony_ci		/*EMPTY*/
173262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1047, "Failed=%x.\n", rval);
173362306a36Sopenharmony_ci	} else {
173462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1048,
173562306a36Sopenharmony_ci		    "Done %s.\n", __func__);
173662306a36Sopenharmony_ci
173762306a36Sopenharmony_ci		if (IS_CNA_CAPABLE(vha->hw)) {
173862306a36Sopenharmony_ci			vha->fcoe_vlan_id = mcp->mb[9] & 0xfff;
173962306a36Sopenharmony_ci			vha->fcoe_fcf_idx = mcp->mb[10];
174062306a36Sopenharmony_ci			vha->fcoe_vn_port_mac[5] = mcp->mb[11] >> 8;
174162306a36Sopenharmony_ci			vha->fcoe_vn_port_mac[4] = mcp->mb[11] & 0xff;
174262306a36Sopenharmony_ci			vha->fcoe_vn_port_mac[3] = mcp->mb[12] >> 8;
174362306a36Sopenharmony_ci			vha->fcoe_vn_port_mac[2] = mcp->mb[12] & 0xff;
174462306a36Sopenharmony_ci			vha->fcoe_vn_port_mac[1] = mcp->mb[13] >> 8;
174562306a36Sopenharmony_ci			vha->fcoe_vn_port_mac[0] = mcp->mb[13] & 0xff;
174662306a36Sopenharmony_ci		}
174762306a36Sopenharmony_ci		/* If FA-WWN supported */
174862306a36Sopenharmony_ci		if (IS_FAWWN_CAPABLE(vha->hw)) {
174962306a36Sopenharmony_ci			if (mcp->mb[7] & BIT_14) {
175062306a36Sopenharmony_ci				vha->port_name[0] = MSB(mcp->mb[16]);
175162306a36Sopenharmony_ci				vha->port_name[1] = LSB(mcp->mb[16]);
175262306a36Sopenharmony_ci				vha->port_name[2] = MSB(mcp->mb[17]);
175362306a36Sopenharmony_ci				vha->port_name[3] = LSB(mcp->mb[17]);
175462306a36Sopenharmony_ci				vha->port_name[4] = MSB(mcp->mb[18]);
175562306a36Sopenharmony_ci				vha->port_name[5] = LSB(mcp->mb[18]);
175662306a36Sopenharmony_ci				vha->port_name[6] = MSB(mcp->mb[19]);
175762306a36Sopenharmony_ci				vha->port_name[7] = LSB(mcp->mb[19]);
175862306a36Sopenharmony_ci				fc_host_port_name(vha->host) =
175962306a36Sopenharmony_ci				    wwn_to_u64(vha->port_name);
176062306a36Sopenharmony_ci				ql_dbg(ql_dbg_mbx, vha, 0x10ca,
176162306a36Sopenharmony_ci				    "FA-WWN acquired %016llx\n",
176262306a36Sopenharmony_ci				    wwn_to_u64(vha->port_name));
176362306a36Sopenharmony_ci			}
176462306a36Sopenharmony_ci		}
176562306a36Sopenharmony_ci
176662306a36Sopenharmony_ci		if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) {
176762306a36Sopenharmony_ci			vha->bbcr = mcp->mb[15];
176862306a36Sopenharmony_ci			if (mcp->mb[7] & SCM_EDC_ACC_RECEIVED) {
176962306a36Sopenharmony_ci				ql_log(ql_log_info, vha, 0x11a4,
177062306a36Sopenharmony_ci				       "SCM: EDC ELS completed, flags 0x%x\n",
177162306a36Sopenharmony_ci				       mcp->mb[21]);
177262306a36Sopenharmony_ci			}
177362306a36Sopenharmony_ci			if (mcp->mb[7] & SCM_RDF_ACC_RECEIVED) {
177462306a36Sopenharmony_ci				vha->hw->flags.scm_enabled = 1;
177562306a36Sopenharmony_ci				vha->scm_fabric_connection_flags |=
177662306a36Sopenharmony_ci				    SCM_FLAG_RDF_COMPLETED;
177762306a36Sopenharmony_ci				ql_log(ql_log_info, vha, 0x11a5,
177862306a36Sopenharmony_ci				       "SCM: RDF ELS completed, flags 0x%x\n",
177962306a36Sopenharmony_ci				       mcp->mb[23]);
178062306a36Sopenharmony_ci			}
178162306a36Sopenharmony_ci		}
178262306a36Sopenharmony_ci	}
178362306a36Sopenharmony_ci
178462306a36Sopenharmony_ci	return rval;
178562306a36Sopenharmony_ci}
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci/*
178862306a36Sopenharmony_ci * qla2x00_get_retry_cnt
178962306a36Sopenharmony_ci *	Get current firmware login retry count and delay.
179062306a36Sopenharmony_ci *
179162306a36Sopenharmony_ci * Input:
179262306a36Sopenharmony_ci *	ha = adapter block pointer.
179362306a36Sopenharmony_ci *	retry_cnt = pointer to login retry count.
179462306a36Sopenharmony_ci *	tov = pointer to login timeout value.
179562306a36Sopenharmony_ci *
179662306a36Sopenharmony_ci * Returns:
179762306a36Sopenharmony_ci *	qla2x00 local function return status code.
179862306a36Sopenharmony_ci *
179962306a36Sopenharmony_ci * Context:
180062306a36Sopenharmony_ci *	Kernel context.
180162306a36Sopenharmony_ci */
180262306a36Sopenharmony_ciint
180362306a36Sopenharmony_ciqla2x00_get_retry_cnt(scsi_qla_host_t *vha, uint8_t *retry_cnt, uint8_t *tov,
180462306a36Sopenharmony_ci    uint16_t *r_a_tov)
180562306a36Sopenharmony_ci{
180662306a36Sopenharmony_ci	int rval;
180762306a36Sopenharmony_ci	uint16_t ratov;
180862306a36Sopenharmony_ci	mbx_cmd_t mc;
180962306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
181062306a36Sopenharmony_ci
181162306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1049,
181262306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
181362306a36Sopenharmony_ci
181462306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_RETRY_COUNT;
181562306a36Sopenharmony_ci	mcp->out_mb = MBX_0;
181662306a36Sopenharmony_ci	mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
181762306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
181862306a36Sopenharmony_ci	mcp->flags = 0;
181962306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
182062306a36Sopenharmony_ci
182162306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
182262306a36Sopenharmony_ci		/*EMPTY*/
182362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x104a,
182462306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
182562306a36Sopenharmony_ci	} else {
182662306a36Sopenharmony_ci		/* Convert returned data and check our values. */
182762306a36Sopenharmony_ci		*r_a_tov = mcp->mb[3] / 2;
182862306a36Sopenharmony_ci		ratov = (mcp->mb[3]/2) / 10;  /* mb[3] value is in 100ms */
182962306a36Sopenharmony_ci		if (mcp->mb[1] * ratov > (*retry_cnt) * (*tov)) {
183062306a36Sopenharmony_ci			/* Update to the larger values */
183162306a36Sopenharmony_ci			*retry_cnt = (uint8_t)mcp->mb[1];
183262306a36Sopenharmony_ci			*tov = ratov;
183362306a36Sopenharmony_ci		}
183462306a36Sopenharmony_ci
183562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104b,
183662306a36Sopenharmony_ci		    "Done %s mb3=%d ratov=%d.\n", __func__, mcp->mb[3], ratov);
183762306a36Sopenharmony_ci	}
183862306a36Sopenharmony_ci
183962306a36Sopenharmony_ci	return rval;
184062306a36Sopenharmony_ci}
184162306a36Sopenharmony_ci
184262306a36Sopenharmony_ci/*
184362306a36Sopenharmony_ci * qla2x00_init_firmware
184462306a36Sopenharmony_ci *	Initialize adapter firmware.
184562306a36Sopenharmony_ci *
184662306a36Sopenharmony_ci * Input:
184762306a36Sopenharmony_ci *	ha = adapter block pointer.
184862306a36Sopenharmony_ci *	dptr = Initialization control block pointer.
184962306a36Sopenharmony_ci *	size = size of initialization control block.
185062306a36Sopenharmony_ci *	TARGET_QUEUE_LOCK must be released.
185162306a36Sopenharmony_ci *	ADAPTER_STATE_LOCK must be released.
185262306a36Sopenharmony_ci *
185362306a36Sopenharmony_ci * Returns:
185462306a36Sopenharmony_ci *	qla2x00 local function return status code.
185562306a36Sopenharmony_ci *
185662306a36Sopenharmony_ci * Context:
185762306a36Sopenharmony_ci *	Kernel context.
185862306a36Sopenharmony_ci */
185962306a36Sopenharmony_ciint
186062306a36Sopenharmony_ciqla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
186162306a36Sopenharmony_ci{
186262306a36Sopenharmony_ci	int rval;
186362306a36Sopenharmony_ci	mbx_cmd_t mc;
186462306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
186562306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
186662306a36Sopenharmony_ci
186762306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104c,
186862306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
186962306a36Sopenharmony_ci
187062306a36Sopenharmony_ci	if (IS_P3P_TYPE(ha) && ql2xdbwr)
187162306a36Sopenharmony_ci		qla82xx_wr_32(ha, (uintptr_t __force)ha->nxdb_wr_ptr,
187262306a36Sopenharmony_ci			(0x04 | (ha->portnum << 5) | (0 << 8) | (0 << 16)));
187362306a36Sopenharmony_ci
187462306a36Sopenharmony_ci	if (ha->flags.npiv_supported)
187562306a36Sopenharmony_ci		mcp->mb[0] = MBC_MID_INITIALIZE_FIRMWARE;
187662306a36Sopenharmony_ci	else
187762306a36Sopenharmony_ci		mcp->mb[0] = MBC_INITIALIZE_FIRMWARE;
187862306a36Sopenharmony_ci
187962306a36Sopenharmony_ci	mcp->mb[1] = 0;
188062306a36Sopenharmony_ci	mcp->mb[2] = MSW(ha->init_cb_dma);
188162306a36Sopenharmony_ci	mcp->mb[3] = LSW(ha->init_cb_dma);
188262306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(ha->init_cb_dma));
188362306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(ha->init_cb_dma));
188462306a36Sopenharmony_ci	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
188562306a36Sopenharmony_ci	if (ha->ex_init_cb && ha->ex_init_cb->ex_version) {
188662306a36Sopenharmony_ci		mcp->mb[1] = BIT_0;
188762306a36Sopenharmony_ci		mcp->mb[10] = MSW(ha->ex_init_cb_dma);
188862306a36Sopenharmony_ci		mcp->mb[11] = LSW(ha->ex_init_cb_dma);
188962306a36Sopenharmony_ci		mcp->mb[12] = MSW(MSD(ha->ex_init_cb_dma));
189062306a36Sopenharmony_ci		mcp->mb[13] = LSW(MSD(ha->ex_init_cb_dma));
189162306a36Sopenharmony_ci		mcp->mb[14] = sizeof(*ha->ex_init_cb);
189262306a36Sopenharmony_ci		mcp->out_mb |= MBX_14|MBX_13|MBX_12|MBX_11|MBX_10;
189362306a36Sopenharmony_ci	}
189462306a36Sopenharmony_ci
189562306a36Sopenharmony_ci	if (ha->flags.scm_supported_f || vha->flags.nvme2_enabled) {
189662306a36Sopenharmony_ci		mcp->mb[1] |= BIT_1;
189762306a36Sopenharmony_ci		mcp->mb[16] = MSW(ha->sf_init_cb_dma);
189862306a36Sopenharmony_ci		mcp->mb[17] = LSW(ha->sf_init_cb_dma);
189962306a36Sopenharmony_ci		mcp->mb[18] = MSW(MSD(ha->sf_init_cb_dma));
190062306a36Sopenharmony_ci		mcp->mb[19] = LSW(MSD(ha->sf_init_cb_dma));
190162306a36Sopenharmony_ci		mcp->mb[15] = sizeof(*ha->sf_init_cb);
190262306a36Sopenharmony_ci		mcp->out_mb |= MBX_19|MBX_18|MBX_17|MBX_16|MBX_15;
190362306a36Sopenharmony_ci	}
190462306a36Sopenharmony_ci
190562306a36Sopenharmony_ci	/* 1 and 2 should normally be captured. */
190662306a36Sopenharmony_ci	mcp->in_mb = MBX_2|MBX_1|MBX_0;
190762306a36Sopenharmony_ci	if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
190862306a36Sopenharmony_ci		/* mb3 is additional info about the installed SFP. */
190962306a36Sopenharmony_ci		mcp->in_mb  |= MBX_3;
191062306a36Sopenharmony_ci	mcp->buf_size = size;
191162306a36Sopenharmony_ci	mcp->flags = MBX_DMA_OUT;
191262306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
191362306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
191462306a36Sopenharmony_ci
191562306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
191662306a36Sopenharmony_ci		/*EMPTY*/
191762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x104d,
191862306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x.\n",
191962306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3]);
192062306a36Sopenharmony_ci		if (ha->init_cb) {
192162306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x104d, "init_cb:\n");
192262306a36Sopenharmony_ci			ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha,
192362306a36Sopenharmony_ci			    0x0104d, ha->init_cb, sizeof(*ha->init_cb));
192462306a36Sopenharmony_ci		}
192562306a36Sopenharmony_ci		if (ha->ex_init_cb && ha->ex_init_cb->ex_version) {
192662306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x104d, "ex_init_cb:\n");
192762306a36Sopenharmony_ci			ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha,
192862306a36Sopenharmony_ci			    0x0104d, ha->ex_init_cb, sizeof(*ha->ex_init_cb));
192962306a36Sopenharmony_ci		}
193062306a36Sopenharmony_ci	} else {
193162306a36Sopenharmony_ci		if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
193262306a36Sopenharmony_ci			if (mcp->mb[2] == 6 || mcp->mb[3] == 2)
193362306a36Sopenharmony_ci				ql_dbg(ql_dbg_mbx, vha, 0x119d,
193462306a36Sopenharmony_ci				    "Invalid SFP/Validation Failed\n");
193562306a36Sopenharmony_ci		}
193662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104e,
193762306a36Sopenharmony_ci		    "Done %s.\n", __func__);
193862306a36Sopenharmony_ci	}
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ci	return rval;
194162306a36Sopenharmony_ci}
194262306a36Sopenharmony_ci
194362306a36Sopenharmony_ci
194462306a36Sopenharmony_ci/*
194562306a36Sopenharmony_ci * qla2x00_get_port_database
194662306a36Sopenharmony_ci *	Issue normal/enhanced get port database mailbox command
194762306a36Sopenharmony_ci *	and copy device name as necessary.
194862306a36Sopenharmony_ci *
194962306a36Sopenharmony_ci * Input:
195062306a36Sopenharmony_ci *	ha = adapter state pointer.
195162306a36Sopenharmony_ci *	dev = structure pointer.
195262306a36Sopenharmony_ci *	opt = enhanced cmd option byte.
195362306a36Sopenharmony_ci *
195462306a36Sopenharmony_ci * Returns:
195562306a36Sopenharmony_ci *	qla2x00 local function return status code.
195662306a36Sopenharmony_ci *
195762306a36Sopenharmony_ci * Context:
195862306a36Sopenharmony_ci *	Kernel context.
195962306a36Sopenharmony_ci */
196062306a36Sopenharmony_ciint
196162306a36Sopenharmony_ciqla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
196262306a36Sopenharmony_ci{
196362306a36Sopenharmony_ci	int rval;
196462306a36Sopenharmony_ci	mbx_cmd_t mc;
196562306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
196662306a36Sopenharmony_ci	port_database_t *pd;
196762306a36Sopenharmony_ci	struct port_database_24xx *pd24;
196862306a36Sopenharmony_ci	dma_addr_t pd_dma;
196962306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
197062306a36Sopenharmony_ci
197162306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104f,
197262306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
197362306a36Sopenharmony_ci
197462306a36Sopenharmony_ci	pd24 = NULL;
197562306a36Sopenharmony_ci	pd = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
197662306a36Sopenharmony_ci	if (pd  == NULL) {
197762306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x1050,
197862306a36Sopenharmony_ci		    "Failed to allocate port database structure.\n");
197962306a36Sopenharmony_ci		fcport->query = 0;
198062306a36Sopenharmony_ci		return QLA_MEMORY_ALLOC_FAILED;
198162306a36Sopenharmony_ci	}
198262306a36Sopenharmony_ci
198362306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_PORT_DATABASE;
198462306a36Sopenharmony_ci	if (opt != 0 && !IS_FWI2_CAPABLE(ha))
198562306a36Sopenharmony_ci		mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE;
198662306a36Sopenharmony_ci	mcp->mb[2] = MSW(pd_dma);
198762306a36Sopenharmony_ci	mcp->mb[3] = LSW(pd_dma);
198862306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(pd_dma));
198962306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(pd_dma));
199062306a36Sopenharmony_ci	mcp->mb[9] = vha->vp_idx;
199162306a36Sopenharmony_ci	mcp->out_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
199262306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
199362306a36Sopenharmony_ci	if (IS_FWI2_CAPABLE(ha)) {
199462306a36Sopenharmony_ci		mcp->mb[1] = fcport->loop_id;
199562306a36Sopenharmony_ci		mcp->mb[10] = opt;
199662306a36Sopenharmony_ci		mcp->out_mb |= MBX_10|MBX_1;
199762306a36Sopenharmony_ci		mcp->in_mb |= MBX_1;
199862306a36Sopenharmony_ci	} else if (HAS_EXTENDED_IDS(ha)) {
199962306a36Sopenharmony_ci		mcp->mb[1] = fcport->loop_id;
200062306a36Sopenharmony_ci		mcp->mb[10] = opt;
200162306a36Sopenharmony_ci		mcp->out_mb |= MBX_10|MBX_1;
200262306a36Sopenharmony_ci	} else {
200362306a36Sopenharmony_ci		mcp->mb[1] = fcport->loop_id << 8 | opt;
200462306a36Sopenharmony_ci		mcp->out_mb |= MBX_1;
200562306a36Sopenharmony_ci	}
200662306a36Sopenharmony_ci	mcp->buf_size = IS_FWI2_CAPABLE(ha) ?
200762306a36Sopenharmony_ci	    PORT_DATABASE_24XX_SIZE : PORT_DATABASE_SIZE;
200862306a36Sopenharmony_ci	mcp->flags = MBX_DMA_IN;
200962306a36Sopenharmony_ci	mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
201062306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
201162306a36Sopenharmony_ci	if (rval != QLA_SUCCESS)
201262306a36Sopenharmony_ci		goto gpd_error_out;
201362306a36Sopenharmony_ci
201462306a36Sopenharmony_ci	if (IS_FWI2_CAPABLE(ha)) {
201562306a36Sopenharmony_ci		uint64_t zero = 0;
201662306a36Sopenharmony_ci		u8 current_login_state, last_login_state;
201762306a36Sopenharmony_ci
201862306a36Sopenharmony_ci		pd24 = (struct port_database_24xx *) pd;
201962306a36Sopenharmony_ci
202062306a36Sopenharmony_ci		/* Check for logged in state. */
202162306a36Sopenharmony_ci		if (NVME_TARGET(ha, fcport)) {
202262306a36Sopenharmony_ci			current_login_state = pd24->current_login_state >> 4;
202362306a36Sopenharmony_ci			last_login_state = pd24->last_login_state >> 4;
202462306a36Sopenharmony_ci		} else {
202562306a36Sopenharmony_ci			current_login_state = pd24->current_login_state & 0xf;
202662306a36Sopenharmony_ci			last_login_state = pd24->last_login_state & 0xf;
202762306a36Sopenharmony_ci		}
202862306a36Sopenharmony_ci		fcport->current_login_state = pd24->current_login_state;
202962306a36Sopenharmony_ci		fcport->last_login_state = pd24->last_login_state;
203062306a36Sopenharmony_ci
203162306a36Sopenharmony_ci		/* Check for logged in state. */
203262306a36Sopenharmony_ci		if (current_login_state != PDS_PRLI_COMPLETE &&
203362306a36Sopenharmony_ci		    last_login_state != PDS_PRLI_COMPLETE) {
203462306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x119a,
203562306a36Sopenharmony_ci			    "Unable to verify login-state (%x/%x) for loop_id %x.\n",
203662306a36Sopenharmony_ci			    current_login_state, last_login_state,
203762306a36Sopenharmony_ci			    fcport->loop_id);
203862306a36Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
203962306a36Sopenharmony_ci
204062306a36Sopenharmony_ci			if (!fcport->query)
204162306a36Sopenharmony_ci				goto gpd_error_out;
204262306a36Sopenharmony_ci		}
204362306a36Sopenharmony_ci
204462306a36Sopenharmony_ci		if (fcport->loop_id == FC_NO_LOOP_ID ||
204562306a36Sopenharmony_ci		    (memcmp(fcport->port_name, (uint8_t *)&zero, 8) &&
204662306a36Sopenharmony_ci		     memcmp(fcport->port_name, pd24->port_name, 8))) {
204762306a36Sopenharmony_ci			/* We lost the device mid way. */
204862306a36Sopenharmony_ci			rval = QLA_NOT_LOGGED_IN;
204962306a36Sopenharmony_ci			goto gpd_error_out;
205062306a36Sopenharmony_ci		}
205162306a36Sopenharmony_ci
205262306a36Sopenharmony_ci		/* Names are little-endian. */
205362306a36Sopenharmony_ci		memcpy(fcport->node_name, pd24->node_name, WWN_SIZE);
205462306a36Sopenharmony_ci		memcpy(fcport->port_name, pd24->port_name, WWN_SIZE);
205562306a36Sopenharmony_ci
205662306a36Sopenharmony_ci		/* Get port_id of device. */
205762306a36Sopenharmony_ci		fcport->d_id.b.domain = pd24->port_id[0];
205862306a36Sopenharmony_ci		fcport->d_id.b.area = pd24->port_id[1];
205962306a36Sopenharmony_ci		fcport->d_id.b.al_pa = pd24->port_id[2];
206062306a36Sopenharmony_ci		fcport->d_id.b.rsvd_1 = 0;
206162306a36Sopenharmony_ci
206262306a36Sopenharmony_ci		/* If not target must be initiator or unknown type. */
206362306a36Sopenharmony_ci		if ((pd24->prli_svc_param_word_3[0] & BIT_4) == 0)
206462306a36Sopenharmony_ci			fcport->port_type = FCT_INITIATOR;
206562306a36Sopenharmony_ci		else
206662306a36Sopenharmony_ci			fcport->port_type = FCT_TARGET;
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_ci		/* Passback COS information. */
206962306a36Sopenharmony_ci		fcport->supported_classes = (pd24->flags & PDF_CLASS_2) ?
207062306a36Sopenharmony_ci				FC_COS_CLASS2 : FC_COS_CLASS3;
207162306a36Sopenharmony_ci
207262306a36Sopenharmony_ci		if (pd24->prli_svc_param_word_3[0] & BIT_7)
207362306a36Sopenharmony_ci			fcport->flags |= FCF_CONF_COMP_SUPPORTED;
207462306a36Sopenharmony_ci	} else {
207562306a36Sopenharmony_ci		uint64_t zero = 0;
207662306a36Sopenharmony_ci
207762306a36Sopenharmony_ci		/* Check for logged in state. */
207862306a36Sopenharmony_ci		if (pd->master_state != PD_STATE_PORT_LOGGED_IN &&
207962306a36Sopenharmony_ci		    pd->slave_state != PD_STATE_PORT_LOGGED_IN) {
208062306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x100a,
208162306a36Sopenharmony_ci			    "Unable to verify login-state (%x/%x) - "
208262306a36Sopenharmony_ci			    "portid=%02x%02x%02x.\n", pd->master_state,
208362306a36Sopenharmony_ci			    pd->slave_state, fcport->d_id.b.domain,
208462306a36Sopenharmony_ci			    fcport->d_id.b.area, fcport->d_id.b.al_pa);
208562306a36Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
208662306a36Sopenharmony_ci			goto gpd_error_out;
208762306a36Sopenharmony_ci		}
208862306a36Sopenharmony_ci
208962306a36Sopenharmony_ci		if (fcport->loop_id == FC_NO_LOOP_ID ||
209062306a36Sopenharmony_ci		    (memcmp(fcport->port_name, (uint8_t *)&zero, 8) &&
209162306a36Sopenharmony_ci		     memcmp(fcport->port_name, pd->port_name, 8))) {
209262306a36Sopenharmony_ci			/* We lost the device mid way. */
209362306a36Sopenharmony_ci			rval = QLA_NOT_LOGGED_IN;
209462306a36Sopenharmony_ci			goto gpd_error_out;
209562306a36Sopenharmony_ci		}
209662306a36Sopenharmony_ci
209762306a36Sopenharmony_ci		/* Names are little-endian. */
209862306a36Sopenharmony_ci		memcpy(fcport->node_name, pd->node_name, WWN_SIZE);
209962306a36Sopenharmony_ci		memcpy(fcport->port_name, pd->port_name, WWN_SIZE);
210062306a36Sopenharmony_ci
210162306a36Sopenharmony_ci		/* Get port_id of device. */
210262306a36Sopenharmony_ci		fcport->d_id.b.domain = pd->port_id[0];
210362306a36Sopenharmony_ci		fcport->d_id.b.area = pd->port_id[3];
210462306a36Sopenharmony_ci		fcport->d_id.b.al_pa = pd->port_id[2];
210562306a36Sopenharmony_ci		fcport->d_id.b.rsvd_1 = 0;
210662306a36Sopenharmony_ci
210762306a36Sopenharmony_ci		/* If not target must be initiator or unknown type. */
210862306a36Sopenharmony_ci		if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
210962306a36Sopenharmony_ci			fcport->port_type = FCT_INITIATOR;
211062306a36Sopenharmony_ci		else
211162306a36Sopenharmony_ci			fcport->port_type = FCT_TARGET;
211262306a36Sopenharmony_ci
211362306a36Sopenharmony_ci		/* Passback COS information. */
211462306a36Sopenharmony_ci		fcport->supported_classes = (pd->options & BIT_4) ?
211562306a36Sopenharmony_ci		    FC_COS_CLASS2 : FC_COS_CLASS3;
211662306a36Sopenharmony_ci	}
211762306a36Sopenharmony_ci
211862306a36Sopenharmony_cigpd_error_out:
211962306a36Sopenharmony_ci	dma_pool_free(ha->s_dma_pool, pd, pd_dma);
212062306a36Sopenharmony_ci	fcport->query = 0;
212162306a36Sopenharmony_ci
212262306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
212362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1052,
212462306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x.\n", rval,
212562306a36Sopenharmony_ci		    mcp->mb[0], mcp->mb[1]);
212662306a36Sopenharmony_ci	} else {
212762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1053,
212862306a36Sopenharmony_ci		    "Done %s.\n", __func__);
212962306a36Sopenharmony_ci	}
213062306a36Sopenharmony_ci
213162306a36Sopenharmony_ci	return rval;
213262306a36Sopenharmony_ci}
213362306a36Sopenharmony_ci
213462306a36Sopenharmony_ciint
213562306a36Sopenharmony_ciqla24xx_get_port_database(scsi_qla_host_t *vha, u16 nport_handle,
213662306a36Sopenharmony_ci	struct port_database_24xx *pdb)
213762306a36Sopenharmony_ci{
213862306a36Sopenharmony_ci	mbx_cmd_t mc;
213962306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
214062306a36Sopenharmony_ci	dma_addr_t pdb_dma;
214162306a36Sopenharmony_ci	int rval;
214262306a36Sopenharmony_ci
214362306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1115,
214462306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
214562306a36Sopenharmony_ci
214662306a36Sopenharmony_ci	memset(pdb, 0, sizeof(*pdb));
214762306a36Sopenharmony_ci
214862306a36Sopenharmony_ci	pdb_dma = dma_map_single(&vha->hw->pdev->dev, pdb,
214962306a36Sopenharmony_ci	    sizeof(*pdb), DMA_FROM_DEVICE);
215062306a36Sopenharmony_ci	if (!pdb_dma) {
215162306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x1116, "Failed to map dma buffer.\n");
215262306a36Sopenharmony_ci		return QLA_MEMORY_ALLOC_FAILED;
215362306a36Sopenharmony_ci	}
215462306a36Sopenharmony_ci
215562306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_PORT_DATABASE;
215662306a36Sopenharmony_ci	mcp->mb[1] = nport_handle;
215762306a36Sopenharmony_ci	mcp->mb[2] = MSW(LSD(pdb_dma));
215862306a36Sopenharmony_ci	mcp->mb[3] = LSW(LSD(pdb_dma));
215962306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(pdb_dma));
216062306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(pdb_dma));
216162306a36Sopenharmony_ci	mcp->mb[9] = 0;
216262306a36Sopenharmony_ci	mcp->mb[10] = 0;
216362306a36Sopenharmony_ci	mcp->out_mb = MBX_10|MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
216462306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
216562306a36Sopenharmony_ci	mcp->buf_size = sizeof(*pdb);
216662306a36Sopenharmony_ci	mcp->flags = MBX_DMA_IN;
216762306a36Sopenharmony_ci	mcp->tov = vha->hw->login_timeout * 2;
216862306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
216962306a36Sopenharmony_ci
217062306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
217162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x111a,
217262306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x.\n",
217362306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1]);
217462306a36Sopenharmony_ci	} else {
217562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x111b,
217662306a36Sopenharmony_ci		    "Done %s.\n", __func__);
217762306a36Sopenharmony_ci	}
217862306a36Sopenharmony_ci
217962306a36Sopenharmony_ci	dma_unmap_single(&vha->hw->pdev->dev, pdb_dma,
218062306a36Sopenharmony_ci	    sizeof(*pdb), DMA_FROM_DEVICE);
218162306a36Sopenharmony_ci
218262306a36Sopenharmony_ci	return rval;
218362306a36Sopenharmony_ci}
218462306a36Sopenharmony_ci
218562306a36Sopenharmony_ci/*
218662306a36Sopenharmony_ci * qla2x00_get_firmware_state
218762306a36Sopenharmony_ci *	Get adapter firmware state.
218862306a36Sopenharmony_ci *
218962306a36Sopenharmony_ci * Input:
219062306a36Sopenharmony_ci *	ha = adapter block pointer.
219162306a36Sopenharmony_ci *	dptr = pointer for firmware state.
219262306a36Sopenharmony_ci *	TARGET_QUEUE_LOCK must be released.
219362306a36Sopenharmony_ci *	ADAPTER_STATE_LOCK must be released.
219462306a36Sopenharmony_ci *
219562306a36Sopenharmony_ci * Returns:
219662306a36Sopenharmony_ci *	qla2x00 local function return status code.
219762306a36Sopenharmony_ci *
219862306a36Sopenharmony_ci * Context:
219962306a36Sopenharmony_ci *	Kernel context.
220062306a36Sopenharmony_ci */
220162306a36Sopenharmony_ciint
220262306a36Sopenharmony_ciqla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states)
220362306a36Sopenharmony_ci{
220462306a36Sopenharmony_ci	int rval;
220562306a36Sopenharmony_ci	mbx_cmd_t mc;
220662306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
220762306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
220862306a36Sopenharmony_ci
220962306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1054,
221062306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
221162306a36Sopenharmony_ci
221262306a36Sopenharmony_ci	if (!ha->flags.fw_started)
221362306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
221462306a36Sopenharmony_ci
221562306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
221662306a36Sopenharmony_ci	mcp->out_mb = MBX_0;
221762306a36Sopenharmony_ci	if (IS_FWI2_CAPABLE(vha->hw))
221862306a36Sopenharmony_ci		mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
221962306a36Sopenharmony_ci	else
222062306a36Sopenharmony_ci		mcp->in_mb = MBX_1|MBX_0;
222162306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
222262306a36Sopenharmony_ci	mcp->flags = 0;
222362306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
222462306a36Sopenharmony_ci
222562306a36Sopenharmony_ci	/* Return firmware states. */
222662306a36Sopenharmony_ci	states[0] = mcp->mb[1];
222762306a36Sopenharmony_ci	if (IS_FWI2_CAPABLE(vha->hw)) {
222862306a36Sopenharmony_ci		states[1] = mcp->mb[2];
222962306a36Sopenharmony_ci		states[2] = mcp->mb[3];  /* SFP info */
223062306a36Sopenharmony_ci		states[3] = mcp->mb[4];
223162306a36Sopenharmony_ci		states[4] = mcp->mb[5];
223262306a36Sopenharmony_ci		states[5] = mcp->mb[6];  /* DPORT status */
223362306a36Sopenharmony_ci	}
223462306a36Sopenharmony_ci
223562306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
223662306a36Sopenharmony_ci		/*EMPTY*/
223762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1055, "Failed=%x.\n", rval);
223862306a36Sopenharmony_ci	} else {
223962306a36Sopenharmony_ci		if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
224062306a36Sopenharmony_ci			if (mcp->mb[2] == 6 || mcp->mb[3] == 2)
224162306a36Sopenharmony_ci				ql_dbg(ql_dbg_mbx, vha, 0x119e,
224262306a36Sopenharmony_ci				    "Invalid SFP/Validation Failed\n");
224362306a36Sopenharmony_ci		}
224462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1056,
224562306a36Sopenharmony_ci		    "Done %s.\n", __func__);
224662306a36Sopenharmony_ci	}
224762306a36Sopenharmony_ci
224862306a36Sopenharmony_ci	return rval;
224962306a36Sopenharmony_ci}
225062306a36Sopenharmony_ci
225162306a36Sopenharmony_ci/*
225262306a36Sopenharmony_ci * qla2x00_get_port_name
225362306a36Sopenharmony_ci *	Issue get port name mailbox command.
225462306a36Sopenharmony_ci *	Returned name is in big endian format.
225562306a36Sopenharmony_ci *
225662306a36Sopenharmony_ci * Input:
225762306a36Sopenharmony_ci *	ha = adapter block pointer.
225862306a36Sopenharmony_ci *	loop_id = loop ID of device.
225962306a36Sopenharmony_ci *	name = pointer for name.
226062306a36Sopenharmony_ci *	TARGET_QUEUE_LOCK must be released.
226162306a36Sopenharmony_ci *	ADAPTER_STATE_LOCK must be released.
226262306a36Sopenharmony_ci *
226362306a36Sopenharmony_ci * Returns:
226462306a36Sopenharmony_ci *	qla2x00 local function return status code.
226562306a36Sopenharmony_ci *
226662306a36Sopenharmony_ci * Context:
226762306a36Sopenharmony_ci *	Kernel context.
226862306a36Sopenharmony_ci */
226962306a36Sopenharmony_ciint
227062306a36Sopenharmony_ciqla2x00_get_port_name(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t *name,
227162306a36Sopenharmony_ci    uint8_t opt)
227262306a36Sopenharmony_ci{
227362306a36Sopenharmony_ci	int rval;
227462306a36Sopenharmony_ci	mbx_cmd_t mc;
227562306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
227662306a36Sopenharmony_ci
227762306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1057,
227862306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
227962306a36Sopenharmony_ci
228062306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_PORT_NAME;
228162306a36Sopenharmony_ci	mcp->mb[9] = vha->vp_idx;
228262306a36Sopenharmony_ci	mcp->out_mb = MBX_9|MBX_1|MBX_0;
228362306a36Sopenharmony_ci	if (HAS_EXTENDED_IDS(vha->hw)) {
228462306a36Sopenharmony_ci		mcp->mb[1] = loop_id;
228562306a36Sopenharmony_ci		mcp->mb[10] = opt;
228662306a36Sopenharmony_ci		mcp->out_mb |= MBX_10;
228762306a36Sopenharmony_ci	} else {
228862306a36Sopenharmony_ci		mcp->mb[1] = loop_id << 8 | opt;
228962306a36Sopenharmony_ci	}
229062306a36Sopenharmony_ci
229162306a36Sopenharmony_ci	mcp->in_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
229262306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
229362306a36Sopenharmony_ci	mcp->flags = 0;
229462306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
229562306a36Sopenharmony_ci
229662306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
229762306a36Sopenharmony_ci		/*EMPTY*/
229862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1058, "Failed=%x.\n", rval);
229962306a36Sopenharmony_ci	} else {
230062306a36Sopenharmony_ci		if (name != NULL) {
230162306a36Sopenharmony_ci			/* This function returns name in big endian. */
230262306a36Sopenharmony_ci			name[0] = MSB(mcp->mb[2]);
230362306a36Sopenharmony_ci			name[1] = LSB(mcp->mb[2]);
230462306a36Sopenharmony_ci			name[2] = MSB(mcp->mb[3]);
230562306a36Sopenharmony_ci			name[3] = LSB(mcp->mb[3]);
230662306a36Sopenharmony_ci			name[4] = MSB(mcp->mb[6]);
230762306a36Sopenharmony_ci			name[5] = LSB(mcp->mb[6]);
230862306a36Sopenharmony_ci			name[6] = MSB(mcp->mb[7]);
230962306a36Sopenharmony_ci			name[7] = LSB(mcp->mb[7]);
231062306a36Sopenharmony_ci		}
231162306a36Sopenharmony_ci
231262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1059,
231362306a36Sopenharmony_ci		    "Done %s.\n", __func__);
231462306a36Sopenharmony_ci	}
231562306a36Sopenharmony_ci
231662306a36Sopenharmony_ci	return rval;
231762306a36Sopenharmony_ci}
231862306a36Sopenharmony_ci
231962306a36Sopenharmony_ci/*
232062306a36Sopenharmony_ci * qla24xx_link_initialization
232162306a36Sopenharmony_ci *	Issue link initialization mailbox command.
232262306a36Sopenharmony_ci *
232362306a36Sopenharmony_ci * Input:
232462306a36Sopenharmony_ci *	ha = adapter block pointer.
232562306a36Sopenharmony_ci *	TARGET_QUEUE_LOCK must be released.
232662306a36Sopenharmony_ci *	ADAPTER_STATE_LOCK must be released.
232762306a36Sopenharmony_ci *
232862306a36Sopenharmony_ci * Returns:
232962306a36Sopenharmony_ci *	qla2x00 local function return status code.
233062306a36Sopenharmony_ci *
233162306a36Sopenharmony_ci * Context:
233262306a36Sopenharmony_ci *	Kernel context.
233362306a36Sopenharmony_ci */
233462306a36Sopenharmony_ciint
233562306a36Sopenharmony_ciqla24xx_link_initialize(scsi_qla_host_t *vha)
233662306a36Sopenharmony_ci{
233762306a36Sopenharmony_ci	int rval;
233862306a36Sopenharmony_ci	mbx_cmd_t mc;
233962306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
234062306a36Sopenharmony_ci
234162306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1152,
234262306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
234362306a36Sopenharmony_ci
234462306a36Sopenharmony_ci	if (!IS_FWI2_CAPABLE(vha->hw) || IS_CNA_CAPABLE(vha->hw))
234562306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
234662306a36Sopenharmony_ci
234762306a36Sopenharmony_ci	mcp->mb[0] = MBC_LINK_INITIALIZATION;
234862306a36Sopenharmony_ci	mcp->mb[1] = BIT_4;
234962306a36Sopenharmony_ci	if (vha->hw->operating_mode == LOOP)
235062306a36Sopenharmony_ci		mcp->mb[1] |= BIT_6;
235162306a36Sopenharmony_ci	else
235262306a36Sopenharmony_ci		mcp->mb[1] |= BIT_5;
235362306a36Sopenharmony_ci	mcp->mb[2] = 0;
235462306a36Sopenharmony_ci	mcp->mb[3] = 0;
235562306a36Sopenharmony_ci	mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
235662306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
235762306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
235862306a36Sopenharmony_ci	mcp->flags = 0;
235962306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
236062306a36Sopenharmony_ci
236162306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
236262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1153, "Failed=%x.\n", rval);
236362306a36Sopenharmony_ci	} else {
236462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1154,
236562306a36Sopenharmony_ci		    "Done %s.\n", __func__);
236662306a36Sopenharmony_ci	}
236762306a36Sopenharmony_ci
236862306a36Sopenharmony_ci	return rval;
236962306a36Sopenharmony_ci}
237062306a36Sopenharmony_ci
237162306a36Sopenharmony_ci/*
237262306a36Sopenharmony_ci * qla2x00_lip_reset
237362306a36Sopenharmony_ci *	Issue LIP reset mailbox command.
237462306a36Sopenharmony_ci *
237562306a36Sopenharmony_ci * Input:
237662306a36Sopenharmony_ci *	ha = adapter block pointer.
237762306a36Sopenharmony_ci *	TARGET_QUEUE_LOCK must be released.
237862306a36Sopenharmony_ci *	ADAPTER_STATE_LOCK must be released.
237962306a36Sopenharmony_ci *
238062306a36Sopenharmony_ci * Returns:
238162306a36Sopenharmony_ci *	qla2x00 local function return status code.
238262306a36Sopenharmony_ci *
238362306a36Sopenharmony_ci * Context:
238462306a36Sopenharmony_ci *	Kernel context.
238562306a36Sopenharmony_ci */
238662306a36Sopenharmony_ciint
238762306a36Sopenharmony_ciqla2x00_lip_reset(scsi_qla_host_t *vha)
238862306a36Sopenharmony_ci{
238962306a36Sopenharmony_ci	int rval;
239062306a36Sopenharmony_ci	mbx_cmd_t mc;
239162306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
239262306a36Sopenharmony_ci
239362306a36Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x105a,
239462306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
239562306a36Sopenharmony_ci
239662306a36Sopenharmony_ci	if (IS_CNA_CAPABLE(vha->hw)) {
239762306a36Sopenharmony_ci		/* Logout across all FCFs. */
239862306a36Sopenharmony_ci		mcp->mb[0] = MBC_LIP_FULL_LOGIN;
239962306a36Sopenharmony_ci		mcp->mb[1] = BIT_1;
240062306a36Sopenharmony_ci		mcp->mb[2] = 0;
240162306a36Sopenharmony_ci		mcp->out_mb = MBX_2|MBX_1|MBX_0;
240262306a36Sopenharmony_ci	} else if (IS_FWI2_CAPABLE(vha->hw)) {
240362306a36Sopenharmony_ci		mcp->mb[0] = MBC_LIP_FULL_LOGIN;
240462306a36Sopenharmony_ci		mcp->mb[1] = BIT_4;
240562306a36Sopenharmony_ci		mcp->mb[2] = 0;
240662306a36Sopenharmony_ci		mcp->mb[3] = vha->hw->loop_reset_delay;
240762306a36Sopenharmony_ci		mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
240862306a36Sopenharmony_ci	} else {
240962306a36Sopenharmony_ci		mcp->mb[0] = MBC_LIP_RESET;
241062306a36Sopenharmony_ci		mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
241162306a36Sopenharmony_ci		if (HAS_EXTENDED_IDS(vha->hw)) {
241262306a36Sopenharmony_ci			mcp->mb[1] = 0x00ff;
241362306a36Sopenharmony_ci			mcp->mb[10] = 0;
241462306a36Sopenharmony_ci			mcp->out_mb |= MBX_10;
241562306a36Sopenharmony_ci		} else {
241662306a36Sopenharmony_ci			mcp->mb[1] = 0xff00;
241762306a36Sopenharmony_ci		}
241862306a36Sopenharmony_ci		mcp->mb[2] = vha->hw->loop_reset_delay;
241962306a36Sopenharmony_ci		mcp->mb[3] = 0;
242062306a36Sopenharmony_ci	}
242162306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
242262306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
242362306a36Sopenharmony_ci	mcp->flags = 0;
242462306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
242562306a36Sopenharmony_ci
242662306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
242762306a36Sopenharmony_ci		/*EMPTY*/
242862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x105b, "Failed=%x.\n", rval);
242962306a36Sopenharmony_ci	} else {
243062306a36Sopenharmony_ci		/*EMPTY*/
243162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105c,
243262306a36Sopenharmony_ci		    "Done %s.\n", __func__);
243362306a36Sopenharmony_ci	}
243462306a36Sopenharmony_ci
243562306a36Sopenharmony_ci	return rval;
243662306a36Sopenharmony_ci}
243762306a36Sopenharmony_ci
243862306a36Sopenharmony_ci/*
243962306a36Sopenharmony_ci * qla2x00_send_sns
244062306a36Sopenharmony_ci *	Send SNS command.
244162306a36Sopenharmony_ci *
244262306a36Sopenharmony_ci * Input:
244362306a36Sopenharmony_ci *	ha = adapter block pointer.
244462306a36Sopenharmony_ci *	sns = pointer for command.
244562306a36Sopenharmony_ci *	cmd_size = command size.
244662306a36Sopenharmony_ci *	buf_size = response/command size.
244762306a36Sopenharmony_ci *	TARGET_QUEUE_LOCK must be released.
244862306a36Sopenharmony_ci *	ADAPTER_STATE_LOCK must be released.
244962306a36Sopenharmony_ci *
245062306a36Sopenharmony_ci * Returns:
245162306a36Sopenharmony_ci *	qla2x00 local function return status code.
245262306a36Sopenharmony_ci *
245362306a36Sopenharmony_ci * Context:
245462306a36Sopenharmony_ci *	Kernel context.
245562306a36Sopenharmony_ci */
245662306a36Sopenharmony_ciint
245762306a36Sopenharmony_ciqla2x00_send_sns(scsi_qla_host_t *vha, dma_addr_t sns_phys_address,
245862306a36Sopenharmony_ci    uint16_t cmd_size, size_t buf_size)
245962306a36Sopenharmony_ci{
246062306a36Sopenharmony_ci	int rval;
246162306a36Sopenharmony_ci	mbx_cmd_t mc;
246262306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
246362306a36Sopenharmony_ci
246462306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105d,
246562306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
246662306a36Sopenharmony_ci
246762306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105e,
246862306a36Sopenharmony_ci	    "Retry cnt=%d ratov=%d total tov=%d.\n",
246962306a36Sopenharmony_ci	    vha->hw->retry_count, vha->hw->login_timeout, mcp->tov);
247062306a36Sopenharmony_ci
247162306a36Sopenharmony_ci	mcp->mb[0] = MBC_SEND_SNS_COMMAND;
247262306a36Sopenharmony_ci	mcp->mb[1] = cmd_size;
247362306a36Sopenharmony_ci	mcp->mb[2] = MSW(sns_phys_address);
247462306a36Sopenharmony_ci	mcp->mb[3] = LSW(sns_phys_address);
247562306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(sns_phys_address));
247662306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(sns_phys_address));
247762306a36Sopenharmony_ci	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
247862306a36Sopenharmony_ci	mcp->in_mb = MBX_0|MBX_1;
247962306a36Sopenharmony_ci	mcp->buf_size = buf_size;
248062306a36Sopenharmony_ci	mcp->flags = MBX_DMA_OUT|MBX_DMA_IN;
248162306a36Sopenharmony_ci	mcp->tov = (vha->hw->login_timeout * 2) + (vha->hw->login_timeout / 2);
248262306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
248362306a36Sopenharmony_ci
248462306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
248562306a36Sopenharmony_ci		/*EMPTY*/
248662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x105f,
248762306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x.\n",
248862306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1]);
248962306a36Sopenharmony_ci	} else {
249062306a36Sopenharmony_ci		/*EMPTY*/
249162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1060,
249262306a36Sopenharmony_ci		    "Done %s.\n", __func__);
249362306a36Sopenharmony_ci	}
249462306a36Sopenharmony_ci
249562306a36Sopenharmony_ci	return rval;
249662306a36Sopenharmony_ci}
249762306a36Sopenharmony_ci
249862306a36Sopenharmony_ciint
249962306a36Sopenharmony_ciqla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
250062306a36Sopenharmony_ci    uint8_t area, uint8_t al_pa, uint16_t *mb, uint8_t opt)
250162306a36Sopenharmony_ci{
250262306a36Sopenharmony_ci	int		rval;
250362306a36Sopenharmony_ci
250462306a36Sopenharmony_ci	struct logio_entry_24xx *lg;
250562306a36Sopenharmony_ci	dma_addr_t	lg_dma;
250662306a36Sopenharmony_ci	uint32_t	iop[2];
250762306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
250862306a36Sopenharmony_ci	struct req_que *req;
250962306a36Sopenharmony_ci
251062306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1061,
251162306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
251262306a36Sopenharmony_ci
251362306a36Sopenharmony_ci	if (vha->vp_idx && vha->qpair)
251462306a36Sopenharmony_ci		req = vha->qpair->req;
251562306a36Sopenharmony_ci	else
251662306a36Sopenharmony_ci		req = ha->req_q_map[0];
251762306a36Sopenharmony_ci
251862306a36Sopenharmony_ci	lg = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
251962306a36Sopenharmony_ci	if (lg == NULL) {
252062306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x1062,
252162306a36Sopenharmony_ci		    "Failed to allocate login IOCB.\n");
252262306a36Sopenharmony_ci		return QLA_MEMORY_ALLOC_FAILED;
252362306a36Sopenharmony_ci	}
252462306a36Sopenharmony_ci
252562306a36Sopenharmony_ci	lg->entry_type = LOGINOUT_PORT_IOCB_TYPE;
252662306a36Sopenharmony_ci	lg->entry_count = 1;
252762306a36Sopenharmony_ci	lg->handle = make_handle(req->id, lg->handle);
252862306a36Sopenharmony_ci	lg->nport_handle = cpu_to_le16(loop_id);
252962306a36Sopenharmony_ci	lg->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI);
253062306a36Sopenharmony_ci	if (opt & BIT_0)
253162306a36Sopenharmony_ci		lg->control_flags |= cpu_to_le16(LCF_COND_PLOGI);
253262306a36Sopenharmony_ci	if (opt & BIT_1)
253362306a36Sopenharmony_ci		lg->control_flags |= cpu_to_le16(LCF_SKIP_PRLI);
253462306a36Sopenharmony_ci	lg->port_id[0] = al_pa;
253562306a36Sopenharmony_ci	lg->port_id[1] = area;
253662306a36Sopenharmony_ci	lg->port_id[2] = domain;
253762306a36Sopenharmony_ci	lg->vp_index = vha->vp_idx;
253862306a36Sopenharmony_ci	rval = qla2x00_issue_iocb_timeout(vha, lg, lg_dma, 0,
253962306a36Sopenharmony_ci	    (ha->r_a_tov / 10 * 2) + 2);
254062306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
254162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1063,
254262306a36Sopenharmony_ci		    "Failed to issue login IOCB (%x).\n", rval);
254362306a36Sopenharmony_ci	} else if (lg->entry_status != 0) {
254462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1064,
254562306a36Sopenharmony_ci		    "Failed to complete IOCB -- error status (%x).\n",
254662306a36Sopenharmony_ci		    lg->entry_status);
254762306a36Sopenharmony_ci		rval = QLA_FUNCTION_FAILED;
254862306a36Sopenharmony_ci	} else if (lg->comp_status != cpu_to_le16(CS_COMPLETE)) {
254962306a36Sopenharmony_ci		iop[0] = le32_to_cpu(lg->io_parameter[0]);
255062306a36Sopenharmony_ci		iop[1] = le32_to_cpu(lg->io_parameter[1]);
255162306a36Sopenharmony_ci
255262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1065,
255362306a36Sopenharmony_ci		    "Failed to complete IOCB -- completion  status (%x) "
255462306a36Sopenharmony_ci		    "ioparam=%x/%x.\n", le16_to_cpu(lg->comp_status),
255562306a36Sopenharmony_ci		    iop[0], iop[1]);
255662306a36Sopenharmony_ci
255762306a36Sopenharmony_ci		switch (iop[0]) {
255862306a36Sopenharmony_ci		case LSC_SCODE_PORTID_USED:
255962306a36Sopenharmony_ci			mb[0] = MBS_PORT_ID_USED;
256062306a36Sopenharmony_ci			mb[1] = LSW(iop[1]);
256162306a36Sopenharmony_ci			break;
256262306a36Sopenharmony_ci		case LSC_SCODE_NPORT_USED:
256362306a36Sopenharmony_ci			mb[0] = MBS_LOOP_ID_USED;
256462306a36Sopenharmony_ci			break;
256562306a36Sopenharmony_ci		case LSC_SCODE_NOLINK:
256662306a36Sopenharmony_ci		case LSC_SCODE_NOIOCB:
256762306a36Sopenharmony_ci		case LSC_SCODE_NOXCB:
256862306a36Sopenharmony_ci		case LSC_SCODE_CMD_FAILED:
256962306a36Sopenharmony_ci		case LSC_SCODE_NOFABRIC:
257062306a36Sopenharmony_ci		case LSC_SCODE_FW_NOT_READY:
257162306a36Sopenharmony_ci		case LSC_SCODE_NOT_LOGGED_IN:
257262306a36Sopenharmony_ci		case LSC_SCODE_NOPCB:
257362306a36Sopenharmony_ci		case LSC_SCODE_ELS_REJECT:
257462306a36Sopenharmony_ci		case LSC_SCODE_CMD_PARAM_ERR:
257562306a36Sopenharmony_ci		case LSC_SCODE_NONPORT:
257662306a36Sopenharmony_ci		case LSC_SCODE_LOGGED_IN:
257762306a36Sopenharmony_ci		case LSC_SCODE_NOFLOGI_ACC:
257862306a36Sopenharmony_ci		default:
257962306a36Sopenharmony_ci			mb[0] = MBS_COMMAND_ERROR;
258062306a36Sopenharmony_ci			break;
258162306a36Sopenharmony_ci		}
258262306a36Sopenharmony_ci	} else {
258362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1066,
258462306a36Sopenharmony_ci		    "Done %s.\n", __func__);
258562306a36Sopenharmony_ci
258662306a36Sopenharmony_ci		iop[0] = le32_to_cpu(lg->io_parameter[0]);
258762306a36Sopenharmony_ci
258862306a36Sopenharmony_ci		mb[0] = MBS_COMMAND_COMPLETE;
258962306a36Sopenharmony_ci		mb[1] = 0;
259062306a36Sopenharmony_ci		if (iop[0] & BIT_4) {
259162306a36Sopenharmony_ci			if (iop[0] & BIT_8)
259262306a36Sopenharmony_ci				mb[1] |= BIT_1;
259362306a36Sopenharmony_ci		} else
259462306a36Sopenharmony_ci			mb[1] = BIT_0;
259562306a36Sopenharmony_ci
259662306a36Sopenharmony_ci		/* Passback COS information. */
259762306a36Sopenharmony_ci		mb[10] = 0;
259862306a36Sopenharmony_ci		if (lg->io_parameter[7] || lg->io_parameter[8])
259962306a36Sopenharmony_ci			mb[10] |= BIT_0;	/* Class 2. */
260062306a36Sopenharmony_ci		if (lg->io_parameter[9] || lg->io_parameter[10])
260162306a36Sopenharmony_ci			mb[10] |= BIT_1;	/* Class 3. */
260262306a36Sopenharmony_ci		if (lg->io_parameter[0] & cpu_to_le32(BIT_7))
260362306a36Sopenharmony_ci			mb[10] |= BIT_7;	/* Confirmed Completion
260462306a36Sopenharmony_ci						 * Allowed
260562306a36Sopenharmony_ci						 */
260662306a36Sopenharmony_ci	}
260762306a36Sopenharmony_ci
260862306a36Sopenharmony_ci	dma_pool_free(ha->s_dma_pool, lg, lg_dma);
260962306a36Sopenharmony_ci
261062306a36Sopenharmony_ci	return rval;
261162306a36Sopenharmony_ci}
261262306a36Sopenharmony_ci
261362306a36Sopenharmony_ci/*
261462306a36Sopenharmony_ci * qla2x00_login_fabric
261562306a36Sopenharmony_ci *	Issue login fabric port mailbox command.
261662306a36Sopenharmony_ci *
261762306a36Sopenharmony_ci * Input:
261862306a36Sopenharmony_ci *	ha = adapter block pointer.
261962306a36Sopenharmony_ci *	loop_id = device loop ID.
262062306a36Sopenharmony_ci *	domain = device domain.
262162306a36Sopenharmony_ci *	area = device area.
262262306a36Sopenharmony_ci *	al_pa = device AL_PA.
262362306a36Sopenharmony_ci *	status = pointer for return status.
262462306a36Sopenharmony_ci *	opt = command options.
262562306a36Sopenharmony_ci *	TARGET_QUEUE_LOCK must be released.
262662306a36Sopenharmony_ci *	ADAPTER_STATE_LOCK must be released.
262762306a36Sopenharmony_ci *
262862306a36Sopenharmony_ci * Returns:
262962306a36Sopenharmony_ci *	qla2x00 local function return status code.
263062306a36Sopenharmony_ci *
263162306a36Sopenharmony_ci * Context:
263262306a36Sopenharmony_ci *	Kernel context.
263362306a36Sopenharmony_ci */
263462306a36Sopenharmony_ciint
263562306a36Sopenharmony_ciqla2x00_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
263662306a36Sopenharmony_ci    uint8_t area, uint8_t al_pa, uint16_t *mb, uint8_t opt)
263762306a36Sopenharmony_ci{
263862306a36Sopenharmony_ci	int rval;
263962306a36Sopenharmony_ci	mbx_cmd_t mc;
264062306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
264162306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
264262306a36Sopenharmony_ci
264362306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1067,
264462306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
264562306a36Sopenharmony_ci
264662306a36Sopenharmony_ci	mcp->mb[0] = MBC_LOGIN_FABRIC_PORT;
264762306a36Sopenharmony_ci	mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
264862306a36Sopenharmony_ci	if (HAS_EXTENDED_IDS(ha)) {
264962306a36Sopenharmony_ci		mcp->mb[1] = loop_id;
265062306a36Sopenharmony_ci		mcp->mb[10] = opt;
265162306a36Sopenharmony_ci		mcp->out_mb |= MBX_10;
265262306a36Sopenharmony_ci	} else {
265362306a36Sopenharmony_ci		mcp->mb[1] = (loop_id << 8) | opt;
265462306a36Sopenharmony_ci	}
265562306a36Sopenharmony_ci	mcp->mb[2] = domain;
265662306a36Sopenharmony_ci	mcp->mb[3] = area << 8 | al_pa;
265762306a36Sopenharmony_ci
265862306a36Sopenharmony_ci	mcp->in_mb = MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
265962306a36Sopenharmony_ci	mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
266062306a36Sopenharmony_ci	mcp->flags = 0;
266162306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
266262306a36Sopenharmony_ci
266362306a36Sopenharmony_ci	/* Return mailbox statuses. */
266462306a36Sopenharmony_ci	if (mb != NULL) {
266562306a36Sopenharmony_ci		mb[0] = mcp->mb[0];
266662306a36Sopenharmony_ci		mb[1] = mcp->mb[1];
266762306a36Sopenharmony_ci		mb[2] = mcp->mb[2];
266862306a36Sopenharmony_ci		mb[6] = mcp->mb[6];
266962306a36Sopenharmony_ci		mb[7] = mcp->mb[7];
267062306a36Sopenharmony_ci		/* COS retrieved from Get-Port-Database mailbox command. */
267162306a36Sopenharmony_ci		mb[10] = 0;
267262306a36Sopenharmony_ci	}
267362306a36Sopenharmony_ci
267462306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
267562306a36Sopenharmony_ci		/* RLU tmp code: need to change main mailbox_command function to
267662306a36Sopenharmony_ci		 * return ok even when the mailbox completion value is not
267762306a36Sopenharmony_ci		 * SUCCESS. The caller needs to be responsible to interpret
267862306a36Sopenharmony_ci		 * the return values of this mailbox command if we're not
267962306a36Sopenharmony_ci		 * to change too much of the existing code.
268062306a36Sopenharmony_ci		 */
268162306a36Sopenharmony_ci		if (mcp->mb[0] == 0x4001 || mcp->mb[0] == 0x4002 ||
268262306a36Sopenharmony_ci		    mcp->mb[0] == 0x4003 || mcp->mb[0] == 0x4005 ||
268362306a36Sopenharmony_ci		    mcp->mb[0] == 0x4006)
268462306a36Sopenharmony_ci			rval = QLA_SUCCESS;
268562306a36Sopenharmony_ci
268662306a36Sopenharmony_ci		/*EMPTY*/
268762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1068,
268862306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
268962306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
269062306a36Sopenharmony_ci	} else {
269162306a36Sopenharmony_ci		/*EMPTY*/
269262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1069,
269362306a36Sopenharmony_ci		    "Done %s.\n", __func__);
269462306a36Sopenharmony_ci	}
269562306a36Sopenharmony_ci
269662306a36Sopenharmony_ci	return rval;
269762306a36Sopenharmony_ci}
269862306a36Sopenharmony_ci
269962306a36Sopenharmony_ci/*
270062306a36Sopenharmony_ci * qla2x00_login_local_device
270162306a36Sopenharmony_ci *           Issue login loop port mailbox command.
270262306a36Sopenharmony_ci *
270362306a36Sopenharmony_ci * Input:
270462306a36Sopenharmony_ci *           ha = adapter block pointer.
270562306a36Sopenharmony_ci *           loop_id = device loop ID.
270662306a36Sopenharmony_ci *           opt = command options.
270762306a36Sopenharmony_ci *
270862306a36Sopenharmony_ci * Returns:
270962306a36Sopenharmony_ci *            Return status code.
271062306a36Sopenharmony_ci *
271162306a36Sopenharmony_ci * Context:
271262306a36Sopenharmony_ci *            Kernel context.
271362306a36Sopenharmony_ci *
271462306a36Sopenharmony_ci */
271562306a36Sopenharmony_ciint
271662306a36Sopenharmony_ciqla2x00_login_local_device(scsi_qla_host_t *vha, fc_port_t *fcport,
271762306a36Sopenharmony_ci    uint16_t *mb_ret, uint8_t opt)
271862306a36Sopenharmony_ci{
271962306a36Sopenharmony_ci	int rval;
272062306a36Sopenharmony_ci	mbx_cmd_t mc;
272162306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
272262306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
272362306a36Sopenharmony_ci
272462306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106a,
272562306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
272662306a36Sopenharmony_ci
272762306a36Sopenharmony_ci	if (IS_FWI2_CAPABLE(ha))
272862306a36Sopenharmony_ci		return qla24xx_login_fabric(vha, fcport->loop_id,
272962306a36Sopenharmony_ci		    fcport->d_id.b.domain, fcport->d_id.b.area,
273062306a36Sopenharmony_ci		    fcport->d_id.b.al_pa, mb_ret, opt);
273162306a36Sopenharmony_ci
273262306a36Sopenharmony_ci	mcp->mb[0] = MBC_LOGIN_LOOP_PORT;
273362306a36Sopenharmony_ci	if (HAS_EXTENDED_IDS(ha))
273462306a36Sopenharmony_ci		mcp->mb[1] = fcport->loop_id;
273562306a36Sopenharmony_ci	else
273662306a36Sopenharmony_ci		mcp->mb[1] = fcport->loop_id << 8;
273762306a36Sopenharmony_ci	mcp->mb[2] = opt;
273862306a36Sopenharmony_ci	mcp->out_mb = MBX_2|MBX_1|MBX_0;
273962306a36Sopenharmony_ci 	mcp->in_mb = MBX_7|MBX_6|MBX_1|MBX_0;
274062306a36Sopenharmony_ci	mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
274162306a36Sopenharmony_ci	mcp->flags = 0;
274262306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
274362306a36Sopenharmony_ci
274462306a36Sopenharmony_ci 	/* Return mailbox statuses. */
274562306a36Sopenharmony_ci 	if (mb_ret != NULL) {
274662306a36Sopenharmony_ci 		mb_ret[0] = mcp->mb[0];
274762306a36Sopenharmony_ci 		mb_ret[1] = mcp->mb[1];
274862306a36Sopenharmony_ci 		mb_ret[6] = mcp->mb[6];
274962306a36Sopenharmony_ci 		mb_ret[7] = mcp->mb[7];
275062306a36Sopenharmony_ci 	}
275162306a36Sopenharmony_ci
275262306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
275362306a36Sopenharmony_ci 		/* AV tmp code: need to change main mailbox_command function to
275462306a36Sopenharmony_ci 		 * return ok even when the mailbox completion value is not
275562306a36Sopenharmony_ci 		 * SUCCESS. The caller needs to be responsible to interpret
275662306a36Sopenharmony_ci 		 * the return values of this mailbox command if we're not
275762306a36Sopenharmony_ci 		 * to change too much of the existing code.
275862306a36Sopenharmony_ci 		 */
275962306a36Sopenharmony_ci 		if (mcp->mb[0] == 0x4005 || mcp->mb[0] == 0x4006)
276062306a36Sopenharmony_ci 			rval = QLA_SUCCESS;
276162306a36Sopenharmony_ci
276262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x106b,
276362306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x mb[6]=%x mb[7]=%x.\n",
276462306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]);
276562306a36Sopenharmony_ci	} else {
276662306a36Sopenharmony_ci		/*EMPTY*/
276762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106c,
276862306a36Sopenharmony_ci		    "Done %s.\n", __func__);
276962306a36Sopenharmony_ci	}
277062306a36Sopenharmony_ci
277162306a36Sopenharmony_ci	return (rval);
277262306a36Sopenharmony_ci}
277362306a36Sopenharmony_ci
277462306a36Sopenharmony_ciint
277562306a36Sopenharmony_ciqla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
277662306a36Sopenharmony_ci    uint8_t area, uint8_t al_pa)
277762306a36Sopenharmony_ci{
277862306a36Sopenharmony_ci	int		rval;
277962306a36Sopenharmony_ci	struct logio_entry_24xx *lg;
278062306a36Sopenharmony_ci	dma_addr_t	lg_dma;
278162306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
278262306a36Sopenharmony_ci	struct req_que *req;
278362306a36Sopenharmony_ci
278462306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106d,
278562306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
278662306a36Sopenharmony_ci
278762306a36Sopenharmony_ci	lg = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
278862306a36Sopenharmony_ci	if (lg == NULL) {
278962306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x106e,
279062306a36Sopenharmony_ci		    "Failed to allocate logout IOCB.\n");
279162306a36Sopenharmony_ci		return QLA_MEMORY_ALLOC_FAILED;
279262306a36Sopenharmony_ci	}
279362306a36Sopenharmony_ci
279462306a36Sopenharmony_ci	req = vha->req;
279562306a36Sopenharmony_ci	lg->entry_type = LOGINOUT_PORT_IOCB_TYPE;
279662306a36Sopenharmony_ci	lg->entry_count = 1;
279762306a36Sopenharmony_ci	lg->handle = make_handle(req->id, lg->handle);
279862306a36Sopenharmony_ci	lg->nport_handle = cpu_to_le16(loop_id);
279962306a36Sopenharmony_ci	lg->control_flags =
280062306a36Sopenharmony_ci	    cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO|
280162306a36Sopenharmony_ci		LCF_FREE_NPORT);
280262306a36Sopenharmony_ci	lg->port_id[0] = al_pa;
280362306a36Sopenharmony_ci	lg->port_id[1] = area;
280462306a36Sopenharmony_ci	lg->port_id[2] = domain;
280562306a36Sopenharmony_ci	lg->vp_index = vha->vp_idx;
280662306a36Sopenharmony_ci	rval = qla2x00_issue_iocb_timeout(vha, lg, lg_dma, 0,
280762306a36Sopenharmony_ci	    (ha->r_a_tov / 10 * 2) + 2);
280862306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
280962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x106f,
281062306a36Sopenharmony_ci		    "Failed to issue logout IOCB (%x).\n", rval);
281162306a36Sopenharmony_ci	} else if (lg->entry_status != 0) {
281262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1070,
281362306a36Sopenharmony_ci		    "Failed to complete IOCB -- error status (%x).\n",
281462306a36Sopenharmony_ci		    lg->entry_status);
281562306a36Sopenharmony_ci		rval = QLA_FUNCTION_FAILED;
281662306a36Sopenharmony_ci	} else if (lg->comp_status != cpu_to_le16(CS_COMPLETE)) {
281762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1071,
281862306a36Sopenharmony_ci		    "Failed to complete IOCB -- completion status (%x) "
281962306a36Sopenharmony_ci		    "ioparam=%x/%x.\n", le16_to_cpu(lg->comp_status),
282062306a36Sopenharmony_ci		    le32_to_cpu(lg->io_parameter[0]),
282162306a36Sopenharmony_ci		    le32_to_cpu(lg->io_parameter[1]));
282262306a36Sopenharmony_ci	} else {
282362306a36Sopenharmony_ci		/*EMPTY*/
282462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1072,
282562306a36Sopenharmony_ci		    "Done %s.\n", __func__);
282662306a36Sopenharmony_ci	}
282762306a36Sopenharmony_ci
282862306a36Sopenharmony_ci	dma_pool_free(ha->s_dma_pool, lg, lg_dma);
282962306a36Sopenharmony_ci
283062306a36Sopenharmony_ci	return rval;
283162306a36Sopenharmony_ci}
283262306a36Sopenharmony_ci
283362306a36Sopenharmony_ci/*
283462306a36Sopenharmony_ci * qla2x00_fabric_logout
283562306a36Sopenharmony_ci *	Issue logout fabric port mailbox command.
283662306a36Sopenharmony_ci *
283762306a36Sopenharmony_ci * Input:
283862306a36Sopenharmony_ci *	ha = adapter block pointer.
283962306a36Sopenharmony_ci *	loop_id = device loop ID.
284062306a36Sopenharmony_ci *	TARGET_QUEUE_LOCK must be released.
284162306a36Sopenharmony_ci *	ADAPTER_STATE_LOCK must be released.
284262306a36Sopenharmony_ci *
284362306a36Sopenharmony_ci * Returns:
284462306a36Sopenharmony_ci *	qla2x00 local function return status code.
284562306a36Sopenharmony_ci *
284662306a36Sopenharmony_ci * Context:
284762306a36Sopenharmony_ci *	Kernel context.
284862306a36Sopenharmony_ci */
284962306a36Sopenharmony_ciint
285062306a36Sopenharmony_ciqla2x00_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
285162306a36Sopenharmony_ci    uint8_t area, uint8_t al_pa)
285262306a36Sopenharmony_ci{
285362306a36Sopenharmony_ci	int rval;
285462306a36Sopenharmony_ci	mbx_cmd_t mc;
285562306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
285662306a36Sopenharmony_ci
285762306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1073,
285862306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
285962306a36Sopenharmony_ci
286062306a36Sopenharmony_ci	mcp->mb[0] = MBC_LOGOUT_FABRIC_PORT;
286162306a36Sopenharmony_ci	mcp->out_mb = MBX_1|MBX_0;
286262306a36Sopenharmony_ci	if (HAS_EXTENDED_IDS(vha->hw)) {
286362306a36Sopenharmony_ci		mcp->mb[1] = loop_id;
286462306a36Sopenharmony_ci		mcp->mb[10] = 0;
286562306a36Sopenharmony_ci		mcp->out_mb |= MBX_10;
286662306a36Sopenharmony_ci	} else {
286762306a36Sopenharmony_ci		mcp->mb[1] = loop_id << 8;
286862306a36Sopenharmony_ci	}
286962306a36Sopenharmony_ci
287062306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
287162306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
287262306a36Sopenharmony_ci	mcp->flags = 0;
287362306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
287462306a36Sopenharmony_ci
287562306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
287662306a36Sopenharmony_ci		/*EMPTY*/
287762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1074,
287862306a36Sopenharmony_ci		    "Failed=%x mb[1]=%x.\n", rval, mcp->mb[1]);
287962306a36Sopenharmony_ci	} else {
288062306a36Sopenharmony_ci		/*EMPTY*/
288162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1075,
288262306a36Sopenharmony_ci		    "Done %s.\n", __func__);
288362306a36Sopenharmony_ci	}
288462306a36Sopenharmony_ci
288562306a36Sopenharmony_ci	return rval;
288662306a36Sopenharmony_ci}
288762306a36Sopenharmony_ci
288862306a36Sopenharmony_ci/*
288962306a36Sopenharmony_ci * qla2x00_full_login_lip
289062306a36Sopenharmony_ci *	Issue full login LIP mailbox command.
289162306a36Sopenharmony_ci *
289262306a36Sopenharmony_ci * Input:
289362306a36Sopenharmony_ci *	ha = adapter block pointer.
289462306a36Sopenharmony_ci *	TARGET_QUEUE_LOCK must be released.
289562306a36Sopenharmony_ci *	ADAPTER_STATE_LOCK must be released.
289662306a36Sopenharmony_ci *
289762306a36Sopenharmony_ci * Returns:
289862306a36Sopenharmony_ci *	qla2x00 local function return status code.
289962306a36Sopenharmony_ci *
290062306a36Sopenharmony_ci * Context:
290162306a36Sopenharmony_ci *	Kernel context.
290262306a36Sopenharmony_ci */
290362306a36Sopenharmony_ciint
290462306a36Sopenharmony_ciqla2x00_full_login_lip(scsi_qla_host_t *vha)
290562306a36Sopenharmony_ci{
290662306a36Sopenharmony_ci	int rval;
290762306a36Sopenharmony_ci	mbx_cmd_t mc;
290862306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
290962306a36Sopenharmony_ci
291062306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1076,
291162306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
291262306a36Sopenharmony_ci
291362306a36Sopenharmony_ci	mcp->mb[0] = MBC_LIP_FULL_LOGIN;
291462306a36Sopenharmony_ci	mcp->mb[1] = IS_FWI2_CAPABLE(vha->hw) ? BIT_4 : 0;
291562306a36Sopenharmony_ci	mcp->mb[2] = 0;
291662306a36Sopenharmony_ci	mcp->mb[3] = 0;
291762306a36Sopenharmony_ci	mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
291862306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
291962306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
292062306a36Sopenharmony_ci	mcp->flags = 0;
292162306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
292262306a36Sopenharmony_ci
292362306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
292462306a36Sopenharmony_ci		/*EMPTY*/
292562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1077, "Failed=%x.\n", rval);
292662306a36Sopenharmony_ci	} else {
292762306a36Sopenharmony_ci		/*EMPTY*/
292862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1078,
292962306a36Sopenharmony_ci		    "Done %s.\n", __func__);
293062306a36Sopenharmony_ci	}
293162306a36Sopenharmony_ci
293262306a36Sopenharmony_ci	return rval;
293362306a36Sopenharmony_ci}
293462306a36Sopenharmony_ci
293562306a36Sopenharmony_ci/*
293662306a36Sopenharmony_ci * qla2x00_get_id_list
293762306a36Sopenharmony_ci *
293862306a36Sopenharmony_ci * Input:
293962306a36Sopenharmony_ci *	ha = adapter block pointer.
294062306a36Sopenharmony_ci *
294162306a36Sopenharmony_ci * Returns:
294262306a36Sopenharmony_ci *	qla2x00 local function return status code.
294362306a36Sopenharmony_ci *
294462306a36Sopenharmony_ci * Context:
294562306a36Sopenharmony_ci *	Kernel context.
294662306a36Sopenharmony_ci */
294762306a36Sopenharmony_ciint
294862306a36Sopenharmony_ciqla2x00_get_id_list(scsi_qla_host_t *vha, void *id_list, dma_addr_t id_list_dma,
294962306a36Sopenharmony_ci    uint16_t *entries)
295062306a36Sopenharmony_ci{
295162306a36Sopenharmony_ci	int rval;
295262306a36Sopenharmony_ci	mbx_cmd_t mc;
295362306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
295462306a36Sopenharmony_ci
295562306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1079,
295662306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
295762306a36Sopenharmony_ci
295862306a36Sopenharmony_ci	if (id_list == NULL)
295962306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
296062306a36Sopenharmony_ci
296162306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_ID_LIST;
296262306a36Sopenharmony_ci	mcp->out_mb = MBX_0;
296362306a36Sopenharmony_ci	if (IS_FWI2_CAPABLE(vha->hw)) {
296462306a36Sopenharmony_ci		mcp->mb[2] = MSW(id_list_dma);
296562306a36Sopenharmony_ci		mcp->mb[3] = LSW(id_list_dma);
296662306a36Sopenharmony_ci		mcp->mb[6] = MSW(MSD(id_list_dma));
296762306a36Sopenharmony_ci		mcp->mb[7] = LSW(MSD(id_list_dma));
296862306a36Sopenharmony_ci		mcp->mb[8] = 0;
296962306a36Sopenharmony_ci		mcp->mb[9] = vha->vp_idx;
297062306a36Sopenharmony_ci		mcp->out_mb |= MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2;
297162306a36Sopenharmony_ci	} else {
297262306a36Sopenharmony_ci		mcp->mb[1] = MSW(id_list_dma);
297362306a36Sopenharmony_ci		mcp->mb[2] = LSW(id_list_dma);
297462306a36Sopenharmony_ci		mcp->mb[3] = MSW(MSD(id_list_dma));
297562306a36Sopenharmony_ci		mcp->mb[6] = LSW(MSD(id_list_dma));
297662306a36Sopenharmony_ci		mcp->out_mb |= MBX_6|MBX_3|MBX_2|MBX_1;
297762306a36Sopenharmony_ci	}
297862306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
297962306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
298062306a36Sopenharmony_ci	mcp->flags = 0;
298162306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
298262306a36Sopenharmony_ci
298362306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
298462306a36Sopenharmony_ci		/*EMPTY*/
298562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x107a, "Failed=%x.\n", rval);
298662306a36Sopenharmony_ci	} else {
298762306a36Sopenharmony_ci		*entries = mcp->mb[1];
298862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107b,
298962306a36Sopenharmony_ci		    "Done %s.\n", __func__);
299062306a36Sopenharmony_ci	}
299162306a36Sopenharmony_ci
299262306a36Sopenharmony_ci	return rval;
299362306a36Sopenharmony_ci}
299462306a36Sopenharmony_ci
299562306a36Sopenharmony_ci/*
299662306a36Sopenharmony_ci * qla2x00_get_resource_cnts
299762306a36Sopenharmony_ci *	Get current firmware resource counts.
299862306a36Sopenharmony_ci *
299962306a36Sopenharmony_ci * Input:
300062306a36Sopenharmony_ci *	ha = adapter block pointer.
300162306a36Sopenharmony_ci *
300262306a36Sopenharmony_ci * Returns:
300362306a36Sopenharmony_ci *	qla2x00 local function return status code.
300462306a36Sopenharmony_ci *
300562306a36Sopenharmony_ci * Context:
300662306a36Sopenharmony_ci *	Kernel context.
300762306a36Sopenharmony_ci */
300862306a36Sopenharmony_ciint
300962306a36Sopenharmony_ciqla2x00_get_resource_cnts(scsi_qla_host_t *vha)
301062306a36Sopenharmony_ci{
301162306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
301262306a36Sopenharmony_ci	int rval;
301362306a36Sopenharmony_ci	mbx_cmd_t mc;
301462306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
301562306a36Sopenharmony_ci
301662306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107c,
301762306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
301862306a36Sopenharmony_ci
301962306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_RESOURCE_COUNTS;
302062306a36Sopenharmony_ci	mcp->out_mb = MBX_0;
302162306a36Sopenharmony_ci	mcp->in_mb = MBX_11|MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
302262306a36Sopenharmony_ci	if (IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
302362306a36Sopenharmony_ci	    IS_QLA27XX(ha) || IS_QLA28XX(ha))
302462306a36Sopenharmony_ci		mcp->in_mb |= MBX_12;
302562306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
302662306a36Sopenharmony_ci	mcp->flags = 0;
302762306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
302862306a36Sopenharmony_ci
302962306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
303062306a36Sopenharmony_ci		/*EMPTY*/
303162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x107d,
303262306a36Sopenharmony_ci		    "Failed mb[0]=%x.\n", mcp->mb[0]);
303362306a36Sopenharmony_ci	} else {
303462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107e,
303562306a36Sopenharmony_ci		    "Done %s mb1=%x mb2=%x mb3=%x mb6=%x mb7=%x mb10=%x "
303662306a36Sopenharmony_ci		    "mb11=%x mb12=%x.\n", __func__, mcp->mb[1], mcp->mb[2],
303762306a36Sopenharmony_ci		    mcp->mb[3], mcp->mb[6], mcp->mb[7], mcp->mb[10],
303862306a36Sopenharmony_ci		    mcp->mb[11], mcp->mb[12]);
303962306a36Sopenharmony_ci
304062306a36Sopenharmony_ci		ha->orig_fw_tgt_xcb_count =  mcp->mb[1];
304162306a36Sopenharmony_ci		ha->cur_fw_tgt_xcb_count = mcp->mb[2];
304262306a36Sopenharmony_ci		ha->cur_fw_xcb_count = mcp->mb[3];
304362306a36Sopenharmony_ci		ha->orig_fw_xcb_count = mcp->mb[6];
304462306a36Sopenharmony_ci		ha->cur_fw_iocb_count = mcp->mb[7];
304562306a36Sopenharmony_ci		ha->orig_fw_iocb_count = mcp->mb[10];
304662306a36Sopenharmony_ci		if (ha->flags.npiv_supported)
304762306a36Sopenharmony_ci			ha->max_npiv_vports = mcp->mb[11];
304862306a36Sopenharmony_ci		if (IS_QLA81XX(ha) || IS_QLA83XX(ha))
304962306a36Sopenharmony_ci			ha->fw_max_fcf_count = mcp->mb[12];
305062306a36Sopenharmony_ci	}
305162306a36Sopenharmony_ci
305262306a36Sopenharmony_ci	return (rval);
305362306a36Sopenharmony_ci}
305462306a36Sopenharmony_ci
305562306a36Sopenharmony_ci/*
305662306a36Sopenharmony_ci * qla2x00_get_fcal_position_map
305762306a36Sopenharmony_ci *	Get FCAL (LILP) position map using mailbox command
305862306a36Sopenharmony_ci *
305962306a36Sopenharmony_ci * Input:
306062306a36Sopenharmony_ci *	ha = adapter state pointer.
306162306a36Sopenharmony_ci *	pos_map = buffer pointer (can be NULL).
306262306a36Sopenharmony_ci *
306362306a36Sopenharmony_ci * Returns:
306462306a36Sopenharmony_ci *	qla2x00 local function return status code.
306562306a36Sopenharmony_ci *
306662306a36Sopenharmony_ci * Context:
306762306a36Sopenharmony_ci *	Kernel context.
306862306a36Sopenharmony_ci */
306962306a36Sopenharmony_ciint
307062306a36Sopenharmony_ciqla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map,
307162306a36Sopenharmony_ci		u8 *num_entries)
307262306a36Sopenharmony_ci{
307362306a36Sopenharmony_ci	int rval;
307462306a36Sopenharmony_ci	mbx_cmd_t mc;
307562306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
307662306a36Sopenharmony_ci	char *pmap;
307762306a36Sopenharmony_ci	dma_addr_t pmap_dma;
307862306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
307962306a36Sopenharmony_ci
308062306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107f,
308162306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
308262306a36Sopenharmony_ci
308362306a36Sopenharmony_ci	pmap = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pmap_dma);
308462306a36Sopenharmony_ci	if (pmap  == NULL) {
308562306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x1080,
308662306a36Sopenharmony_ci		    "Memory alloc failed.\n");
308762306a36Sopenharmony_ci		return QLA_MEMORY_ALLOC_FAILED;
308862306a36Sopenharmony_ci	}
308962306a36Sopenharmony_ci
309062306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_FC_AL_POSITION_MAP;
309162306a36Sopenharmony_ci	mcp->mb[2] = MSW(pmap_dma);
309262306a36Sopenharmony_ci	mcp->mb[3] = LSW(pmap_dma);
309362306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(pmap_dma));
309462306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(pmap_dma));
309562306a36Sopenharmony_ci	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
309662306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
309762306a36Sopenharmony_ci	mcp->buf_size = FCAL_MAP_SIZE;
309862306a36Sopenharmony_ci	mcp->flags = MBX_DMA_IN;
309962306a36Sopenharmony_ci	mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
310062306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
310162306a36Sopenharmony_ci
310262306a36Sopenharmony_ci	if (rval == QLA_SUCCESS) {
310362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1081,
310462306a36Sopenharmony_ci		    "mb0/mb1=%x/%X FC/AL position map size (%x).\n",
310562306a36Sopenharmony_ci		    mcp->mb[0], mcp->mb[1], (unsigned)pmap[0]);
310662306a36Sopenharmony_ci		ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111d,
310762306a36Sopenharmony_ci		    pmap, pmap[0] + 1);
310862306a36Sopenharmony_ci
310962306a36Sopenharmony_ci		if (pos_map)
311062306a36Sopenharmony_ci			memcpy(pos_map, pmap, FCAL_MAP_SIZE);
311162306a36Sopenharmony_ci		if (num_entries)
311262306a36Sopenharmony_ci			*num_entries = pmap[0];
311362306a36Sopenharmony_ci	}
311462306a36Sopenharmony_ci	dma_pool_free(ha->s_dma_pool, pmap, pmap_dma);
311562306a36Sopenharmony_ci
311662306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
311762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1082, "Failed=%x.\n", rval);
311862306a36Sopenharmony_ci	} else {
311962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1083,
312062306a36Sopenharmony_ci		    "Done %s.\n", __func__);
312162306a36Sopenharmony_ci	}
312262306a36Sopenharmony_ci
312362306a36Sopenharmony_ci	return rval;
312462306a36Sopenharmony_ci}
312562306a36Sopenharmony_ci
312662306a36Sopenharmony_ci/*
312762306a36Sopenharmony_ci * qla2x00_get_link_status
312862306a36Sopenharmony_ci *
312962306a36Sopenharmony_ci * Input:
313062306a36Sopenharmony_ci *	ha = adapter block pointer.
313162306a36Sopenharmony_ci *	loop_id = device loop ID.
313262306a36Sopenharmony_ci *	ret_buf = pointer to link status return buffer.
313362306a36Sopenharmony_ci *
313462306a36Sopenharmony_ci * Returns:
313562306a36Sopenharmony_ci *	0 = success.
313662306a36Sopenharmony_ci *	BIT_0 = mem alloc error.
313762306a36Sopenharmony_ci *	BIT_1 = mailbox error.
313862306a36Sopenharmony_ci */
313962306a36Sopenharmony_ciint
314062306a36Sopenharmony_ciqla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
314162306a36Sopenharmony_ci    struct link_statistics *stats, dma_addr_t stats_dma)
314262306a36Sopenharmony_ci{
314362306a36Sopenharmony_ci	int rval;
314462306a36Sopenharmony_ci	mbx_cmd_t mc;
314562306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
314662306a36Sopenharmony_ci	uint32_t *iter = (uint32_t *)stats;
314762306a36Sopenharmony_ci	ushort dwords = offsetof(typeof(*stats), link_up_cnt)/sizeof(*iter);
314862306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
314962306a36Sopenharmony_ci
315062306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1084,
315162306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
315262306a36Sopenharmony_ci
315362306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_LINK_STATUS;
315462306a36Sopenharmony_ci	mcp->mb[2] = MSW(LSD(stats_dma));
315562306a36Sopenharmony_ci	mcp->mb[3] = LSW(LSD(stats_dma));
315662306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(stats_dma));
315762306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(stats_dma));
315862306a36Sopenharmony_ci	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
315962306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
316062306a36Sopenharmony_ci	if (IS_FWI2_CAPABLE(ha)) {
316162306a36Sopenharmony_ci		mcp->mb[1] = loop_id;
316262306a36Sopenharmony_ci		mcp->mb[4] = 0;
316362306a36Sopenharmony_ci		mcp->mb[10] = 0;
316462306a36Sopenharmony_ci		mcp->out_mb |= MBX_10|MBX_4|MBX_1;
316562306a36Sopenharmony_ci		mcp->in_mb |= MBX_1;
316662306a36Sopenharmony_ci	} else if (HAS_EXTENDED_IDS(ha)) {
316762306a36Sopenharmony_ci		mcp->mb[1] = loop_id;
316862306a36Sopenharmony_ci		mcp->mb[10] = 0;
316962306a36Sopenharmony_ci		mcp->out_mb |= MBX_10|MBX_1;
317062306a36Sopenharmony_ci	} else {
317162306a36Sopenharmony_ci		mcp->mb[1] = loop_id << 8;
317262306a36Sopenharmony_ci		mcp->out_mb |= MBX_1;
317362306a36Sopenharmony_ci	}
317462306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
317562306a36Sopenharmony_ci	mcp->flags = IOCTL_CMD;
317662306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
317762306a36Sopenharmony_ci
317862306a36Sopenharmony_ci	if (rval == QLA_SUCCESS) {
317962306a36Sopenharmony_ci		if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
318062306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x1085,
318162306a36Sopenharmony_ci			    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
318262306a36Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
318362306a36Sopenharmony_ci		} else {
318462306a36Sopenharmony_ci			/* Re-endianize - firmware data is le32. */
318562306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1086,
318662306a36Sopenharmony_ci			    "Done %s.\n", __func__);
318762306a36Sopenharmony_ci			for ( ; dwords--; iter++)
318862306a36Sopenharmony_ci				le32_to_cpus(iter);
318962306a36Sopenharmony_ci		}
319062306a36Sopenharmony_ci	} else {
319162306a36Sopenharmony_ci		/* Failed. */
319262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1087, "Failed=%x.\n", rval);
319362306a36Sopenharmony_ci	}
319462306a36Sopenharmony_ci
319562306a36Sopenharmony_ci	return rval;
319662306a36Sopenharmony_ci}
319762306a36Sopenharmony_ci
319862306a36Sopenharmony_ciint
319962306a36Sopenharmony_ciqla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
320062306a36Sopenharmony_ci    dma_addr_t stats_dma, uint16_t options)
320162306a36Sopenharmony_ci{
320262306a36Sopenharmony_ci	int rval;
320362306a36Sopenharmony_ci	mbx_cmd_t mc;
320462306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
320562306a36Sopenharmony_ci	uint32_t *iter = (uint32_t *)stats;
320662306a36Sopenharmony_ci	ushort dwords = sizeof(*stats)/sizeof(*iter);
320762306a36Sopenharmony_ci
320862306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1088,
320962306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
321062306a36Sopenharmony_ci
321162306a36Sopenharmony_ci	memset(&mc, 0, sizeof(mc));
321262306a36Sopenharmony_ci	mc.mb[0] = MBC_GET_LINK_PRIV_STATS;
321362306a36Sopenharmony_ci	mc.mb[2] = MSW(LSD(stats_dma));
321462306a36Sopenharmony_ci	mc.mb[3] = LSW(LSD(stats_dma));
321562306a36Sopenharmony_ci	mc.mb[6] = MSW(MSD(stats_dma));
321662306a36Sopenharmony_ci	mc.mb[7] = LSW(MSD(stats_dma));
321762306a36Sopenharmony_ci	mc.mb[8] = dwords;
321862306a36Sopenharmony_ci	mc.mb[9] = vha->vp_idx;
321962306a36Sopenharmony_ci	mc.mb[10] = options;
322062306a36Sopenharmony_ci
322162306a36Sopenharmony_ci	rval = qla24xx_send_mb_cmd(vha, &mc);
322262306a36Sopenharmony_ci
322362306a36Sopenharmony_ci	if (rval == QLA_SUCCESS) {
322462306a36Sopenharmony_ci		if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
322562306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x1089,
322662306a36Sopenharmony_ci			    "Failed mb[0]=%x.\n", mcp->mb[0]);
322762306a36Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
322862306a36Sopenharmony_ci		} else {
322962306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108a,
323062306a36Sopenharmony_ci			    "Done %s.\n", __func__);
323162306a36Sopenharmony_ci			/* Re-endianize - firmware data is le32. */
323262306a36Sopenharmony_ci			for ( ; dwords--; iter++)
323362306a36Sopenharmony_ci				le32_to_cpus(iter);
323462306a36Sopenharmony_ci		}
323562306a36Sopenharmony_ci	} else {
323662306a36Sopenharmony_ci		/* Failed. */
323762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x108b, "Failed=%x.\n", rval);
323862306a36Sopenharmony_ci	}
323962306a36Sopenharmony_ci
324062306a36Sopenharmony_ci	return rval;
324162306a36Sopenharmony_ci}
324262306a36Sopenharmony_ci
324362306a36Sopenharmony_ciint
324462306a36Sopenharmony_ciqla24xx_abort_command(srb_t *sp)
324562306a36Sopenharmony_ci{
324662306a36Sopenharmony_ci	int		rval;
324762306a36Sopenharmony_ci	unsigned long   flags = 0;
324862306a36Sopenharmony_ci
324962306a36Sopenharmony_ci	struct abort_entry_24xx *abt;
325062306a36Sopenharmony_ci	dma_addr_t	abt_dma;
325162306a36Sopenharmony_ci	uint32_t	handle;
325262306a36Sopenharmony_ci	fc_port_t	*fcport = sp->fcport;
325362306a36Sopenharmony_ci	struct scsi_qla_host *vha = fcport->vha;
325462306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
325562306a36Sopenharmony_ci	struct req_que *req;
325662306a36Sopenharmony_ci	struct qla_qpair *qpair = sp->qpair;
325762306a36Sopenharmony_ci
325862306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108c,
325962306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
326062306a36Sopenharmony_ci
326162306a36Sopenharmony_ci	if (sp->qpair)
326262306a36Sopenharmony_ci		req = sp->qpair->req;
326362306a36Sopenharmony_ci	else
326462306a36Sopenharmony_ci		return QLA_ERR_NO_QPAIR;
326562306a36Sopenharmony_ci
326662306a36Sopenharmony_ci	if (ql2xasynctmfenable)
326762306a36Sopenharmony_ci		return qla24xx_async_abort_command(sp);
326862306a36Sopenharmony_ci
326962306a36Sopenharmony_ci	spin_lock_irqsave(qpair->qp_lock_ptr, flags);
327062306a36Sopenharmony_ci	for (handle = 1; handle < req->num_outstanding_cmds; handle++) {
327162306a36Sopenharmony_ci		if (req->outstanding_cmds[handle] == sp)
327262306a36Sopenharmony_ci			break;
327362306a36Sopenharmony_ci	}
327462306a36Sopenharmony_ci	spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
327562306a36Sopenharmony_ci	if (handle == req->num_outstanding_cmds) {
327662306a36Sopenharmony_ci		/* Command not found. */
327762306a36Sopenharmony_ci		return QLA_ERR_NOT_FOUND;
327862306a36Sopenharmony_ci	}
327962306a36Sopenharmony_ci
328062306a36Sopenharmony_ci	abt = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &abt_dma);
328162306a36Sopenharmony_ci	if (abt == NULL) {
328262306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x108d,
328362306a36Sopenharmony_ci		    "Failed to allocate abort IOCB.\n");
328462306a36Sopenharmony_ci		return QLA_MEMORY_ALLOC_FAILED;
328562306a36Sopenharmony_ci	}
328662306a36Sopenharmony_ci
328762306a36Sopenharmony_ci	abt->entry_type = ABORT_IOCB_TYPE;
328862306a36Sopenharmony_ci	abt->entry_count = 1;
328962306a36Sopenharmony_ci	abt->handle = make_handle(req->id, abt->handle);
329062306a36Sopenharmony_ci	abt->nport_handle = cpu_to_le16(fcport->loop_id);
329162306a36Sopenharmony_ci	abt->handle_to_abort = make_handle(req->id, handle);
329262306a36Sopenharmony_ci	abt->port_id[0] = fcport->d_id.b.al_pa;
329362306a36Sopenharmony_ci	abt->port_id[1] = fcport->d_id.b.area;
329462306a36Sopenharmony_ci	abt->port_id[2] = fcport->d_id.b.domain;
329562306a36Sopenharmony_ci	abt->vp_index = fcport->vha->vp_idx;
329662306a36Sopenharmony_ci
329762306a36Sopenharmony_ci	abt->req_que_no = cpu_to_le16(req->id);
329862306a36Sopenharmony_ci	/* Need to pass original sp */
329962306a36Sopenharmony_ci	qla_nvme_abort_set_option(abt, sp);
330062306a36Sopenharmony_ci
330162306a36Sopenharmony_ci	rval = qla2x00_issue_iocb(vha, abt, abt_dma, 0);
330262306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
330362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x108e,
330462306a36Sopenharmony_ci		    "Failed to issue IOCB (%x).\n", rval);
330562306a36Sopenharmony_ci	} else if (abt->entry_status != 0) {
330662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x108f,
330762306a36Sopenharmony_ci		    "Failed to complete IOCB -- error status (%x).\n",
330862306a36Sopenharmony_ci		    abt->entry_status);
330962306a36Sopenharmony_ci		rval = QLA_FUNCTION_FAILED;
331062306a36Sopenharmony_ci	} else if (abt->nport_handle != cpu_to_le16(0)) {
331162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1090,
331262306a36Sopenharmony_ci		    "Failed to complete IOCB -- completion status (%x).\n",
331362306a36Sopenharmony_ci		    le16_to_cpu(abt->nport_handle));
331462306a36Sopenharmony_ci		if (abt->nport_handle == cpu_to_le16(CS_IOCB_ERROR))
331562306a36Sopenharmony_ci			rval = QLA_FUNCTION_PARAMETER_ERROR;
331662306a36Sopenharmony_ci		else
331762306a36Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
331862306a36Sopenharmony_ci	} else {
331962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1091,
332062306a36Sopenharmony_ci		    "Done %s.\n", __func__);
332162306a36Sopenharmony_ci	}
332262306a36Sopenharmony_ci	if (rval == QLA_SUCCESS)
332362306a36Sopenharmony_ci		qla_nvme_abort_process_comp_status(abt, sp);
332462306a36Sopenharmony_ci
332562306a36Sopenharmony_ci	qla_wait_nvme_release_cmd_kref(sp);
332662306a36Sopenharmony_ci
332762306a36Sopenharmony_ci	dma_pool_free(ha->s_dma_pool, abt, abt_dma);
332862306a36Sopenharmony_ci
332962306a36Sopenharmony_ci	return rval;
333062306a36Sopenharmony_ci}
333162306a36Sopenharmony_ci
333262306a36Sopenharmony_cistruct tsk_mgmt_cmd {
333362306a36Sopenharmony_ci	union {
333462306a36Sopenharmony_ci		struct tsk_mgmt_entry tsk;
333562306a36Sopenharmony_ci		struct sts_entry_24xx sts;
333662306a36Sopenharmony_ci	} p;
333762306a36Sopenharmony_ci};
333862306a36Sopenharmony_ci
333962306a36Sopenharmony_cistatic int
334062306a36Sopenharmony_ci__qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
334162306a36Sopenharmony_ci    uint64_t l, int tag)
334262306a36Sopenharmony_ci{
334362306a36Sopenharmony_ci	int		rval, rval2;
334462306a36Sopenharmony_ci	struct tsk_mgmt_cmd *tsk;
334562306a36Sopenharmony_ci	struct sts_entry_24xx *sts;
334662306a36Sopenharmony_ci	dma_addr_t	tsk_dma;
334762306a36Sopenharmony_ci	scsi_qla_host_t *vha;
334862306a36Sopenharmony_ci	struct qla_hw_data *ha;
334962306a36Sopenharmony_ci	struct req_que *req;
335062306a36Sopenharmony_ci	struct qla_qpair *qpair;
335162306a36Sopenharmony_ci
335262306a36Sopenharmony_ci	vha = fcport->vha;
335362306a36Sopenharmony_ci	ha = vha->hw;
335462306a36Sopenharmony_ci	req = vha->req;
335562306a36Sopenharmony_ci
335662306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1092,
335762306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
335862306a36Sopenharmony_ci
335962306a36Sopenharmony_ci	if (vha->vp_idx && vha->qpair) {
336062306a36Sopenharmony_ci		/* NPIV port */
336162306a36Sopenharmony_ci		qpair = vha->qpair;
336262306a36Sopenharmony_ci		req = qpair->req;
336362306a36Sopenharmony_ci	}
336462306a36Sopenharmony_ci
336562306a36Sopenharmony_ci	tsk = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma);
336662306a36Sopenharmony_ci	if (tsk == NULL) {
336762306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x1093,
336862306a36Sopenharmony_ci		    "Failed to allocate task management IOCB.\n");
336962306a36Sopenharmony_ci		return QLA_MEMORY_ALLOC_FAILED;
337062306a36Sopenharmony_ci	}
337162306a36Sopenharmony_ci
337262306a36Sopenharmony_ci	tsk->p.tsk.entry_type = TSK_MGMT_IOCB_TYPE;
337362306a36Sopenharmony_ci	tsk->p.tsk.entry_count = 1;
337462306a36Sopenharmony_ci	tsk->p.tsk.handle = make_handle(req->id, tsk->p.tsk.handle);
337562306a36Sopenharmony_ci	tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id);
337662306a36Sopenharmony_ci	tsk->p.tsk.timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
337762306a36Sopenharmony_ci	tsk->p.tsk.control_flags = cpu_to_le32(type);
337862306a36Sopenharmony_ci	tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa;
337962306a36Sopenharmony_ci	tsk->p.tsk.port_id[1] = fcport->d_id.b.area;
338062306a36Sopenharmony_ci	tsk->p.tsk.port_id[2] = fcport->d_id.b.domain;
338162306a36Sopenharmony_ci	tsk->p.tsk.vp_index = fcport->vha->vp_idx;
338262306a36Sopenharmony_ci	if (type == TCF_LUN_RESET) {
338362306a36Sopenharmony_ci		int_to_scsilun(l, &tsk->p.tsk.lun);
338462306a36Sopenharmony_ci		host_to_fcp_swap((uint8_t *)&tsk->p.tsk.lun,
338562306a36Sopenharmony_ci		    sizeof(tsk->p.tsk.lun));
338662306a36Sopenharmony_ci	}
338762306a36Sopenharmony_ci
338862306a36Sopenharmony_ci	sts = &tsk->p.sts;
338962306a36Sopenharmony_ci	rval = qla2x00_issue_iocb(vha, tsk, tsk_dma, 0);
339062306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
339162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1094,
339262306a36Sopenharmony_ci		    "Failed to issue %s reset IOCB (%x).\n", name, rval);
339362306a36Sopenharmony_ci	} else if (sts->entry_status != 0) {
339462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1095,
339562306a36Sopenharmony_ci		    "Failed to complete IOCB -- error status (%x).\n",
339662306a36Sopenharmony_ci		    sts->entry_status);
339762306a36Sopenharmony_ci		rval = QLA_FUNCTION_FAILED;
339862306a36Sopenharmony_ci	} else if (sts->comp_status != cpu_to_le16(CS_COMPLETE)) {
339962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1096,
340062306a36Sopenharmony_ci		    "Failed to complete IOCB -- completion status (%x).\n",
340162306a36Sopenharmony_ci		    le16_to_cpu(sts->comp_status));
340262306a36Sopenharmony_ci		rval = QLA_FUNCTION_FAILED;
340362306a36Sopenharmony_ci	} else if (le16_to_cpu(sts->scsi_status) &
340462306a36Sopenharmony_ci	    SS_RESPONSE_INFO_LEN_VALID) {
340562306a36Sopenharmony_ci		if (le32_to_cpu(sts->rsp_data_len) < 4) {
340662306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1097,
340762306a36Sopenharmony_ci			    "Ignoring inconsistent data length -- not enough "
340862306a36Sopenharmony_ci			    "response info (%d).\n",
340962306a36Sopenharmony_ci			    le32_to_cpu(sts->rsp_data_len));
341062306a36Sopenharmony_ci		} else if (sts->data[3]) {
341162306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x1098,
341262306a36Sopenharmony_ci			    "Failed to complete IOCB -- response (%x).\n",
341362306a36Sopenharmony_ci			    sts->data[3]);
341462306a36Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
341562306a36Sopenharmony_ci		}
341662306a36Sopenharmony_ci	}
341762306a36Sopenharmony_ci
341862306a36Sopenharmony_ci	/* Issue marker IOCB. */
341962306a36Sopenharmony_ci	rval2 = qla2x00_marker(vha, ha->base_qpair, fcport->loop_id, l,
342062306a36Sopenharmony_ci	    type == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
342162306a36Sopenharmony_ci	if (rval2 != QLA_SUCCESS) {
342262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1099,
342362306a36Sopenharmony_ci		    "Failed to issue marker IOCB (%x).\n", rval2);
342462306a36Sopenharmony_ci	} else {
342562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109a,
342662306a36Sopenharmony_ci		    "Done %s.\n", __func__);
342762306a36Sopenharmony_ci	}
342862306a36Sopenharmony_ci
342962306a36Sopenharmony_ci	dma_pool_free(ha->s_dma_pool, tsk, tsk_dma);
343062306a36Sopenharmony_ci
343162306a36Sopenharmony_ci	return rval;
343262306a36Sopenharmony_ci}
343362306a36Sopenharmony_ci
343462306a36Sopenharmony_ciint
343562306a36Sopenharmony_ciqla24xx_abort_target(struct fc_port *fcport, uint64_t l, int tag)
343662306a36Sopenharmony_ci{
343762306a36Sopenharmony_ci	struct qla_hw_data *ha = fcport->vha->hw;
343862306a36Sopenharmony_ci
343962306a36Sopenharmony_ci	if ((ql2xasynctmfenable) && IS_FWI2_CAPABLE(ha))
344062306a36Sopenharmony_ci		return qla2x00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag);
344162306a36Sopenharmony_ci
344262306a36Sopenharmony_ci	return __qla24xx_issue_tmf("Target", TCF_TARGET_RESET, fcport, l, tag);
344362306a36Sopenharmony_ci}
344462306a36Sopenharmony_ci
344562306a36Sopenharmony_ciint
344662306a36Sopenharmony_ciqla24xx_lun_reset(struct fc_port *fcport, uint64_t l, int tag)
344762306a36Sopenharmony_ci{
344862306a36Sopenharmony_ci	struct qla_hw_data *ha = fcport->vha->hw;
344962306a36Sopenharmony_ci
345062306a36Sopenharmony_ci	if ((ql2xasynctmfenable) && IS_FWI2_CAPABLE(ha))
345162306a36Sopenharmony_ci		return qla2x00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag);
345262306a36Sopenharmony_ci
345362306a36Sopenharmony_ci	return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l, tag);
345462306a36Sopenharmony_ci}
345562306a36Sopenharmony_ci
345662306a36Sopenharmony_ciint
345762306a36Sopenharmony_ciqla2x00_system_error(scsi_qla_host_t *vha)
345862306a36Sopenharmony_ci{
345962306a36Sopenharmony_ci	int rval;
346062306a36Sopenharmony_ci	mbx_cmd_t mc;
346162306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
346262306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
346362306a36Sopenharmony_ci
346462306a36Sopenharmony_ci	if (!IS_QLA23XX(ha) && !IS_FWI2_CAPABLE(ha))
346562306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
346662306a36Sopenharmony_ci
346762306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109b,
346862306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
346962306a36Sopenharmony_ci
347062306a36Sopenharmony_ci	mcp->mb[0] = MBC_GEN_SYSTEM_ERROR;
347162306a36Sopenharmony_ci	mcp->out_mb = MBX_0;
347262306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
347362306a36Sopenharmony_ci	mcp->tov = 5;
347462306a36Sopenharmony_ci	mcp->flags = 0;
347562306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
347662306a36Sopenharmony_ci
347762306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
347862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x109c, "Failed=%x.\n", rval);
347962306a36Sopenharmony_ci	} else {
348062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109d,
348162306a36Sopenharmony_ci		    "Done %s.\n", __func__);
348262306a36Sopenharmony_ci	}
348362306a36Sopenharmony_ci
348462306a36Sopenharmony_ci	return rval;
348562306a36Sopenharmony_ci}
348662306a36Sopenharmony_ci
348762306a36Sopenharmony_ciint
348862306a36Sopenharmony_ciqla2x00_write_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t data)
348962306a36Sopenharmony_ci{
349062306a36Sopenharmony_ci	int rval;
349162306a36Sopenharmony_ci	mbx_cmd_t mc;
349262306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
349362306a36Sopenharmony_ci
349462306a36Sopenharmony_ci	if (!IS_QLA25XX(vha->hw) && !IS_QLA2031(vha->hw) &&
349562306a36Sopenharmony_ci	    !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw))
349662306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
349762306a36Sopenharmony_ci
349862306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1182,
349962306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
350062306a36Sopenharmony_ci
350162306a36Sopenharmony_ci	mcp->mb[0] = MBC_WRITE_SERDES;
350262306a36Sopenharmony_ci	mcp->mb[1] = addr;
350362306a36Sopenharmony_ci	if (IS_QLA2031(vha->hw))
350462306a36Sopenharmony_ci		mcp->mb[2] = data & 0xff;
350562306a36Sopenharmony_ci	else
350662306a36Sopenharmony_ci		mcp->mb[2] = data;
350762306a36Sopenharmony_ci
350862306a36Sopenharmony_ci	mcp->mb[3] = 0;
350962306a36Sopenharmony_ci	mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
351062306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
351162306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
351262306a36Sopenharmony_ci	mcp->flags = 0;
351362306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
351462306a36Sopenharmony_ci
351562306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
351662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1183,
351762306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
351862306a36Sopenharmony_ci	} else {
351962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1184,
352062306a36Sopenharmony_ci		    "Done %s.\n", __func__);
352162306a36Sopenharmony_ci	}
352262306a36Sopenharmony_ci
352362306a36Sopenharmony_ci	return rval;
352462306a36Sopenharmony_ci}
352562306a36Sopenharmony_ci
352662306a36Sopenharmony_ciint
352762306a36Sopenharmony_ciqla2x00_read_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t *data)
352862306a36Sopenharmony_ci{
352962306a36Sopenharmony_ci	int rval;
353062306a36Sopenharmony_ci	mbx_cmd_t mc;
353162306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
353262306a36Sopenharmony_ci
353362306a36Sopenharmony_ci	if (!IS_QLA25XX(vha->hw) && !IS_QLA2031(vha->hw) &&
353462306a36Sopenharmony_ci	    !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw))
353562306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
353662306a36Sopenharmony_ci
353762306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1185,
353862306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
353962306a36Sopenharmony_ci
354062306a36Sopenharmony_ci	mcp->mb[0] = MBC_READ_SERDES;
354162306a36Sopenharmony_ci	mcp->mb[1] = addr;
354262306a36Sopenharmony_ci	mcp->mb[3] = 0;
354362306a36Sopenharmony_ci	mcp->out_mb = MBX_3|MBX_1|MBX_0;
354462306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
354562306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
354662306a36Sopenharmony_ci	mcp->flags = 0;
354762306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
354862306a36Sopenharmony_ci
354962306a36Sopenharmony_ci	if (IS_QLA2031(vha->hw))
355062306a36Sopenharmony_ci		*data = mcp->mb[1] & 0xff;
355162306a36Sopenharmony_ci	else
355262306a36Sopenharmony_ci		*data = mcp->mb[1];
355362306a36Sopenharmony_ci
355462306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
355562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1186,
355662306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
355762306a36Sopenharmony_ci	} else {
355862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1187,
355962306a36Sopenharmony_ci		    "Done %s.\n", __func__);
356062306a36Sopenharmony_ci	}
356162306a36Sopenharmony_ci
356262306a36Sopenharmony_ci	return rval;
356362306a36Sopenharmony_ci}
356462306a36Sopenharmony_ci
356562306a36Sopenharmony_ciint
356662306a36Sopenharmony_ciqla8044_write_serdes_word(scsi_qla_host_t *vha, uint32_t addr, uint32_t data)
356762306a36Sopenharmony_ci{
356862306a36Sopenharmony_ci	int rval;
356962306a36Sopenharmony_ci	mbx_cmd_t mc;
357062306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
357162306a36Sopenharmony_ci
357262306a36Sopenharmony_ci	if (!IS_QLA8044(vha->hw))
357362306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
357462306a36Sopenharmony_ci
357562306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x11a0,
357662306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
357762306a36Sopenharmony_ci
357862306a36Sopenharmony_ci	mcp->mb[0] = MBC_SET_GET_ETH_SERDES_REG;
357962306a36Sopenharmony_ci	mcp->mb[1] = HCS_WRITE_SERDES;
358062306a36Sopenharmony_ci	mcp->mb[3] = LSW(addr);
358162306a36Sopenharmony_ci	mcp->mb[4] = MSW(addr);
358262306a36Sopenharmony_ci	mcp->mb[5] = LSW(data);
358362306a36Sopenharmony_ci	mcp->mb[6] = MSW(data);
358462306a36Sopenharmony_ci	mcp->out_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_1|MBX_0;
358562306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
358662306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
358762306a36Sopenharmony_ci	mcp->flags = 0;
358862306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
358962306a36Sopenharmony_ci
359062306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
359162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x11a1,
359262306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
359362306a36Sopenharmony_ci	} else {
359462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1188,
359562306a36Sopenharmony_ci		    "Done %s.\n", __func__);
359662306a36Sopenharmony_ci	}
359762306a36Sopenharmony_ci
359862306a36Sopenharmony_ci	return rval;
359962306a36Sopenharmony_ci}
360062306a36Sopenharmony_ci
360162306a36Sopenharmony_ciint
360262306a36Sopenharmony_ciqla8044_read_serdes_word(scsi_qla_host_t *vha, uint32_t addr, uint32_t *data)
360362306a36Sopenharmony_ci{
360462306a36Sopenharmony_ci	int rval;
360562306a36Sopenharmony_ci	mbx_cmd_t mc;
360662306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
360762306a36Sopenharmony_ci
360862306a36Sopenharmony_ci	if (!IS_QLA8044(vha->hw))
360962306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
361062306a36Sopenharmony_ci
361162306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1189,
361262306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
361362306a36Sopenharmony_ci
361462306a36Sopenharmony_ci	mcp->mb[0] = MBC_SET_GET_ETH_SERDES_REG;
361562306a36Sopenharmony_ci	mcp->mb[1] = HCS_READ_SERDES;
361662306a36Sopenharmony_ci	mcp->mb[3] = LSW(addr);
361762306a36Sopenharmony_ci	mcp->mb[4] = MSW(addr);
361862306a36Sopenharmony_ci	mcp->out_mb = MBX_4|MBX_3|MBX_1|MBX_0;
361962306a36Sopenharmony_ci	mcp->in_mb = MBX_2|MBX_1|MBX_0;
362062306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
362162306a36Sopenharmony_ci	mcp->flags = 0;
362262306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
362362306a36Sopenharmony_ci
362462306a36Sopenharmony_ci	*data = mcp->mb[2] << 16 | mcp->mb[1];
362562306a36Sopenharmony_ci
362662306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
362762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x118a,
362862306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
362962306a36Sopenharmony_ci	} else {
363062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118b,
363162306a36Sopenharmony_ci		    "Done %s.\n", __func__);
363262306a36Sopenharmony_ci	}
363362306a36Sopenharmony_ci
363462306a36Sopenharmony_ci	return rval;
363562306a36Sopenharmony_ci}
363662306a36Sopenharmony_ci
363762306a36Sopenharmony_ci/**
363862306a36Sopenharmony_ci * qla2x00_set_serdes_params() -
363962306a36Sopenharmony_ci * @vha: HA context
364062306a36Sopenharmony_ci * @sw_em_1g: serial link options
364162306a36Sopenharmony_ci * @sw_em_2g: serial link options
364262306a36Sopenharmony_ci * @sw_em_4g: serial link options
364362306a36Sopenharmony_ci *
364462306a36Sopenharmony_ci * Returns
364562306a36Sopenharmony_ci */
364662306a36Sopenharmony_ciint
364762306a36Sopenharmony_ciqla2x00_set_serdes_params(scsi_qla_host_t *vha, uint16_t sw_em_1g,
364862306a36Sopenharmony_ci    uint16_t sw_em_2g, uint16_t sw_em_4g)
364962306a36Sopenharmony_ci{
365062306a36Sopenharmony_ci	int rval;
365162306a36Sopenharmony_ci	mbx_cmd_t mc;
365262306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
365362306a36Sopenharmony_ci
365462306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109e,
365562306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
365662306a36Sopenharmony_ci
365762306a36Sopenharmony_ci	mcp->mb[0] = MBC_SERDES_PARAMS;
365862306a36Sopenharmony_ci	mcp->mb[1] = BIT_0;
365962306a36Sopenharmony_ci	mcp->mb[2] = sw_em_1g | BIT_15;
366062306a36Sopenharmony_ci	mcp->mb[3] = sw_em_2g | BIT_15;
366162306a36Sopenharmony_ci	mcp->mb[4] = sw_em_4g | BIT_15;
366262306a36Sopenharmony_ci	mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
366362306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
366462306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
366562306a36Sopenharmony_ci	mcp->flags = 0;
366662306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
366762306a36Sopenharmony_ci
366862306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
366962306a36Sopenharmony_ci		/*EMPTY*/
367062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x109f,
367162306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
367262306a36Sopenharmony_ci	} else {
367362306a36Sopenharmony_ci		/*EMPTY*/
367462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a0,
367562306a36Sopenharmony_ci		    "Done %s.\n", __func__);
367662306a36Sopenharmony_ci	}
367762306a36Sopenharmony_ci
367862306a36Sopenharmony_ci	return rval;
367962306a36Sopenharmony_ci}
368062306a36Sopenharmony_ci
368162306a36Sopenharmony_ciint
368262306a36Sopenharmony_ciqla2x00_stop_firmware(scsi_qla_host_t *vha)
368362306a36Sopenharmony_ci{
368462306a36Sopenharmony_ci	int rval;
368562306a36Sopenharmony_ci	mbx_cmd_t mc;
368662306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
368762306a36Sopenharmony_ci
368862306a36Sopenharmony_ci	if (!IS_FWI2_CAPABLE(vha->hw))
368962306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
369062306a36Sopenharmony_ci
369162306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a1,
369262306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
369362306a36Sopenharmony_ci
369462306a36Sopenharmony_ci	mcp->mb[0] = MBC_STOP_FIRMWARE;
369562306a36Sopenharmony_ci	mcp->mb[1] = 0;
369662306a36Sopenharmony_ci	mcp->out_mb = MBX_1|MBX_0;
369762306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
369862306a36Sopenharmony_ci	mcp->tov = 5;
369962306a36Sopenharmony_ci	mcp->flags = 0;
370062306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
370162306a36Sopenharmony_ci
370262306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
370362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10a2, "Failed=%x.\n", rval);
370462306a36Sopenharmony_ci		if (mcp->mb[0] == MBS_INVALID_COMMAND)
370562306a36Sopenharmony_ci			rval = QLA_INVALID_COMMAND;
370662306a36Sopenharmony_ci	} else {
370762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a3,
370862306a36Sopenharmony_ci		    "Done %s.\n", __func__);
370962306a36Sopenharmony_ci	}
371062306a36Sopenharmony_ci
371162306a36Sopenharmony_ci	return rval;
371262306a36Sopenharmony_ci}
371362306a36Sopenharmony_ci
371462306a36Sopenharmony_ciint
371562306a36Sopenharmony_ciqla2x00_enable_eft_trace(scsi_qla_host_t *vha, dma_addr_t eft_dma,
371662306a36Sopenharmony_ci    uint16_t buffers)
371762306a36Sopenharmony_ci{
371862306a36Sopenharmony_ci	int rval;
371962306a36Sopenharmony_ci	mbx_cmd_t mc;
372062306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
372162306a36Sopenharmony_ci
372262306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a4,
372362306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
372462306a36Sopenharmony_ci
372562306a36Sopenharmony_ci	if (!IS_FWI2_CAPABLE(vha->hw))
372662306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
372762306a36Sopenharmony_ci
372862306a36Sopenharmony_ci	if (unlikely(pci_channel_offline(vha->hw->pdev)))
372962306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
373062306a36Sopenharmony_ci
373162306a36Sopenharmony_ci	mcp->mb[0] = MBC_TRACE_CONTROL;
373262306a36Sopenharmony_ci	mcp->mb[1] = TC_EFT_ENABLE;
373362306a36Sopenharmony_ci	mcp->mb[2] = LSW(eft_dma);
373462306a36Sopenharmony_ci	mcp->mb[3] = MSW(eft_dma);
373562306a36Sopenharmony_ci	mcp->mb[4] = LSW(MSD(eft_dma));
373662306a36Sopenharmony_ci	mcp->mb[5] = MSW(MSD(eft_dma));
373762306a36Sopenharmony_ci	mcp->mb[6] = buffers;
373862306a36Sopenharmony_ci	mcp->mb[7] = TC_AEN_DISABLE;
373962306a36Sopenharmony_ci	mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
374062306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
374162306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
374262306a36Sopenharmony_ci	mcp->flags = 0;
374362306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
374462306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
374562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10a5,
374662306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x.\n",
374762306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1]);
374862306a36Sopenharmony_ci	} else {
374962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a6,
375062306a36Sopenharmony_ci		    "Done %s.\n", __func__);
375162306a36Sopenharmony_ci	}
375262306a36Sopenharmony_ci
375362306a36Sopenharmony_ci	return rval;
375462306a36Sopenharmony_ci}
375562306a36Sopenharmony_ci
375662306a36Sopenharmony_ciint
375762306a36Sopenharmony_ciqla2x00_disable_eft_trace(scsi_qla_host_t *vha)
375862306a36Sopenharmony_ci{
375962306a36Sopenharmony_ci	int rval;
376062306a36Sopenharmony_ci	mbx_cmd_t mc;
376162306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
376262306a36Sopenharmony_ci
376362306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a7,
376462306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
376562306a36Sopenharmony_ci
376662306a36Sopenharmony_ci	if (!IS_FWI2_CAPABLE(vha->hw))
376762306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
376862306a36Sopenharmony_ci
376962306a36Sopenharmony_ci	if (unlikely(pci_channel_offline(vha->hw->pdev)))
377062306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
377162306a36Sopenharmony_ci
377262306a36Sopenharmony_ci	mcp->mb[0] = MBC_TRACE_CONTROL;
377362306a36Sopenharmony_ci	mcp->mb[1] = TC_EFT_DISABLE;
377462306a36Sopenharmony_ci	mcp->out_mb = MBX_1|MBX_0;
377562306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
377662306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
377762306a36Sopenharmony_ci	mcp->flags = 0;
377862306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
377962306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
378062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10a8,
378162306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x.\n",
378262306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1]);
378362306a36Sopenharmony_ci	} else {
378462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a9,
378562306a36Sopenharmony_ci		    "Done %s.\n", __func__);
378662306a36Sopenharmony_ci	}
378762306a36Sopenharmony_ci
378862306a36Sopenharmony_ci	return rval;
378962306a36Sopenharmony_ci}
379062306a36Sopenharmony_ci
379162306a36Sopenharmony_ciint
379262306a36Sopenharmony_ciqla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma,
379362306a36Sopenharmony_ci    uint16_t buffers, uint16_t *mb, uint32_t *dwords)
379462306a36Sopenharmony_ci{
379562306a36Sopenharmony_ci	int rval;
379662306a36Sopenharmony_ci	mbx_cmd_t mc;
379762306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
379862306a36Sopenharmony_ci
379962306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10aa,
380062306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
380162306a36Sopenharmony_ci
380262306a36Sopenharmony_ci	if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw) &&
380362306a36Sopenharmony_ci	    !IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) &&
380462306a36Sopenharmony_ci	    !IS_QLA28XX(vha->hw))
380562306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
380662306a36Sopenharmony_ci
380762306a36Sopenharmony_ci	if (unlikely(pci_channel_offline(vha->hw->pdev)))
380862306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
380962306a36Sopenharmony_ci
381062306a36Sopenharmony_ci	mcp->mb[0] = MBC_TRACE_CONTROL;
381162306a36Sopenharmony_ci	mcp->mb[1] = TC_FCE_ENABLE;
381262306a36Sopenharmony_ci	mcp->mb[2] = LSW(fce_dma);
381362306a36Sopenharmony_ci	mcp->mb[3] = MSW(fce_dma);
381462306a36Sopenharmony_ci	mcp->mb[4] = LSW(MSD(fce_dma));
381562306a36Sopenharmony_ci	mcp->mb[5] = MSW(MSD(fce_dma));
381662306a36Sopenharmony_ci	mcp->mb[6] = buffers;
381762306a36Sopenharmony_ci	mcp->mb[7] = TC_AEN_DISABLE;
381862306a36Sopenharmony_ci	mcp->mb[8] = 0;
381962306a36Sopenharmony_ci	mcp->mb[9] = TC_FCE_DEFAULT_RX_SIZE;
382062306a36Sopenharmony_ci	mcp->mb[10] = TC_FCE_DEFAULT_TX_SIZE;
382162306a36Sopenharmony_ci	mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|
382262306a36Sopenharmony_ci	    MBX_1|MBX_0;
382362306a36Sopenharmony_ci	mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
382462306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
382562306a36Sopenharmony_ci	mcp->flags = 0;
382662306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
382762306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
382862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10ab,
382962306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x.\n",
383062306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1]);
383162306a36Sopenharmony_ci	} else {
383262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ac,
383362306a36Sopenharmony_ci		    "Done %s.\n", __func__);
383462306a36Sopenharmony_ci
383562306a36Sopenharmony_ci		if (mb)
383662306a36Sopenharmony_ci			memcpy(mb, mcp->mb, 8 * sizeof(*mb));
383762306a36Sopenharmony_ci		if (dwords)
383862306a36Sopenharmony_ci			*dwords = buffers;
383962306a36Sopenharmony_ci	}
384062306a36Sopenharmony_ci
384162306a36Sopenharmony_ci	return rval;
384262306a36Sopenharmony_ci}
384362306a36Sopenharmony_ci
384462306a36Sopenharmony_ciint
384562306a36Sopenharmony_ciqla2x00_disable_fce_trace(scsi_qla_host_t *vha, uint64_t *wr, uint64_t *rd)
384662306a36Sopenharmony_ci{
384762306a36Sopenharmony_ci	int rval;
384862306a36Sopenharmony_ci	mbx_cmd_t mc;
384962306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
385062306a36Sopenharmony_ci
385162306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ad,
385262306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
385362306a36Sopenharmony_ci
385462306a36Sopenharmony_ci	if (!IS_FWI2_CAPABLE(vha->hw))
385562306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
385662306a36Sopenharmony_ci
385762306a36Sopenharmony_ci	if (unlikely(pci_channel_offline(vha->hw->pdev)))
385862306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
385962306a36Sopenharmony_ci
386062306a36Sopenharmony_ci	mcp->mb[0] = MBC_TRACE_CONTROL;
386162306a36Sopenharmony_ci	mcp->mb[1] = TC_FCE_DISABLE;
386262306a36Sopenharmony_ci	mcp->mb[2] = TC_FCE_DISABLE_TRACE;
386362306a36Sopenharmony_ci	mcp->out_mb = MBX_2|MBX_1|MBX_0;
386462306a36Sopenharmony_ci	mcp->in_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|
386562306a36Sopenharmony_ci	    MBX_1|MBX_0;
386662306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
386762306a36Sopenharmony_ci	mcp->flags = 0;
386862306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
386962306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
387062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10ae,
387162306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x.\n",
387262306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1]);
387362306a36Sopenharmony_ci	} else {
387462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10af,
387562306a36Sopenharmony_ci		    "Done %s.\n", __func__);
387662306a36Sopenharmony_ci
387762306a36Sopenharmony_ci		if (wr)
387862306a36Sopenharmony_ci			*wr = (uint64_t) mcp->mb[5] << 48 |
387962306a36Sopenharmony_ci			    (uint64_t) mcp->mb[4] << 32 |
388062306a36Sopenharmony_ci			    (uint64_t) mcp->mb[3] << 16 |
388162306a36Sopenharmony_ci			    (uint64_t) mcp->mb[2];
388262306a36Sopenharmony_ci		if (rd)
388362306a36Sopenharmony_ci			*rd = (uint64_t) mcp->mb[9] << 48 |
388462306a36Sopenharmony_ci			    (uint64_t) mcp->mb[8] << 32 |
388562306a36Sopenharmony_ci			    (uint64_t) mcp->mb[7] << 16 |
388662306a36Sopenharmony_ci			    (uint64_t) mcp->mb[6];
388762306a36Sopenharmony_ci	}
388862306a36Sopenharmony_ci
388962306a36Sopenharmony_ci	return rval;
389062306a36Sopenharmony_ci}
389162306a36Sopenharmony_ci
389262306a36Sopenharmony_ciint
389362306a36Sopenharmony_ciqla2x00_get_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
389462306a36Sopenharmony_ci	uint16_t *port_speed, uint16_t *mb)
389562306a36Sopenharmony_ci{
389662306a36Sopenharmony_ci	int rval;
389762306a36Sopenharmony_ci	mbx_cmd_t mc;
389862306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
389962306a36Sopenharmony_ci
390062306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b0,
390162306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
390262306a36Sopenharmony_ci
390362306a36Sopenharmony_ci	if (!IS_IIDMA_CAPABLE(vha->hw))
390462306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
390562306a36Sopenharmony_ci
390662306a36Sopenharmony_ci	mcp->mb[0] = MBC_PORT_PARAMS;
390762306a36Sopenharmony_ci	mcp->mb[1] = loop_id;
390862306a36Sopenharmony_ci	mcp->mb[2] = mcp->mb[3] = 0;
390962306a36Sopenharmony_ci	mcp->mb[9] = vha->vp_idx;
391062306a36Sopenharmony_ci	mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0;
391162306a36Sopenharmony_ci	mcp->in_mb = MBX_3|MBX_1|MBX_0;
391262306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
391362306a36Sopenharmony_ci	mcp->flags = 0;
391462306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
391562306a36Sopenharmony_ci
391662306a36Sopenharmony_ci	/* Return mailbox statuses. */
391762306a36Sopenharmony_ci	if (mb) {
391862306a36Sopenharmony_ci		mb[0] = mcp->mb[0];
391962306a36Sopenharmony_ci		mb[1] = mcp->mb[1];
392062306a36Sopenharmony_ci		mb[3] = mcp->mb[3];
392162306a36Sopenharmony_ci	}
392262306a36Sopenharmony_ci
392362306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
392462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10b1, "Failed=%x.\n", rval);
392562306a36Sopenharmony_ci	} else {
392662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b2,
392762306a36Sopenharmony_ci		    "Done %s.\n", __func__);
392862306a36Sopenharmony_ci		if (port_speed)
392962306a36Sopenharmony_ci			*port_speed = mcp->mb[3];
393062306a36Sopenharmony_ci	}
393162306a36Sopenharmony_ci
393262306a36Sopenharmony_ci	return rval;
393362306a36Sopenharmony_ci}
393462306a36Sopenharmony_ci
393562306a36Sopenharmony_ciint
393662306a36Sopenharmony_ciqla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
393762306a36Sopenharmony_ci    uint16_t port_speed, uint16_t *mb)
393862306a36Sopenharmony_ci{
393962306a36Sopenharmony_ci	int rval;
394062306a36Sopenharmony_ci	mbx_cmd_t mc;
394162306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
394262306a36Sopenharmony_ci
394362306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b3,
394462306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
394562306a36Sopenharmony_ci
394662306a36Sopenharmony_ci	if (!IS_IIDMA_CAPABLE(vha->hw))
394762306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
394862306a36Sopenharmony_ci
394962306a36Sopenharmony_ci	mcp->mb[0] = MBC_PORT_PARAMS;
395062306a36Sopenharmony_ci	mcp->mb[1] = loop_id;
395162306a36Sopenharmony_ci	mcp->mb[2] = BIT_0;
395262306a36Sopenharmony_ci	mcp->mb[3] = port_speed & 0x3F;
395362306a36Sopenharmony_ci	mcp->mb[9] = vha->vp_idx;
395462306a36Sopenharmony_ci	mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0;
395562306a36Sopenharmony_ci	mcp->in_mb = MBX_3|MBX_1|MBX_0;
395662306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
395762306a36Sopenharmony_ci	mcp->flags = 0;
395862306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
395962306a36Sopenharmony_ci
396062306a36Sopenharmony_ci	/* Return mailbox statuses. */
396162306a36Sopenharmony_ci	if (mb) {
396262306a36Sopenharmony_ci		mb[0] = mcp->mb[0];
396362306a36Sopenharmony_ci		mb[1] = mcp->mb[1];
396462306a36Sopenharmony_ci		mb[3] = mcp->mb[3];
396562306a36Sopenharmony_ci	}
396662306a36Sopenharmony_ci
396762306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
396862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10b4,
396962306a36Sopenharmony_ci		    "Failed=%x.\n", rval);
397062306a36Sopenharmony_ci	} else {
397162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b5,
397262306a36Sopenharmony_ci		    "Done %s.\n", __func__);
397362306a36Sopenharmony_ci	}
397462306a36Sopenharmony_ci
397562306a36Sopenharmony_ci	return rval;
397662306a36Sopenharmony_ci}
397762306a36Sopenharmony_ci
397862306a36Sopenharmony_civoid
397962306a36Sopenharmony_ciqla24xx_report_id_acquisition(scsi_qla_host_t *vha,
398062306a36Sopenharmony_ci	struct vp_rpt_id_entry_24xx *rptid_entry)
398162306a36Sopenharmony_ci{
398262306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
398362306a36Sopenharmony_ci	scsi_qla_host_t *vp = NULL;
398462306a36Sopenharmony_ci	unsigned long   flags;
398562306a36Sopenharmony_ci	int found;
398662306a36Sopenharmony_ci	port_id_t id;
398762306a36Sopenharmony_ci	struct fc_port *fcport;
398862306a36Sopenharmony_ci
398962306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b6,
399062306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
399162306a36Sopenharmony_ci
399262306a36Sopenharmony_ci	if (rptid_entry->entry_status != 0)
399362306a36Sopenharmony_ci		return;
399462306a36Sopenharmony_ci
399562306a36Sopenharmony_ci	id.b.domain = rptid_entry->port_id[2];
399662306a36Sopenharmony_ci	id.b.area   = rptid_entry->port_id[1];
399762306a36Sopenharmony_ci	id.b.al_pa  = rptid_entry->port_id[0];
399862306a36Sopenharmony_ci	id.b.rsvd_1 = 0;
399962306a36Sopenharmony_ci	ha->flags.n2n_ae = 0;
400062306a36Sopenharmony_ci
400162306a36Sopenharmony_ci	if (rptid_entry->format == 0) {
400262306a36Sopenharmony_ci		/* loop */
400362306a36Sopenharmony_ci		ql_dbg(ql_dbg_async, vha, 0x10b7,
400462306a36Sopenharmony_ci		    "Format 0 : Number of VPs setup %d, number of "
400562306a36Sopenharmony_ci		    "VPs acquired %d.\n", rptid_entry->vp_setup,
400662306a36Sopenharmony_ci		    rptid_entry->vp_acquired);
400762306a36Sopenharmony_ci		ql_dbg(ql_dbg_async, vha, 0x10b8,
400862306a36Sopenharmony_ci		    "Primary port id %02x%02x%02x.\n",
400962306a36Sopenharmony_ci		    rptid_entry->port_id[2], rptid_entry->port_id[1],
401062306a36Sopenharmony_ci		    rptid_entry->port_id[0]);
401162306a36Sopenharmony_ci		ha->current_topology = ISP_CFG_NL;
401262306a36Sopenharmony_ci		qla_update_host_map(vha, id);
401362306a36Sopenharmony_ci
401462306a36Sopenharmony_ci	} else if (rptid_entry->format == 1) {
401562306a36Sopenharmony_ci		/* fabric */
401662306a36Sopenharmony_ci		ql_dbg(ql_dbg_async, vha, 0x10b9,
401762306a36Sopenharmony_ci		    "Format 1: VP[%d] enabled - status %d - with "
401862306a36Sopenharmony_ci		    "port id %02x%02x%02x.\n", rptid_entry->vp_idx,
401962306a36Sopenharmony_ci			rptid_entry->vp_status,
402062306a36Sopenharmony_ci		    rptid_entry->port_id[2], rptid_entry->port_id[1],
402162306a36Sopenharmony_ci		    rptid_entry->port_id[0]);
402262306a36Sopenharmony_ci		ql_dbg(ql_dbg_async, vha, 0x5075,
402362306a36Sopenharmony_ci		   "Format 1: Remote WWPN %8phC.\n",
402462306a36Sopenharmony_ci		   rptid_entry->u.f1.port_name);
402562306a36Sopenharmony_ci
402662306a36Sopenharmony_ci		ql_dbg(ql_dbg_async, vha, 0x5075,
402762306a36Sopenharmony_ci		   "Format 1: WWPN %8phC.\n",
402862306a36Sopenharmony_ci		   vha->port_name);
402962306a36Sopenharmony_ci
403062306a36Sopenharmony_ci		switch (rptid_entry->u.f1.flags & TOPO_MASK) {
403162306a36Sopenharmony_ci		case TOPO_N2N:
403262306a36Sopenharmony_ci			ha->current_topology = ISP_CFG_N;
403362306a36Sopenharmony_ci			spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
403462306a36Sopenharmony_ci			list_for_each_entry(fcport, &vha->vp_fcports, list) {
403562306a36Sopenharmony_ci				fcport->scan_state = QLA_FCPORT_SCAN;
403662306a36Sopenharmony_ci				fcport->n2n_flag = 0;
403762306a36Sopenharmony_ci			}
403862306a36Sopenharmony_ci			id.b24 = 0;
403962306a36Sopenharmony_ci			if (wwn_to_u64(vha->port_name) >
404062306a36Sopenharmony_ci			    wwn_to_u64(rptid_entry->u.f1.port_name)) {
404162306a36Sopenharmony_ci				vha->d_id.b24 = 0;
404262306a36Sopenharmony_ci				vha->d_id.b.al_pa = 1;
404362306a36Sopenharmony_ci				ha->flags.n2n_bigger = 1;
404462306a36Sopenharmony_ci
404562306a36Sopenharmony_ci				id.b.al_pa = 2;
404662306a36Sopenharmony_ci				ql_dbg(ql_dbg_async, vha, 0x5075,
404762306a36Sopenharmony_ci				    "Format 1: assign local id %x remote id %x\n",
404862306a36Sopenharmony_ci				    vha->d_id.b24, id.b24);
404962306a36Sopenharmony_ci			} else {
405062306a36Sopenharmony_ci				ql_dbg(ql_dbg_async, vha, 0x5075,
405162306a36Sopenharmony_ci				    "Format 1: Remote login - Waiting for WWPN %8phC.\n",
405262306a36Sopenharmony_ci				    rptid_entry->u.f1.port_name);
405362306a36Sopenharmony_ci				ha->flags.n2n_bigger = 0;
405462306a36Sopenharmony_ci			}
405562306a36Sopenharmony_ci
405662306a36Sopenharmony_ci			fcport = qla2x00_find_fcport_by_wwpn(vha,
405762306a36Sopenharmony_ci			    rptid_entry->u.f1.port_name, 1);
405862306a36Sopenharmony_ci			spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
405962306a36Sopenharmony_ci
406062306a36Sopenharmony_ci
406162306a36Sopenharmony_ci			if (fcport) {
406262306a36Sopenharmony_ci				fcport->plogi_nack_done_deadline = jiffies + HZ;
406362306a36Sopenharmony_ci				fcport->dm_login_expire = jiffies +
406462306a36Sopenharmony_ci					QLA_N2N_WAIT_TIME * HZ;
406562306a36Sopenharmony_ci				fcport->scan_state = QLA_FCPORT_FOUND;
406662306a36Sopenharmony_ci				fcport->n2n_flag = 1;
406762306a36Sopenharmony_ci				fcport->keep_nport_handle = 1;
406862306a36Sopenharmony_ci				fcport->login_retry = vha->hw->login_retry_count;
406962306a36Sopenharmony_ci				fcport->fc4_type = FS_FC4TYPE_FCP;
407062306a36Sopenharmony_ci				if (vha->flags.nvme_enabled)
407162306a36Sopenharmony_ci					fcport->fc4_type |= FS_FC4TYPE_NVME;
407262306a36Sopenharmony_ci
407362306a36Sopenharmony_ci				if (wwn_to_u64(vha->port_name) >
407462306a36Sopenharmony_ci				    wwn_to_u64(fcport->port_name)) {
407562306a36Sopenharmony_ci					fcport->d_id = id;
407662306a36Sopenharmony_ci				}
407762306a36Sopenharmony_ci
407862306a36Sopenharmony_ci				switch (fcport->disc_state) {
407962306a36Sopenharmony_ci				case DSC_DELETED:
408062306a36Sopenharmony_ci					set_bit(RELOGIN_NEEDED,
408162306a36Sopenharmony_ci					    &vha->dpc_flags);
408262306a36Sopenharmony_ci					break;
408362306a36Sopenharmony_ci				case DSC_DELETE_PEND:
408462306a36Sopenharmony_ci					break;
408562306a36Sopenharmony_ci				default:
408662306a36Sopenharmony_ci					qlt_schedule_sess_for_deletion(fcport);
408762306a36Sopenharmony_ci					break;
408862306a36Sopenharmony_ci				}
408962306a36Sopenharmony_ci			} else {
409062306a36Sopenharmony_ci				qla24xx_post_newsess_work(vha, &id,
409162306a36Sopenharmony_ci				    rptid_entry->u.f1.port_name,
409262306a36Sopenharmony_ci				    rptid_entry->u.f1.node_name,
409362306a36Sopenharmony_ci				    NULL,
409462306a36Sopenharmony_ci				    FS_FCP_IS_N2N);
409562306a36Sopenharmony_ci			}
409662306a36Sopenharmony_ci
409762306a36Sopenharmony_ci			/* if our portname is higher then initiate N2N login */
409862306a36Sopenharmony_ci
409962306a36Sopenharmony_ci			set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags);
410062306a36Sopenharmony_ci			return;
410162306a36Sopenharmony_ci		case TOPO_FL:
410262306a36Sopenharmony_ci			ha->current_topology = ISP_CFG_FL;
410362306a36Sopenharmony_ci			break;
410462306a36Sopenharmony_ci		case TOPO_F:
410562306a36Sopenharmony_ci			ha->current_topology = ISP_CFG_F;
410662306a36Sopenharmony_ci			break;
410762306a36Sopenharmony_ci		default:
410862306a36Sopenharmony_ci			break;
410962306a36Sopenharmony_ci		}
411062306a36Sopenharmony_ci
411162306a36Sopenharmony_ci		ha->flags.gpsc_supported = 1;
411262306a36Sopenharmony_ci		ha->current_topology = ISP_CFG_F;
411362306a36Sopenharmony_ci		/* buffer to buffer credit flag */
411462306a36Sopenharmony_ci		vha->flags.bbcr_enable = (rptid_entry->u.f1.bbcr & 0xf) != 0;
411562306a36Sopenharmony_ci
411662306a36Sopenharmony_ci		if (rptid_entry->vp_idx == 0) {
411762306a36Sopenharmony_ci			if (rptid_entry->vp_status == VP_STAT_COMPL) {
411862306a36Sopenharmony_ci				/* FA-WWN is only for physical port */
411962306a36Sopenharmony_ci				if (qla_ini_mode_enabled(vha) &&
412062306a36Sopenharmony_ci				    ha->flags.fawwpn_enabled &&
412162306a36Sopenharmony_ci				    (rptid_entry->u.f1.flags &
412262306a36Sopenharmony_ci				     BIT_6)) {
412362306a36Sopenharmony_ci					memcpy(vha->port_name,
412462306a36Sopenharmony_ci					    rptid_entry->u.f1.port_name,
412562306a36Sopenharmony_ci					    WWN_SIZE);
412662306a36Sopenharmony_ci				}
412762306a36Sopenharmony_ci
412862306a36Sopenharmony_ci				qla_update_host_map(vha, id);
412962306a36Sopenharmony_ci			}
413062306a36Sopenharmony_ci
413162306a36Sopenharmony_ci			set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
413262306a36Sopenharmony_ci			set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
413362306a36Sopenharmony_ci		} else {
413462306a36Sopenharmony_ci			if (rptid_entry->vp_status != VP_STAT_COMPL &&
413562306a36Sopenharmony_ci				rptid_entry->vp_status != VP_STAT_ID_CHG) {
413662306a36Sopenharmony_ci				ql_dbg(ql_dbg_mbx, vha, 0x10ba,
413762306a36Sopenharmony_ci				    "Could not acquire ID for VP[%d].\n",
413862306a36Sopenharmony_ci				    rptid_entry->vp_idx);
413962306a36Sopenharmony_ci				return;
414062306a36Sopenharmony_ci			}
414162306a36Sopenharmony_ci
414262306a36Sopenharmony_ci			found = 0;
414362306a36Sopenharmony_ci			spin_lock_irqsave(&ha->vport_slock, flags);
414462306a36Sopenharmony_ci			list_for_each_entry(vp, &ha->vp_list, list) {
414562306a36Sopenharmony_ci				if (rptid_entry->vp_idx == vp->vp_idx) {
414662306a36Sopenharmony_ci					found = 1;
414762306a36Sopenharmony_ci					break;
414862306a36Sopenharmony_ci				}
414962306a36Sopenharmony_ci			}
415062306a36Sopenharmony_ci			spin_unlock_irqrestore(&ha->vport_slock, flags);
415162306a36Sopenharmony_ci
415262306a36Sopenharmony_ci			if (!found)
415362306a36Sopenharmony_ci				return;
415462306a36Sopenharmony_ci
415562306a36Sopenharmony_ci			qla_update_host_map(vp, id);
415662306a36Sopenharmony_ci
415762306a36Sopenharmony_ci			/*
415862306a36Sopenharmony_ci			 * Cannot configure here as we are still sitting on the
415962306a36Sopenharmony_ci			 * response queue. Handle it in dpc context.
416062306a36Sopenharmony_ci			 */
416162306a36Sopenharmony_ci			set_bit(VP_IDX_ACQUIRED, &vp->vp_flags);
416262306a36Sopenharmony_ci			set_bit(REGISTER_FC4_NEEDED, &vp->dpc_flags);
416362306a36Sopenharmony_ci			set_bit(REGISTER_FDMI_NEEDED, &vp->dpc_flags);
416462306a36Sopenharmony_ci		}
416562306a36Sopenharmony_ci		set_bit(VP_DPC_NEEDED, &vha->dpc_flags);
416662306a36Sopenharmony_ci		qla2xxx_wake_dpc(vha);
416762306a36Sopenharmony_ci	} else if (rptid_entry->format == 2) {
416862306a36Sopenharmony_ci		ql_dbg(ql_dbg_async, vha, 0x505f,
416962306a36Sopenharmony_ci		    "RIDA: format 2/N2N Primary port id %02x%02x%02x.\n",
417062306a36Sopenharmony_ci		    rptid_entry->port_id[2], rptid_entry->port_id[1],
417162306a36Sopenharmony_ci		    rptid_entry->port_id[0]);
417262306a36Sopenharmony_ci
417362306a36Sopenharmony_ci		ql_dbg(ql_dbg_async, vha, 0x5075,
417462306a36Sopenharmony_ci		    "N2N: Remote WWPN %8phC.\n",
417562306a36Sopenharmony_ci		    rptid_entry->u.f2.port_name);
417662306a36Sopenharmony_ci
417762306a36Sopenharmony_ci		/* N2N.  direct connect */
417862306a36Sopenharmony_ci		ha->current_topology = ISP_CFG_N;
417962306a36Sopenharmony_ci		ha->flags.rida_fmt2 = 1;
418062306a36Sopenharmony_ci		vha->d_id.b.domain = rptid_entry->port_id[2];
418162306a36Sopenharmony_ci		vha->d_id.b.area = rptid_entry->port_id[1];
418262306a36Sopenharmony_ci		vha->d_id.b.al_pa = rptid_entry->port_id[0];
418362306a36Sopenharmony_ci
418462306a36Sopenharmony_ci		ha->flags.n2n_ae = 1;
418562306a36Sopenharmony_ci		spin_lock_irqsave(&ha->vport_slock, flags);
418662306a36Sopenharmony_ci		qla_update_vp_map(vha, SET_AL_PA);
418762306a36Sopenharmony_ci		spin_unlock_irqrestore(&ha->vport_slock, flags);
418862306a36Sopenharmony_ci
418962306a36Sopenharmony_ci		list_for_each_entry(fcport, &vha->vp_fcports, list) {
419062306a36Sopenharmony_ci			fcport->scan_state = QLA_FCPORT_SCAN;
419162306a36Sopenharmony_ci			fcport->n2n_flag = 0;
419262306a36Sopenharmony_ci		}
419362306a36Sopenharmony_ci
419462306a36Sopenharmony_ci		fcport = qla2x00_find_fcport_by_wwpn(vha,
419562306a36Sopenharmony_ci		    rptid_entry->u.f2.port_name, 1);
419662306a36Sopenharmony_ci
419762306a36Sopenharmony_ci		if (fcport) {
419862306a36Sopenharmony_ci			fcport->login_retry = vha->hw->login_retry_count;
419962306a36Sopenharmony_ci			fcport->plogi_nack_done_deadline = jiffies + HZ;
420062306a36Sopenharmony_ci			fcport->scan_state = QLA_FCPORT_FOUND;
420162306a36Sopenharmony_ci			fcport->keep_nport_handle = 1;
420262306a36Sopenharmony_ci			fcport->n2n_flag = 1;
420362306a36Sopenharmony_ci			fcport->d_id.b.domain =
420462306a36Sopenharmony_ci				rptid_entry->u.f2.remote_nport_id[2];
420562306a36Sopenharmony_ci			fcport->d_id.b.area =
420662306a36Sopenharmony_ci				rptid_entry->u.f2.remote_nport_id[1];
420762306a36Sopenharmony_ci			fcport->d_id.b.al_pa =
420862306a36Sopenharmony_ci				rptid_entry->u.f2.remote_nport_id[0];
420962306a36Sopenharmony_ci
421062306a36Sopenharmony_ci			/*
421162306a36Sopenharmony_ci			 * For the case where remote port sending PRLO, FW
421262306a36Sopenharmony_ci			 * sends up RIDA Format 2 as an indication of session
421362306a36Sopenharmony_ci			 * loss. In other word, FW state change from PRLI
421462306a36Sopenharmony_ci			 * complete back to PLOGI complete. Delete the
421562306a36Sopenharmony_ci			 * session and let relogin drive the reconnect.
421662306a36Sopenharmony_ci			 */
421762306a36Sopenharmony_ci			if (atomic_read(&fcport->state) == FCS_ONLINE)
421862306a36Sopenharmony_ci				qlt_schedule_sess_for_deletion(fcport);
421962306a36Sopenharmony_ci		}
422062306a36Sopenharmony_ci	}
422162306a36Sopenharmony_ci}
422262306a36Sopenharmony_ci
422362306a36Sopenharmony_ci/*
422462306a36Sopenharmony_ci * qla24xx_modify_vp_config
422562306a36Sopenharmony_ci *	Change VP configuration for vha
422662306a36Sopenharmony_ci *
422762306a36Sopenharmony_ci * Input:
422862306a36Sopenharmony_ci *	vha = adapter block pointer.
422962306a36Sopenharmony_ci *
423062306a36Sopenharmony_ci * Returns:
423162306a36Sopenharmony_ci *	qla2xxx local function return status code.
423262306a36Sopenharmony_ci *
423362306a36Sopenharmony_ci * Context:
423462306a36Sopenharmony_ci *	Kernel context.
423562306a36Sopenharmony_ci */
423662306a36Sopenharmony_ciint
423762306a36Sopenharmony_ciqla24xx_modify_vp_config(scsi_qla_host_t *vha)
423862306a36Sopenharmony_ci{
423962306a36Sopenharmony_ci	int		rval;
424062306a36Sopenharmony_ci	struct vp_config_entry_24xx *vpmod;
424162306a36Sopenharmony_ci	dma_addr_t	vpmod_dma;
424262306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
424362306a36Sopenharmony_ci	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
424462306a36Sopenharmony_ci
424562306a36Sopenharmony_ci	/* This can be called by the parent */
424662306a36Sopenharmony_ci
424762306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10bb,
424862306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
424962306a36Sopenharmony_ci
425062306a36Sopenharmony_ci	vpmod = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &vpmod_dma);
425162306a36Sopenharmony_ci	if (!vpmod) {
425262306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x10bc,
425362306a36Sopenharmony_ci		    "Failed to allocate modify VP IOCB.\n");
425462306a36Sopenharmony_ci		return QLA_MEMORY_ALLOC_FAILED;
425562306a36Sopenharmony_ci	}
425662306a36Sopenharmony_ci
425762306a36Sopenharmony_ci	vpmod->entry_type = VP_CONFIG_IOCB_TYPE;
425862306a36Sopenharmony_ci	vpmod->entry_count = 1;
425962306a36Sopenharmony_ci	vpmod->command = VCT_COMMAND_MOD_ENABLE_VPS;
426062306a36Sopenharmony_ci	vpmod->vp_count = 1;
426162306a36Sopenharmony_ci	vpmod->vp_index1 = vha->vp_idx;
426262306a36Sopenharmony_ci	vpmod->options_idx1 = BIT_3|BIT_4|BIT_5;
426362306a36Sopenharmony_ci
426462306a36Sopenharmony_ci	qlt_modify_vp_config(vha, vpmod);
426562306a36Sopenharmony_ci
426662306a36Sopenharmony_ci	memcpy(vpmod->node_name_idx1, vha->node_name, WWN_SIZE);
426762306a36Sopenharmony_ci	memcpy(vpmod->port_name_idx1, vha->port_name, WWN_SIZE);
426862306a36Sopenharmony_ci	vpmod->entry_count = 1;
426962306a36Sopenharmony_ci
427062306a36Sopenharmony_ci	rval = qla2x00_issue_iocb(base_vha, vpmod, vpmod_dma, 0);
427162306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
427262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10bd,
427362306a36Sopenharmony_ci		    "Failed to issue VP config IOCB (%x).\n", rval);
427462306a36Sopenharmony_ci	} else if (vpmod->comp_status != 0) {
427562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10be,
427662306a36Sopenharmony_ci		    "Failed to complete IOCB -- error status (%x).\n",
427762306a36Sopenharmony_ci		    vpmod->comp_status);
427862306a36Sopenharmony_ci		rval = QLA_FUNCTION_FAILED;
427962306a36Sopenharmony_ci	} else if (vpmod->comp_status != cpu_to_le16(CS_COMPLETE)) {
428062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10bf,
428162306a36Sopenharmony_ci		    "Failed to complete IOCB -- completion status (%x).\n",
428262306a36Sopenharmony_ci		    le16_to_cpu(vpmod->comp_status));
428362306a36Sopenharmony_ci		rval = QLA_FUNCTION_FAILED;
428462306a36Sopenharmony_ci	} else {
428562306a36Sopenharmony_ci		/* EMPTY */
428662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c0,
428762306a36Sopenharmony_ci		    "Done %s.\n", __func__);
428862306a36Sopenharmony_ci		fc_vport_set_state(vha->fc_vport, FC_VPORT_INITIALIZING);
428962306a36Sopenharmony_ci	}
429062306a36Sopenharmony_ci	dma_pool_free(ha->s_dma_pool, vpmod, vpmod_dma);
429162306a36Sopenharmony_ci
429262306a36Sopenharmony_ci	return rval;
429362306a36Sopenharmony_ci}
429462306a36Sopenharmony_ci
429562306a36Sopenharmony_ci/*
429662306a36Sopenharmony_ci * qla2x00_send_change_request
429762306a36Sopenharmony_ci *	Receive or disable RSCN request from fabric controller
429862306a36Sopenharmony_ci *
429962306a36Sopenharmony_ci * Input:
430062306a36Sopenharmony_ci *	ha = adapter block pointer
430162306a36Sopenharmony_ci *	format = registration format:
430262306a36Sopenharmony_ci *		0 - Reserved
430362306a36Sopenharmony_ci *		1 - Fabric detected registration
430462306a36Sopenharmony_ci *		2 - N_port detected registration
430562306a36Sopenharmony_ci *		3 - Full registration
430662306a36Sopenharmony_ci *		FF - clear registration
430762306a36Sopenharmony_ci *	vp_idx = Virtual port index
430862306a36Sopenharmony_ci *
430962306a36Sopenharmony_ci * Returns:
431062306a36Sopenharmony_ci *	qla2x00 local function return status code.
431162306a36Sopenharmony_ci *
431262306a36Sopenharmony_ci * Context:
431362306a36Sopenharmony_ci *	Kernel Context
431462306a36Sopenharmony_ci */
431562306a36Sopenharmony_ci
431662306a36Sopenharmony_ciint
431762306a36Sopenharmony_ciqla2x00_send_change_request(scsi_qla_host_t *vha, uint16_t format,
431862306a36Sopenharmony_ci			    uint16_t vp_idx)
431962306a36Sopenharmony_ci{
432062306a36Sopenharmony_ci	int rval;
432162306a36Sopenharmony_ci	mbx_cmd_t mc;
432262306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
432362306a36Sopenharmony_ci
432462306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c7,
432562306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
432662306a36Sopenharmony_ci
432762306a36Sopenharmony_ci	mcp->mb[0] = MBC_SEND_CHANGE_REQUEST;
432862306a36Sopenharmony_ci	mcp->mb[1] = format;
432962306a36Sopenharmony_ci	mcp->mb[9] = vp_idx;
433062306a36Sopenharmony_ci	mcp->out_mb = MBX_9|MBX_1|MBX_0;
433162306a36Sopenharmony_ci	mcp->in_mb = MBX_0|MBX_1;
433262306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
433362306a36Sopenharmony_ci	mcp->flags = 0;
433462306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
433562306a36Sopenharmony_ci
433662306a36Sopenharmony_ci	if (rval == QLA_SUCCESS) {
433762306a36Sopenharmony_ci		if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
433862306a36Sopenharmony_ci			rval = BIT_1;
433962306a36Sopenharmony_ci		}
434062306a36Sopenharmony_ci	} else
434162306a36Sopenharmony_ci		rval = BIT_1;
434262306a36Sopenharmony_ci
434362306a36Sopenharmony_ci	return rval;
434462306a36Sopenharmony_ci}
434562306a36Sopenharmony_ci
434662306a36Sopenharmony_ciint
434762306a36Sopenharmony_ciqla2x00_dump_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr,
434862306a36Sopenharmony_ci    uint32_t size)
434962306a36Sopenharmony_ci{
435062306a36Sopenharmony_ci	int rval;
435162306a36Sopenharmony_ci	mbx_cmd_t mc;
435262306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
435362306a36Sopenharmony_ci
435462306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1009,
435562306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
435662306a36Sopenharmony_ci
435762306a36Sopenharmony_ci	if (MSW(addr) || IS_FWI2_CAPABLE(vha->hw)) {
435862306a36Sopenharmony_ci		mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED;
435962306a36Sopenharmony_ci		mcp->mb[8] = MSW(addr);
436062306a36Sopenharmony_ci		mcp->mb[10] = 0;
436162306a36Sopenharmony_ci		mcp->out_mb = MBX_10|MBX_8|MBX_0;
436262306a36Sopenharmony_ci	} else {
436362306a36Sopenharmony_ci		mcp->mb[0] = MBC_DUMP_RISC_RAM;
436462306a36Sopenharmony_ci		mcp->out_mb = MBX_0;
436562306a36Sopenharmony_ci	}
436662306a36Sopenharmony_ci	mcp->mb[1] = LSW(addr);
436762306a36Sopenharmony_ci	mcp->mb[2] = MSW(req_dma);
436862306a36Sopenharmony_ci	mcp->mb[3] = LSW(req_dma);
436962306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(req_dma));
437062306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(req_dma));
437162306a36Sopenharmony_ci	mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1;
437262306a36Sopenharmony_ci	if (IS_FWI2_CAPABLE(vha->hw)) {
437362306a36Sopenharmony_ci		mcp->mb[4] = MSW(size);
437462306a36Sopenharmony_ci		mcp->mb[5] = LSW(size);
437562306a36Sopenharmony_ci		mcp->out_mb |= MBX_5|MBX_4;
437662306a36Sopenharmony_ci	} else {
437762306a36Sopenharmony_ci		mcp->mb[4] = LSW(size);
437862306a36Sopenharmony_ci		mcp->out_mb |= MBX_4;
437962306a36Sopenharmony_ci	}
438062306a36Sopenharmony_ci
438162306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
438262306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
438362306a36Sopenharmony_ci	mcp->flags = 0;
438462306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
438562306a36Sopenharmony_ci
438662306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
438762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1008,
438862306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
438962306a36Sopenharmony_ci	} else {
439062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1007,
439162306a36Sopenharmony_ci		    "Done %s.\n", __func__);
439262306a36Sopenharmony_ci	}
439362306a36Sopenharmony_ci
439462306a36Sopenharmony_ci	return rval;
439562306a36Sopenharmony_ci}
439662306a36Sopenharmony_ci/* 84XX Support **************************************************************/
439762306a36Sopenharmony_ci
439862306a36Sopenharmony_cistruct cs84xx_mgmt_cmd {
439962306a36Sopenharmony_ci	union {
440062306a36Sopenharmony_ci		struct verify_chip_entry_84xx req;
440162306a36Sopenharmony_ci		struct verify_chip_rsp_84xx rsp;
440262306a36Sopenharmony_ci	} p;
440362306a36Sopenharmony_ci};
440462306a36Sopenharmony_ci
440562306a36Sopenharmony_ciint
440662306a36Sopenharmony_ciqla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status)
440762306a36Sopenharmony_ci{
440862306a36Sopenharmony_ci	int rval, retry;
440962306a36Sopenharmony_ci	struct cs84xx_mgmt_cmd *mn;
441062306a36Sopenharmony_ci	dma_addr_t mn_dma;
441162306a36Sopenharmony_ci	uint16_t options;
441262306a36Sopenharmony_ci	unsigned long flags;
441362306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
441462306a36Sopenharmony_ci
441562306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c8,
441662306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
441762306a36Sopenharmony_ci
441862306a36Sopenharmony_ci	mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
441962306a36Sopenharmony_ci	if (mn == NULL) {
442062306a36Sopenharmony_ci		return QLA_MEMORY_ALLOC_FAILED;
442162306a36Sopenharmony_ci	}
442262306a36Sopenharmony_ci
442362306a36Sopenharmony_ci	/* Force Update? */
442462306a36Sopenharmony_ci	options = ha->cs84xx->fw_update ? VCO_FORCE_UPDATE : 0;
442562306a36Sopenharmony_ci	/* Diagnostic firmware? */
442662306a36Sopenharmony_ci	/* options |= MENLO_DIAG_FW; */
442762306a36Sopenharmony_ci	/* We update the firmware with only one data sequence. */
442862306a36Sopenharmony_ci	options |= VCO_END_OF_DATA;
442962306a36Sopenharmony_ci
443062306a36Sopenharmony_ci	do {
443162306a36Sopenharmony_ci		retry = 0;
443262306a36Sopenharmony_ci		memset(mn, 0, sizeof(*mn));
443362306a36Sopenharmony_ci		mn->p.req.entry_type = VERIFY_CHIP_IOCB_TYPE;
443462306a36Sopenharmony_ci		mn->p.req.entry_count = 1;
443562306a36Sopenharmony_ci		mn->p.req.options = cpu_to_le16(options);
443662306a36Sopenharmony_ci
443762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111c,
443862306a36Sopenharmony_ci		    "Dump of Verify Request.\n");
443962306a36Sopenharmony_ci		ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111e,
444062306a36Sopenharmony_ci		    mn, sizeof(*mn));
444162306a36Sopenharmony_ci
444262306a36Sopenharmony_ci		rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120);
444362306a36Sopenharmony_ci		if (rval != QLA_SUCCESS) {
444462306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x10cb,
444562306a36Sopenharmony_ci			    "Failed to issue verify IOCB (%x).\n", rval);
444662306a36Sopenharmony_ci			goto verify_done;
444762306a36Sopenharmony_ci		}
444862306a36Sopenharmony_ci
444962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1110,
445062306a36Sopenharmony_ci		    "Dump of Verify Response.\n");
445162306a36Sopenharmony_ci		ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1118,
445262306a36Sopenharmony_ci		    mn, sizeof(*mn));
445362306a36Sopenharmony_ci
445462306a36Sopenharmony_ci		status[0] = le16_to_cpu(mn->p.rsp.comp_status);
445562306a36Sopenharmony_ci		status[1] = status[0] == CS_VCS_CHIP_FAILURE ?
445662306a36Sopenharmony_ci		    le16_to_cpu(mn->p.rsp.failure_code) : 0;
445762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ce,
445862306a36Sopenharmony_ci		    "cs=%x fc=%x.\n", status[0], status[1]);
445962306a36Sopenharmony_ci
446062306a36Sopenharmony_ci		if (status[0] != CS_COMPLETE) {
446162306a36Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
446262306a36Sopenharmony_ci			if (!(options & VCO_DONT_UPDATE_FW)) {
446362306a36Sopenharmony_ci				ql_dbg(ql_dbg_mbx, vha, 0x10cf,
446462306a36Sopenharmony_ci				    "Firmware update failed. Retrying "
446562306a36Sopenharmony_ci				    "without update firmware.\n");
446662306a36Sopenharmony_ci				options |= VCO_DONT_UPDATE_FW;
446762306a36Sopenharmony_ci				options &= ~VCO_FORCE_UPDATE;
446862306a36Sopenharmony_ci				retry = 1;
446962306a36Sopenharmony_ci			}
447062306a36Sopenharmony_ci		} else {
447162306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d0,
447262306a36Sopenharmony_ci			    "Firmware updated to %x.\n",
447362306a36Sopenharmony_ci			    le32_to_cpu(mn->p.rsp.fw_ver));
447462306a36Sopenharmony_ci
447562306a36Sopenharmony_ci			/* NOTE: we only update OP firmware. */
447662306a36Sopenharmony_ci			spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
447762306a36Sopenharmony_ci			ha->cs84xx->op_fw_version =
447862306a36Sopenharmony_ci			    le32_to_cpu(mn->p.rsp.fw_ver);
447962306a36Sopenharmony_ci			spin_unlock_irqrestore(&ha->cs84xx->access_lock,
448062306a36Sopenharmony_ci			    flags);
448162306a36Sopenharmony_ci		}
448262306a36Sopenharmony_ci	} while (retry);
448362306a36Sopenharmony_ci
448462306a36Sopenharmony_civerify_done:
448562306a36Sopenharmony_ci	dma_pool_free(ha->s_dma_pool, mn, mn_dma);
448662306a36Sopenharmony_ci
448762306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
448862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10d1,
448962306a36Sopenharmony_ci		    "Failed=%x.\n", rval);
449062306a36Sopenharmony_ci	} else {
449162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d2,
449262306a36Sopenharmony_ci		    "Done %s.\n", __func__);
449362306a36Sopenharmony_ci	}
449462306a36Sopenharmony_ci
449562306a36Sopenharmony_ci	return rval;
449662306a36Sopenharmony_ci}
449762306a36Sopenharmony_ci
449862306a36Sopenharmony_ciint
449962306a36Sopenharmony_ciqla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req)
450062306a36Sopenharmony_ci{
450162306a36Sopenharmony_ci	int rval;
450262306a36Sopenharmony_ci	unsigned long flags;
450362306a36Sopenharmony_ci	mbx_cmd_t mc;
450462306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
450562306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
450662306a36Sopenharmony_ci
450762306a36Sopenharmony_ci	if (!ha->flags.fw_started)
450862306a36Sopenharmony_ci		return QLA_SUCCESS;
450962306a36Sopenharmony_ci
451062306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d3,
451162306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
451262306a36Sopenharmony_ci
451362306a36Sopenharmony_ci	if (IS_SHADOW_REG_CAPABLE(ha))
451462306a36Sopenharmony_ci		req->options |= BIT_13;
451562306a36Sopenharmony_ci
451662306a36Sopenharmony_ci	mcp->mb[0] = MBC_INITIALIZE_MULTIQ;
451762306a36Sopenharmony_ci	mcp->mb[1] = req->options;
451862306a36Sopenharmony_ci	mcp->mb[2] = MSW(LSD(req->dma));
451962306a36Sopenharmony_ci	mcp->mb[3] = LSW(LSD(req->dma));
452062306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(req->dma));
452162306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(req->dma));
452262306a36Sopenharmony_ci	mcp->mb[5] = req->length;
452362306a36Sopenharmony_ci	if (req->rsp)
452462306a36Sopenharmony_ci		mcp->mb[10] = req->rsp->id;
452562306a36Sopenharmony_ci	mcp->mb[12] = req->qos;
452662306a36Sopenharmony_ci	mcp->mb[11] = req->vp_idx;
452762306a36Sopenharmony_ci	mcp->mb[13] = req->rid;
452862306a36Sopenharmony_ci	if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
452962306a36Sopenharmony_ci		mcp->mb[15] = 0;
453062306a36Sopenharmony_ci
453162306a36Sopenharmony_ci	mcp->mb[4] = req->id;
453262306a36Sopenharmony_ci	/* que in ptr index */
453362306a36Sopenharmony_ci	mcp->mb[8] = 0;
453462306a36Sopenharmony_ci	/* que out ptr index */
453562306a36Sopenharmony_ci	mcp->mb[9] = *req->out_ptr = 0;
453662306a36Sopenharmony_ci	mcp->out_mb = MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|MBX_7|
453762306a36Sopenharmony_ci			MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
453862306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
453962306a36Sopenharmony_ci	mcp->flags = MBX_DMA_OUT;
454062306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS * 2;
454162306a36Sopenharmony_ci
454262306a36Sopenharmony_ci	if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
454362306a36Sopenharmony_ci	    IS_QLA28XX(ha))
454462306a36Sopenharmony_ci		mcp->in_mb |= MBX_1;
454562306a36Sopenharmony_ci	if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
454662306a36Sopenharmony_ci		mcp->out_mb |= MBX_15;
454762306a36Sopenharmony_ci		/* debug q create issue in SR-IOV */
454862306a36Sopenharmony_ci		mcp->in_mb |= MBX_9 | MBX_8 | MBX_7;
454962306a36Sopenharmony_ci	}
455062306a36Sopenharmony_ci
455162306a36Sopenharmony_ci	spin_lock_irqsave(&ha->hardware_lock, flags);
455262306a36Sopenharmony_ci	if (!(req->options & BIT_0)) {
455362306a36Sopenharmony_ci		wrt_reg_dword(req->req_q_in, 0);
455462306a36Sopenharmony_ci		if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
455562306a36Sopenharmony_ci			wrt_reg_dword(req->req_q_out, 0);
455662306a36Sopenharmony_ci	}
455762306a36Sopenharmony_ci	spin_unlock_irqrestore(&ha->hardware_lock, flags);
455862306a36Sopenharmony_ci
455962306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
456062306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
456162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10d4,
456262306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
456362306a36Sopenharmony_ci	} else {
456462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d5,
456562306a36Sopenharmony_ci		    "Done %s.\n", __func__);
456662306a36Sopenharmony_ci	}
456762306a36Sopenharmony_ci
456862306a36Sopenharmony_ci	return rval;
456962306a36Sopenharmony_ci}
457062306a36Sopenharmony_ci
457162306a36Sopenharmony_ciint
457262306a36Sopenharmony_ciqla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
457362306a36Sopenharmony_ci{
457462306a36Sopenharmony_ci	int rval;
457562306a36Sopenharmony_ci	unsigned long flags;
457662306a36Sopenharmony_ci	mbx_cmd_t mc;
457762306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
457862306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
457962306a36Sopenharmony_ci
458062306a36Sopenharmony_ci	if (!ha->flags.fw_started)
458162306a36Sopenharmony_ci		return QLA_SUCCESS;
458262306a36Sopenharmony_ci
458362306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d6,
458462306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
458562306a36Sopenharmony_ci
458662306a36Sopenharmony_ci	if (IS_SHADOW_REG_CAPABLE(ha))
458762306a36Sopenharmony_ci		rsp->options |= BIT_13;
458862306a36Sopenharmony_ci
458962306a36Sopenharmony_ci	mcp->mb[0] = MBC_INITIALIZE_MULTIQ;
459062306a36Sopenharmony_ci	mcp->mb[1] = rsp->options;
459162306a36Sopenharmony_ci	mcp->mb[2] = MSW(LSD(rsp->dma));
459262306a36Sopenharmony_ci	mcp->mb[3] = LSW(LSD(rsp->dma));
459362306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(rsp->dma));
459462306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(rsp->dma));
459562306a36Sopenharmony_ci	mcp->mb[5] = rsp->length;
459662306a36Sopenharmony_ci	mcp->mb[14] = rsp->msix->entry;
459762306a36Sopenharmony_ci	mcp->mb[13] = rsp->rid;
459862306a36Sopenharmony_ci	if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
459962306a36Sopenharmony_ci		mcp->mb[15] = 0;
460062306a36Sopenharmony_ci
460162306a36Sopenharmony_ci	mcp->mb[4] = rsp->id;
460262306a36Sopenharmony_ci	/* que in ptr index */
460362306a36Sopenharmony_ci	mcp->mb[8] = *rsp->in_ptr = 0;
460462306a36Sopenharmony_ci	/* que out ptr index */
460562306a36Sopenharmony_ci	mcp->mb[9] = 0;
460662306a36Sopenharmony_ci	mcp->out_mb = MBX_14|MBX_13|MBX_9|MBX_8|MBX_7
460762306a36Sopenharmony_ci			|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
460862306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
460962306a36Sopenharmony_ci	mcp->flags = MBX_DMA_OUT;
461062306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS * 2;
461162306a36Sopenharmony_ci
461262306a36Sopenharmony_ci	if (IS_QLA81XX(ha)) {
461362306a36Sopenharmony_ci		mcp->out_mb |= MBX_12|MBX_11|MBX_10;
461462306a36Sopenharmony_ci		mcp->in_mb |= MBX_1;
461562306a36Sopenharmony_ci	} else if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
461662306a36Sopenharmony_ci		mcp->out_mb |= MBX_15|MBX_12|MBX_11|MBX_10;
461762306a36Sopenharmony_ci		mcp->in_mb |= MBX_1;
461862306a36Sopenharmony_ci		/* debug q create issue in SR-IOV */
461962306a36Sopenharmony_ci		mcp->in_mb |= MBX_9 | MBX_8 | MBX_7;
462062306a36Sopenharmony_ci	}
462162306a36Sopenharmony_ci
462262306a36Sopenharmony_ci	spin_lock_irqsave(&ha->hardware_lock, flags);
462362306a36Sopenharmony_ci	if (!(rsp->options & BIT_0)) {
462462306a36Sopenharmony_ci		wrt_reg_dword(rsp->rsp_q_out, 0);
462562306a36Sopenharmony_ci		if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
462662306a36Sopenharmony_ci			wrt_reg_dword(rsp->rsp_q_in, 0);
462762306a36Sopenharmony_ci	}
462862306a36Sopenharmony_ci
462962306a36Sopenharmony_ci	spin_unlock_irqrestore(&ha->hardware_lock, flags);
463062306a36Sopenharmony_ci
463162306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
463262306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
463362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10d7,
463462306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
463562306a36Sopenharmony_ci	} else {
463662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d8,
463762306a36Sopenharmony_ci		    "Done %s.\n", __func__);
463862306a36Sopenharmony_ci	}
463962306a36Sopenharmony_ci
464062306a36Sopenharmony_ci	return rval;
464162306a36Sopenharmony_ci}
464262306a36Sopenharmony_ci
464362306a36Sopenharmony_ciint
464462306a36Sopenharmony_ciqla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb)
464562306a36Sopenharmony_ci{
464662306a36Sopenharmony_ci	int rval;
464762306a36Sopenharmony_ci	mbx_cmd_t mc;
464862306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
464962306a36Sopenharmony_ci
465062306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d9,
465162306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
465262306a36Sopenharmony_ci
465362306a36Sopenharmony_ci	mcp->mb[0] = MBC_IDC_ACK;
465462306a36Sopenharmony_ci	memcpy(&mcp->mb[1], mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
465562306a36Sopenharmony_ci	mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
465662306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
465762306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
465862306a36Sopenharmony_ci	mcp->flags = 0;
465962306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
466062306a36Sopenharmony_ci
466162306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
466262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10da,
466362306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
466462306a36Sopenharmony_ci	} else {
466562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10db,
466662306a36Sopenharmony_ci		    "Done %s.\n", __func__);
466762306a36Sopenharmony_ci	}
466862306a36Sopenharmony_ci
466962306a36Sopenharmony_ci	return rval;
467062306a36Sopenharmony_ci}
467162306a36Sopenharmony_ci
467262306a36Sopenharmony_ciint
467362306a36Sopenharmony_ciqla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size)
467462306a36Sopenharmony_ci{
467562306a36Sopenharmony_ci	int rval;
467662306a36Sopenharmony_ci	mbx_cmd_t mc;
467762306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
467862306a36Sopenharmony_ci
467962306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10dc,
468062306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
468162306a36Sopenharmony_ci
468262306a36Sopenharmony_ci	if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) &&
468362306a36Sopenharmony_ci	    !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw))
468462306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
468562306a36Sopenharmony_ci
468662306a36Sopenharmony_ci	mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
468762306a36Sopenharmony_ci	mcp->mb[1] = FAC_OPT_CMD_GET_SECTOR_SIZE;
468862306a36Sopenharmony_ci	mcp->out_mb = MBX_1|MBX_0;
468962306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
469062306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
469162306a36Sopenharmony_ci	mcp->flags = 0;
469262306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
469362306a36Sopenharmony_ci
469462306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
469562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10dd,
469662306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x.\n",
469762306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1]);
469862306a36Sopenharmony_ci	} else {
469962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10de,
470062306a36Sopenharmony_ci		    "Done %s.\n", __func__);
470162306a36Sopenharmony_ci		*sector_size = mcp->mb[1];
470262306a36Sopenharmony_ci	}
470362306a36Sopenharmony_ci
470462306a36Sopenharmony_ci	return rval;
470562306a36Sopenharmony_ci}
470662306a36Sopenharmony_ci
470762306a36Sopenharmony_ciint
470862306a36Sopenharmony_ciqla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable)
470962306a36Sopenharmony_ci{
471062306a36Sopenharmony_ci	int rval;
471162306a36Sopenharmony_ci	mbx_cmd_t mc;
471262306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
471362306a36Sopenharmony_ci
471462306a36Sopenharmony_ci	if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) &&
471562306a36Sopenharmony_ci	    !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw))
471662306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
471762306a36Sopenharmony_ci
471862306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10df,
471962306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
472062306a36Sopenharmony_ci
472162306a36Sopenharmony_ci	mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
472262306a36Sopenharmony_ci	mcp->mb[1] = enable ? FAC_OPT_CMD_WRITE_ENABLE :
472362306a36Sopenharmony_ci	    FAC_OPT_CMD_WRITE_PROTECT;
472462306a36Sopenharmony_ci	mcp->out_mb = MBX_1|MBX_0;
472562306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
472662306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
472762306a36Sopenharmony_ci	mcp->flags = 0;
472862306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
472962306a36Sopenharmony_ci
473062306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
473162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10e0,
473262306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x.\n",
473362306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1]);
473462306a36Sopenharmony_ci	} else {
473562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e1,
473662306a36Sopenharmony_ci		    "Done %s.\n", __func__);
473762306a36Sopenharmony_ci	}
473862306a36Sopenharmony_ci
473962306a36Sopenharmony_ci	return rval;
474062306a36Sopenharmony_ci}
474162306a36Sopenharmony_ci
474262306a36Sopenharmony_ciint
474362306a36Sopenharmony_ciqla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish)
474462306a36Sopenharmony_ci{
474562306a36Sopenharmony_ci	int rval;
474662306a36Sopenharmony_ci	mbx_cmd_t mc;
474762306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
474862306a36Sopenharmony_ci
474962306a36Sopenharmony_ci	if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) &&
475062306a36Sopenharmony_ci	    !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw))
475162306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
475262306a36Sopenharmony_ci
475362306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e2,
475462306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
475562306a36Sopenharmony_ci
475662306a36Sopenharmony_ci	mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
475762306a36Sopenharmony_ci	mcp->mb[1] = FAC_OPT_CMD_ERASE_SECTOR;
475862306a36Sopenharmony_ci	mcp->mb[2] = LSW(start);
475962306a36Sopenharmony_ci	mcp->mb[3] = MSW(start);
476062306a36Sopenharmony_ci	mcp->mb[4] = LSW(finish);
476162306a36Sopenharmony_ci	mcp->mb[5] = MSW(finish);
476262306a36Sopenharmony_ci	mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
476362306a36Sopenharmony_ci	mcp->in_mb = MBX_2|MBX_1|MBX_0;
476462306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
476562306a36Sopenharmony_ci	mcp->flags = 0;
476662306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
476762306a36Sopenharmony_ci
476862306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
476962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10e3,
477062306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
477162306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
477262306a36Sopenharmony_ci	} else {
477362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e4,
477462306a36Sopenharmony_ci		    "Done %s.\n", __func__);
477562306a36Sopenharmony_ci	}
477662306a36Sopenharmony_ci
477762306a36Sopenharmony_ci	return rval;
477862306a36Sopenharmony_ci}
477962306a36Sopenharmony_ci
478062306a36Sopenharmony_ciint
478162306a36Sopenharmony_ciqla81xx_fac_semaphore_access(scsi_qla_host_t *vha, int lock)
478262306a36Sopenharmony_ci{
478362306a36Sopenharmony_ci	int rval = QLA_SUCCESS;
478462306a36Sopenharmony_ci	mbx_cmd_t mc;
478562306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
478662306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
478762306a36Sopenharmony_ci
478862306a36Sopenharmony_ci	if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
478962306a36Sopenharmony_ci	    !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
479062306a36Sopenharmony_ci		return rval;
479162306a36Sopenharmony_ci
479262306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e2,
479362306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
479462306a36Sopenharmony_ci
479562306a36Sopenharmony_ci	mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
479662306a36Sopenharmony_ci	mcp->mb[1] = (lock ? FAC_OPT_CMD_LOCK_SEMAPHORE :
479762306a36Sopenharmony_ci	    FAC_OPT_CMD_UNLOCK_SEMAPHORE);
479862306a36Sopenharmony_ci	mcp->out_mb = MBX_1|MBX_0;
479962306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
480062306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
480162306a36Sopenharmony_ci	mcp->flags = 0;
480262306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
480362306a36Sopenharmony_ci
480462306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
480562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10e3,
480662306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
480762306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
480862306a36Sopenharmony_ci	} else {
480962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e4,
481062306a36Sopenharmony_ci		    "Done %s.\n", __func__);
481162306a36Sopenharmony_ci	}
481262306a36Sopenharmony_ci
481362306a36Sopenharmony_ci	return rval;
481462306a36Sopenharmony_ci}
481562306a36Sopenharmony_ci
481662306a36Sopenharmony_ciint
481762306a36Sopenharmony_ciqla81xx_restart_mpi_firmware(scsi_qla_host_t *vha)
481862306a36Sopenharmony_ci{
481962306a36Sopenharmony_ci	int rval = 0;
482062306a36Sopenharmony_ci	mbx_cmd_t mc;
482162306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
482262306a36Sopenharmony_ci
482362306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e5,
482462306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
482562306a36Sopenharmony_ci
482662306a36Sopenharmony_ci	mcp->mb[0] = MBC_RESTART_MPI_FW;
482762306a36Sopenharmony_ci	mcp->out_mb = MBX_0;
482862306a36Sopenharmony_ci	mcp->in_mb = MBX_0|MBX_1;
482962306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
483062306a36Sopenharmony_ci	mcp->flags = 0;
483162306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
483262306a36Sopenharmony_ci
483362306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
483462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10e6,
483562306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x.\n",
483662306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1]);
483762306a36Sopenharmony_ci	} else {
483862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e7,
483962306a36Sopenharmony_ci		    "Done %s.\n", __func__);
484062306a36Sopenharmony_ci	}
484162306a36Sopenharmony_ci
484262306a36Sopenharmony_ci	return rval;
484362306a36Sopenharmony_ci}
484462306a36Sopenharmony_ci
484562306a36Sopenharmony_ciint
484662306a36Sopenharmony_ciqla82xx_set_driver_version(scsi_qla_host_t *vha, char *version)
484762306a36Sopenharmony_ci{
484862306a36Sopenharmony_ci	int rval;
484962306a36Sopenharmony_ci	mbx_cmd_t mc;
485062306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
485162306a36Sopenharmony_ci	int i;
485262306a36Sopenharmony_ci	int len;
485362306a36Sopenharmony_ci	__le16 *str;
485462306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
485562306a36Sopenharmony_ci
485662306a36Sopenharmony_ci	if (!IS_P3P_TYPE(ha))
485762306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
485862306a36Sopenharmony_ci
485962306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x117b,
486062306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
486162306a36Sopenharmony_ci
486262306a36Sopenharmony_ci	str = (__force __le16 *)version;
486362306a36Sopenharmony_ci	len = strlen(version);
486462306a36Sopenharmony_ci
486562306a36Sopenharmony_ci	mcp->mb[0] = MBC_SET_RNID_PARAMS;
486662306a36Sopenharmony_ci	mcp->mb[1] = RNID_TYPE_SET_VERSION << 8;
486762306a36Sopenharmony_ci	mcp->out_mb = MBX_1|MBX_0;
486862306a36Sopenharmony_ci	for (i = 4; i < 16 && len; i++, str++, len -= 2) {
486962306a36Sopenharmony_ci		mcp->mb[i] = le16_to_cpup(str);
487062306a36Sopenharmony_ci		mcp->out_mb |= 1<<i;
487162306a36Sopenharmony_ci	}
487262306a36Sopenharmony_ci	for (; i < 16; i++) {
487362306a36Sopenharmony_ci		mcp->mb[i] = 0;
487462306a36Sopenharmony_ci		mcp->out_mb |= 1<<i;
487562306a36Sopenharmony_ci	}
487662306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
487762306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
487862306a36Sopenharmony_ci	mcp->flags = 0;
487962306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
488062306a36Sopenharmony_ci
488162306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
488262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x117c,
488362306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]);
488462306a36Sopenharmony_ci	} else {
488562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x117d,
488662306a36Sopenharmony_ci		    "Done %s.\n", __func__);
488762306a36Sopenharmony_ci	}
488862306a36Sopenharmony_ci
488962306a36Sopenharmony_ci	return rval;
489062306a36Sopenharmony_ci}
489162306a36Sopenharmony_ci
489262306a36Sopenharmony_ciint
489362306a36Sopenharmony_ciqla25xx_set_driver_version(scsi_qla_host_t *vha, char *version)
489462306a36Sopenharmony_ci{
489562306a36Sopenharmony_ci	int rval;
489662306a36Sopenharmony_ci	mbx_cmd_t mc;
489762306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
489862306a36Sopenharmony_ci	int len;
489962306a36Sopenharmony_ci	uint16_t dwlen;
490062306a36Sopenharmony_ci	uint8_t *str;
490162306a36Sopenharmony_ci	dma_addr_t str_dma;
490262306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
490362306a36Sopenharmony_ci
490462306a36Sopenharmony_ci	if (!IS_FWI2_CAPABLE(ha) || IS_QLA24XX_TYPE(ha) || IS_QLA81XX(ha) ||
490562306a36Sopenharmony_ci	    IS_P3P_TYPE(ha))
490662306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
490762306a36Sopenharmony_ci
490862306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x117e,
490962306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
491062306a36Sopenharmony_ci
491162306a36Sopenharmony_ci	str = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &str_dma);
491262306a36Sopenharmony_ci	if (!str) {
491362306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x117f,
491462306a36Sopenharmony_ci		    "Failed to allocate driver version param.\n");
491562306a36Sopenharmony_ci		return QLA_MEMORY_ALLOC_FAILED;
491662306a36Sopenharmony_ci	}
491762306a36Sopenharmony_ci
491862306a36Sopenharmony_ci	memcpy(str, "\x7\x3\x11\x0", 4);
491962306a36Sopenharmony_ci	dwlen = str[0];
492062306a36Sopenharmony_ci	len = dwlen * 4 - 4;
492162306a36Sopenharmony_ci	memset(str + 4, 0, len);
492262306a36Sopenharmony_ci	if (len > strlen(version))
492362306a36Sopenharmony_ci		len = strlen(version);
492462306a36Sopenharmony_ci	memcpy(str + 4, version, len);
492562306a36Sopenharmony_ci
492662306a36Sopenharmony_ci	mcp->mb[0] = MBC_SET_RNID_PARAMS;
492762306a36Sopenharmony_ci	mcp->mb[1] = RNID_TYPE_SET_VERSION << 8 | dwlen;
492862306a36Sopenharmony_ci	mcp->mb[2] = MSW(LSD(str_dma));
492962306a36Sopenharmony_ci	mcp->mb[3] = LSW(LSD(str_dma));
493062306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(str_dma));
493162306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(str_dma));
493262306a36Sopenharmony_ci	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
493362306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
493462306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
493562306a36Sopenharmony_ci	mcp->flags = 0;
493662306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
493762306a36Sopenharmony_ci
493862306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
493962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1180,
494062306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]);
494162306a36Sopenharmony_ci	} else {
494262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1181,
494362306a36Sopenharmony_ci		    "Done %s.\n", __func__);
494462306a36Sopenharmony_ci	}
494562306a36Sopenharmony_ci
494662306a36Sopenharmony_ci	dma_pool_free(ha->s_dma_pool, str, str_dma);
494762306a36Sopenharmony_ci
494862306a36Sopenharmony_ci	return rval;
494962306a36Sopenharmony_ci}
495062306a36Sopenharmony_ci
495162306a36Sopenharmony_ciint
495262306a36Sopenharmony_ciqla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma,
495362306a36Sopenharmony_ci			     void *buf, uint16_t bufsiz)
495462306a36Sopenharmony_ci{
495562306a36Sopenharmony_ci	int rval, i;
495662306a36Sopenharmony_ci	mbx_cmd_t mc;
495762306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
495862306a36Sopenharmony_ci	uint32_t	*bp;
495962306a36Sopenharmony_ci
496062306a36Sopenharmony_ci	if (!IS_FWI2_CAPABLE(vha->hw))
496162306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
496262306a36Sopenharmony_ci
496362306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1159,
496462306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
496562306a36Sopenharmony_ci
496662306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_RNID_PARAMS;
496762306a36Sopenharmony_ci	mcp->mb[1] = RNID_TYPE_PORT_LOGIN << 8;
496862306a36Sopenharmony_ci	mcp->mb[2] = MSW(buf_dma);
496962306a36Sopenharmony_ci	mcp->mb[3] = LSW(buf_dma);
497062306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(buf_dma));
497162306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(buf_dma));
497262306a36Sopenharmony_ci	mcp->mb[8] = bufsiz/4;
497362306a36Sopenharmony_ci	mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
497462306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
497562306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
497662306a36Sopenharmony_ci	mcp->flags = 0;
497762306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
497862306a36Sopenharmony_ci
497962306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
498062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x115a,
498162306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]);
498262306a36Sopenharmony_ci	} else {
498362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x115b,
498462306a36Sopenharmony_ci		    "Done %s.\n", __func__);
498562306a36Sopenharmony_ci		bp = (uint32_t *) buf;
498662306a36Sopenharmony_ci		for (i = 0; i < (bufsiz-4)/4; i++, bp++)
498762306a36Sopenharmony_ci			*bp = le32_to_cpu((__force __le32)*bp);
498862306a36Sopenharmony_ci	}
498962306a36Sopenharmony_ci
499062306a36Sopenharmony_ci	return rval;
499162306a36Sopenharmony_ci}
499262306a36Sopenharmony_ci
499362306a36Sopenharmony_ci#define PUREX_CMD_COUNT	4
499462306a36Sopenharmony_ciint
499562306a36Sopenharmony_ciqla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
499662306a36Sopenharmony_ci{
499762306a36Sopenharmony_ci	int rval;
499862306a36Sopenharmony_ci	mbx_cmd_t mc;
499962306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
500062306a36Sopenharmony_ci	uint8_t *els_cmd_map;
500162306a36Sopenharmony_ci	uint8_t active_cnt = 0;
500262306a36Sopenharmony_ci	dma_addr_t els_cmd_map_dma;
500362306a36Sopenharmony_ci	uint8_t cmd_opcode[PUREX_CMD_COUNT];
500462306a36Sopenharmony_ci	uint8_t i, index, purex_bit;
500562306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
500662306a36Sopenharmony_ci
500762306a36Sopenharmony_ci	if (!IS_QLA25XX(ha) && !IS_QLA2031(ha) &&
500862306a36Sopenharmony_ci	    !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
500962306a36Sopenharmony_ci		return QLA_SUCCESS;
501062306a36Sopenharmony_ci
501162306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1197,
501262306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
501362306a36Sopenharmony_ci
501462306a36Sopenharmony_ci	els_cmd_map = dma_alloc_coherent(&ha->pdev->dev, ELS_CMD_MAP_SIZE,
501562306a36Sopenharmony_ci	    &els_cmd_map_dma, GFP_KERNEL);
501662306a36Sopenharmony_ci	if (!els_cmd_map) {
501762306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x7101,
501862306a36Sopenharmony_ci		    "Failed to allocate RDP els command param.\n");
501962306a36Sopenharmony_ci		return QLA_MEMORY_ALLOC_FAILED;
502062306a36Sopenharmony_ci	}
502162306a36Sopenharmony_ci
502262306a36Sopenharmony_ci	/* List of Purex ELS */
502362306a36Sopenharmony_ci	if (ql2xrdpenable) {
502462306a36Sopenharmony_ci		cmd_opcode[active_cnt] = ELS_RDP;
502562306a36Sopenharmony_ci		active_cnt++;
502662306a36Sopenharmony_ci	}
502762306a36Sopenharmony_ci	if (ha->flags.scm_supported_f) {
502862306a36Sopenharmony_ci		cmd_opcode[active_cnt] = ELS_FPIN;
502962306a36Sopenharmony_ci		active_cnt++;
503062306a36Sopenharmony_ci	}
503162306a36Sopenharmony_ci	if (ha->flags.edif_enabled) {
503262306a36Sopenharmony_ci		cmd_opcode[active_cnt] = ELS_AUTH_ELS;
503362306a36Sopenharmony_ci		active_cnt++;
503462306a36Sopenharmony_ci	}
503562306a36Sopenharmony_ci
503662306a36Sopenharmony_ci	for (i = 0; i < active_cnt; i++) {
503762306a36Sopenharmony_ci		index = cmd_opcode[i] / 8;
503862306a36Sopenharmony_ci		purex_bit = cmd_opcode[i] % 8;
503962306a36Sopenharmony_ci		els_cmd_map[index] |= 1 << purex_bit;
504062306a36Sopenharmony_ci	}
504162306a36Sopenharmony_ci
504262306a36Sopenharmony_ci	mcp->mb[0] = MBC_SET_RNID_PARAMS;
504362306a36Sopenharmony_ci	mcp->mb[1] = RNID_TYPE_ELS_CMD << 8;
504462306a36Sopenharmony_ci	mcp->mb[2] = MSW(LSD(els_cmd_map_dma));
504562306a36Sopenharmony_ci	mcp->mb[3] = LSW(LSD(els_cmd_map_dma));
504662306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(els_cmd_map_dma));
504762306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(els_cmd_map_dma));
504862306a36Sopenharmony_ci	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
504962306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
505062306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
505162306a36Sopenharmony_ci	mcp->flags = MBX_DMA_OUT;
505262306a36Sopenharmony_ci	mcp->buf_size = ELS_CMD_MAP_SIZE;
505362306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
505462306a36Sopenharmony_ci
505562306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
505662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x118d,
505762306a36Sopenharmony_ci		    "Failed=%x (%x,%x).\n", rval, mcp->mb[0], mcp->mb[1]);
505862306a36Sopenharmony_ci	} else {
505962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118c,
506062306a36Sopenharmony_ci		    "Done %s.\n", __func__);
506162306a36Sopenharmony_ci	}
506262306a36Sopenharmony_ci
506362306a36Sopenharmony_ci	dma_free_coherent(&ha->pdev->dev, ELS_CMD_MAP_SIZE,
506462306a36Sopenharmony_ci	   els_cmd_map, els_cmd_map_dma);
506562306a36Sopenharmony_ci
506662306a36Sopenharmony_ci	return rval;
506762306a36Sopenharmony_ci}
506862306a36Sopenharmony_ci
506962306a36Sopenharmony_cistatic int
507062306a36Sopenharmony_ciqla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp)
507162306a36Sopenharmony_ci{
507262306a36Sopenharmony_ci	int rval;
507362306a36Sopenharmony_ci	mbx_cmd_t mc;
507462306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
507562306a36Sopenharmony_ci
507662306a36Sopenharmony_ci	if (!IS_FWI2_CAPABLE(vha->hw))
507762306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
507862306a36Sopenharmony_ci
507962306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1159,
508062306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
508162306a36Sopenharmony_ci
508262306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_RNID_PARAMS;
508362306a36Sopenharmony_ci	mcp->mb[1] = RNID_TYPE_ASIC_TEMP << 8;
508462306a36Sopenharmony_ci	mcp->out_mb = MBX_1|MBX_0;
508562306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
508662306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
508762306a36Sopenharmony_ci	mcp->flags = 0;
508862306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
508962306a36Sopenharmony_ci	*temp = mcp->mb[1];
509062306a36Sopenharmony_ci
509162306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
509262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x115a,
509362306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]);
509462306a36Sopenharmony_ci	} else {
509562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x115b,
509662306a36Sopenharmony_ci		    "Done %s.\n", __func__);
509762306a36Sopenharmony_ci	}
509862306a36Sopenharmony_ci
509962306a36Sopenharmony_ci	return rval;
510062306a36Sopenharmony_ci}
510162306a36Sopenharmony_ci
510262306a36Sopenharmony_ciint
510362306a36Sopenharmony_ciqla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp,
510462306a36Sopenharmony_ci	uint16_t dev, uint16_t off, uint16_t len, uint16_t opt)
510562306a36Sopenharmony_ci{
510662306a36Sopenharmony_ci	int rval;
510762306a36Sopenharmony_ci	mbx_cmd_t mc;
510862306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
510962306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
511062306a36Sopenharmony_ci
511162306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e8,
511262306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
511362306a36Sopenharmony_ci
511462306a36Sopenharmony_ci	if (!IS_FWI2_CAPABLE(ha))
511562306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
511662306a36Sopenharmony_ci
511762306a36Sopenharmony_ci	if (len == 1)
511862306a36Sopenharmony_ci		opt |= BIT_0;
511962306a36Sopenharmony_ci
512062306a36Sopenharmony_ci	mcp->mb[0] = MBC_READ_SFP;
512162306a36Sopenharmony_ci	mcp->mb[1] = dev;
512262306a36Sopenharmony_ci	mcp->mb[2] = MSW(LSD(sfp_dma));
512362306a36Sopenharmony_ci	mcp->mb[3] = LSW(LSD(sfp_dma));
512462306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(sfp_dma));
512562306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(sfp_dma));
512662306a36Sopenharmony_ci	mcp->mb[8] = len;
512762306a36Sopenharmony_ci	mcp->mb[9] = off;
512862306a36Sopenharmony_ci	mcp->mb[10] = opt;
512962306a36Sopenharmony_ci	mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
513062306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
513162306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
513262306a36Sopenharmony_ci	mcp->flags = 0;
513362306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
513462306a36Sopenharmony_ci
513562306a36Sopenharmony_ci	if (opt & BIT_0)
513662306a36Sopenharmony_ci		*sfp = mcp->mb[1];
513762306a36Sopenharmony_ci
513862306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
513962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10e9,
514062306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
514162306a36Sopenharmony_ci		if (mcp->mb[0] == MBS_COMMAND_ERROR && mcp->mb[1] == 0x22) {
514262306a36Sopenharmony_ci			/* sfp is not there */
514362306a36Sopenharmony_ci			rval = QLA_INTERFACE_ERROR;
514462306a36Sopenharmony_ci		}
514562306a36Sopenharmony_ci	} else {
514662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea,
514762306a36Sopenharmony_ci		    "Done %s.\n", __func__);
514862306a36Sopenharmony_ci	}
514962306a36Sopenharmony_ci
515062306a36Sopenharmony_ci	return rval;
515162306a36Sopenharmony_ci}
515262306a36Sopenharmony_ci
515362306a36Sopenharmony_ciint
515462306a36Sopenharmony_ciqla2x00_write_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp,
515562306a36Sopenharmony_ci	uint16_t dev, uint16_t off, uint16_t len, uint16_t opt)
515662306a36Sopenharmony_ci{
515762306a36Sopenharmony_ci	int rval;
515862306a36Sopenharmony_ci	mbx_cmd_t mc;
515962306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
516062306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
516162306a36Sopenharmony_ci
516262306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10eb,
516362306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
516462306a36Sopenharmony_ci
516562306a36Sopenharmony_ci	if (!IS_FWI2_CAPABLE(ha))
516662306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
516762306a36Sopenharmony_ci
516862306a36Sopenharmony_ci	if (len == 1)
516962306a36Sopenharmony_ci		opt |= BIT_0;
517062306a36Sopenharmony_ci
517162306a36Sopenharmony_ci	if (opt & BIT_0)
517262306a36Sopenharmony_ci		len = *sfp;
517362306a36Sopenharmony_ci
517462306a36Sopenharmony_ci	mcp->mb[0] = MBC_WRITE_SFP;
517562306a36Sopenharmony_ci	mcp->mb[1] = dev;
517662306a36Sopenharmony_ci	mcp->mb[2] = MSW(LSD(sfp_dma));
517762306a36Sopenharmony_ci	mcp->mb[3] = LSW(LSD(sfp_dma));
517862306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(sfp_dma));
517962306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(sfp_dma));
518062306a36Sopenharmony_ci	mcp->mb[8] = len;
518162306a36Sopenharmony_ci	mcp->mb[9] = off;
518262306a36Sopenharmony_ci	mcp->mb[10] = opt;
518362306a36Sopenharmony_ci	mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
518462306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
518562306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
518662306a36Sopenharmony_ci	mcp->flags = 0;
518762306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
518862306a36Sopenharmony_ci
518962306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
519062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10ec,
519162306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
519262306a36Sopenharmony_ci	} else {
519362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ed,
519462306a36Sopenharmony_ci		    "Done %s.\n", __func__);
519562306a36Sopenharmony_ci	}
519662306a36Sopenharmony_ci
519762306a36Sopenharmony_ci	return rval;
519862306a36Sopenharmony_ci}
519962306a36Sopenharmony_ci
520062306a36Sopenharmony_ciint
520162306a36Sopenharmony_ciqla2x00_get_xgmac_stats(scsi_qla_host_t *vha, dma_addr_t stats_dma,
520262306a36Sopenharmony_ci    uint16_t size_in_bytes, uint16_t *actual_size)
520362306a36Sopenharmony_ci{
520462306a36Sopenharmony_ci	int rval;
520562306a36Sopenharmony_ci	mbx_cmd_t mc;
520662306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
520762306a36Sopenharmony_ci
520862306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ee,
520962306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
521062306a36Sopenharmony_ci
521162306a36Sopenharmony_ci	if (!IS_CNA_CAPABLE(vha->hw))
521262306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
521362306a36Sopenharmony_ci
521462306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_XGMAC_STATS;
521562306a36Sopenharmony_ci	mcp->mb[2] = MSW(stats_dma);
521662306a36Sopenharmony_ci	mcp->mb[3] = LSW(stats_dma);
521762306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(stats_dma));
521862306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(stats_dma));
521962306a36Sopenharmony_ci	mcp->mb[8] = size_in_bytes >> 2;
522062306a36Sopenharmony_ci	mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
522162306a36Sopenharmony_ci	mcp->in_mb = MBX_2|MBX_1|MBX_0;
522262306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
522362306a36Sopenharmony_ci	mcp->flags = 0;
522462306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
522562306a36Sopenharmony_ci
522662306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
522762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10ef,
522862306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
522962306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
523062306a36Sopenharmony_ci	} else {
523162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f0,
523262306a36Sopenharmony_ci		    "Done %s.\n", __func__);
523362306a36Sopenharmony_ci
523462306a36Sopenharmony_ci
523562306a36Sopenharmony_ci		*actual_size = mcp->mb[2] << 2;
523662306a36Sopenharmony_ci	}
523762306a36Sopenharmony_ci
523862306a36Sopenharmony_ci	return rval;
523962306a36Sopenharmony_ci}
524062306a36Sopenharmony_ci
524162306a36Sopenharmony_ciint
524262306a36Sopenharmony_ciqla2x00_get_dcbx_params(scsi_qla_host_t *vha, dma_addr_t tlv_dma,
524362306a36Sopenharmony_ci    uint16_t size)
524462306a36Sopenharmony_ci{
524562306a36Sopenharmony_ci	int rval;
524662306a36Sopenharmony_ci	mbx_cmd_t mc;
524762306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
524862306a36Sopenharmony_ci
524962306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f1,
525062306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
525162306a36Sopenharmony_ci
525262306a36Sopenharmony_ci	if (!IS_CNA_CAPABLE(vha->hw))
525362306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
525462306a36Sopenharmony_ci
525562306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_DCBX_PARAMS;
525662306a36Sopenharmony_ci	mcp->mb[1] = 0;
525762306a36Sopenharmony_ci	mcp->mb[2] = MSW(tlv_dma);
525862306a36Sopenharmony_ci	mcp->mb[3] = LSW(tlv_dma);
525962306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(tlv_dma));
526062306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(tlv_dma));
526162306a36Sopenharmony_ci	mcp->mb[8] = size;
526262306a36Sopenharmony_ci	mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
526362306a36Sopenharmony_ci	mcp->in_mb = MBX_2|MBX_1|MBX_0;
526462306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
526562306a36Sopenharmony_ci	mcp->flags = 0;
526662306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
526762306a36Sopenharmony_ci
526862306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
526962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10f2,
527062306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
527162306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
527262306a36Sopenharmony_ci	} else {
527362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f3,
527462306a36Sopenharmony_ci		    "Done %s.\n", __func__);
527562306a36Sopenharmony_ci	}
527662306a36Sopenharmony_ci
527762306a36Sopenharmony_ci	return rval;
527862306a36Sopenharmony_ci}
527962306a36Sopenharmony_ci
528062306a36Sopenharmony_ciint
528162306a36Sopenharmony_ciqla2x00_read_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t *data)
528262306a36Sopenharmony_ci{
528362306a36Sopenharmony_ci	int rval;
528462306a36Sopenharmony_ci	mbx_cmd_t mc;
528562306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
528662306a36Sopenharmony_ci
528762306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f4,
528862306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
528962306a36Sopenharmony_ci
529062306a36Sopenharmony_ci	if (!IS_FWI2_CAPABLE(vha->hw))
529162306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
529262306a36Sopenharmony_ci
529362306a36Sopenharmony_ci	mcp->mb[0] = MBC_READ_RAM_EXTENDED;
529462306a36Sopenharmony_ci	mcp->mb[1] = LSW(risc_addr);
529562306a36Sopenharmony_ci	mcp->mb[8] = MSW(risc_addr);
529662306a36Sopenharmony_ci	mcp->out_mb = MBX_8|MBX_1|MBX_0;
529762306a36Sopenharmony_ci	mcp->in_mb = MBX_3|MBX_2|MBX_0;
529862306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
529962306a36Sopenharmony_ci	mcp->flags = 0;
530062306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
530162306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
530262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10f5,
530362306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
530462306a36Sopenharmony_ci	} else {
530562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f6,
530662306a36Sopenharmony_ci		    "Done %s.\n", __func__);
530762306a36Sopenharmony_ci		*data = mcp->mb[3] << 16 | mcp->mb[2];
530862306a36Sopenharmony_ci	}
530962306a36Sopenharmony_ci
531062306a36Sopenharmony_ci	return rval;
531162306a36Sopenharmony_ci}
531262306a36Sopenharmony_ci
531362306a36Sopenharmony_ciint
531462306a36Sopenharmony_ciqla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
531562306a36Sopenharmony_ci	uint16_t *mresp)
531662306a36Sopenharmony_ci{
531762306a36Sopenharmony_ci	int rval;
531862306a36Sopenharmony_ci	mbx_cmd_t mc;
531962306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
532062306a36Sopenharmony_ci
532162306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f7,
532262306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
532362306a36Sopenharmony_ci
532462306a36Sopenharmony_ci	memset(mcp->mb, 0 , sizeof(mcp->mb));
532562306a36Sopenharmony_ci	mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
532662306a36Sopenharmony_ci	mcp->mb[1] = mreq->options | BIT_6;	// BIT_6 specifies 64 bit addressing
532762306a36Sopenharmony_ci
532862306a36Sopenharmony_ci	/* transfer count */
532962306a36Sopenharmony_ci	mcp->mb[10] = LSW(mreq->transfer_size);
533062306a36Sopenharmony_ci	mcp->mb[11] = MSW(mreq->transfer_size);
533162306a36Sopenharmony_ci
533262306a36Sopenharmony_ci	/* send data address */
533362306a36Sopenharmony_ci	mcp->mb[14] = LSW(mreq->send_dma);
533462306a36Sopenharmony_ci	mcp->mb[15] = MSW(mreq->send_dma);
533562306a36Sopenharmony_ci	mcp->mb[20] = LSW(MSD(mreq->send_dma));
533662306a36Sopenharmony_ci	mcp->mb[21] = MSW(MSD(mreq->send_dma));
533762306a36Sopenharmony_ci
533862306a36Sopenharmony_ci	/* receive data address */
533962306a36Sopenharmony_ci	mcp->mb[16] = LSW(mreq->rcv_dma);
534062306a36Sopenharmony_ci	mcp->mb[17] = MSW(mreq->rcv_dma);
534162306a36Sopenharmony_ci	mcp->mb[6] = LSW(MSD(mreq->rcv_dma));
534262306a36Sopenharmony_ci	mcp->mb[7] = MSW(MSD(mreq->rcv_dma));
534362306a36Sopenharmony_ci
534462306a36Sopenharmony_ci	/* Iteration count */
534562306a36Sopenharmony_ci	mcp->mb[18] = LSW(mreq->iteration_count);
534662306a36Sopenharmony_ci	mcp->mb[19] = MSW(mreq->iteration_count);
534762306a36Sopenharmony_ci
534862306a36Sopenharmony_ci	mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
534962306a36Sopenharmony_ci	    MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0;
535062306a36Sopenharmony_ci	if (IS_CNA_CAPABLE(vha->hw))
535162306a36Sopenharmony_ci		mcp->out_mb |= MBX_2;
535262306a36Sopenharmony_ci	mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0;
535362306a36Sopenharmony_ci
535462306a36Sopenharmony_ci	mcp->buf_size = mreq->transfer_size;
535562306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
535662306a36Sopenharmony_ci	mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
535762306a36Sopenharmony_ci
535862306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
535962306a36Sopenharmony_ci
536062306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
536162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10f8,
536262306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[3]=%x mb[18]=%x "
536362306a36Sopenharmony_ci		    "mb[19]=%x.\n", rval, mcp->mb[0], mcp->mb[1], mcp->mb[2],
536462306a36Sopenharmony_ci		    mcp->mb[3], mcp->mb[18], mcp->mb[19]);
536562306a36Sopenharmony_ci	} else {
536662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f9,
536762306a36Sopenharmony_ci		    "Done %s.\n", __func__);
536862306a36Sopenharmony_ci	}
536962306a36Sopenharmony_ci
537062306a36Sopenharmony_ci	/* Copy mailbox information */
537162306a36Sopenharmony_ci	memcpy( mresp, mcp->mb, 64);
537262306a36Sopenharmony_ci	return rval;
537362306a36Sopenharmony_ci}
537462306a36Sopenharmony_ci
537562306a36Sopenharmony_ciint
537662306a36Sopenharmony_ciqla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
537762306a36Sopenharmony_ci	uint16_t *mresp)
537862306a36Sopenharmony_ci{
537962306a36Sopenharmony_ci	int rval;
538062306a36Sopenharmony_ci	mbx_cmd_t mc;
538162306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
538262306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
538362306a36Sopenharmony_ci
538462306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10fa,
538562306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
538662306a36Sopenharmony_ci
538762306a36Sopenharmony_ci	memset(mcp->mb, 0 , sizeof(mcp->mb));
538862306a36Sopenharmony_ci	mcp->mb[0] = MBC_DIAGNOSTIC_ECHO;
538962306a36Sopenharmony_ci	/* BIT_6 specifies 64bit address */
539062306a36Sopenharmony_ci	mcp->mb[1] = mreq->options | BIT_15 | BIT_6;
539162306a36Sopenharmony_ci	if (IS_CNA_CAPABLE(ha)) {
539262306a36Sopenharmony_ci		mcp->mb[2] = vha->fcoe_fcf_idx;
539362306a36Sopenharmony_ci	}
539462306a36Sopenharmony_ci	mcp->mb[16] = LSW(mreq->rcv_dma);
539562306a36Sopenharmony_ci	mcp->mb[17] = MSW(mreq->rcv_dma);
539662306a36Sopenharmony_ci	mcp->mb[6] = LSW(MSD(mreq->rcv_dma));
539762306a36Sopenharmony_ci	mcp->mb[7] = MSW(MSD(mreq->rcv_dma));
539862306a36Sopenharmony_ci
539962306a36Sopenharmony_ci	mcp->mb[10] = LSW(mreq->transfer_size);
540062306a36Sopenharmony_ci
540162306a36Sopenharmony_ci	mcp->mb[14] = LSW(mreq->send_dma);
540262306a36Sopenharmony_ci	mcp->mb[15] = MSW(mreq->send_dma);
540362306a36Sopenharmony_ci	mcp->mb[20] = LSW(MSD(mreq->send_dma));
540462306a36Sopenharmony_ci	mcp->mb[21] = MSW(MSD(mreq->send_dma));
540562306a36Sopenharmony_ci
540662306a36Sopenharmony_ci	mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15|
540762306a36Sopenharmony_ci	    MBX_14|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0;
540862306a36Sopenharmony_ci	if (IS_CNA_CAPABLE(ha))
540962306a36Sopenharmony_ci		mcp->out_mb |= MBX_2;
541062306a36Sopenharmony_ci
541162306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
541262306a36Sopenharmony_ci	if (IS_CNA_CAPABLE(ha) || IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) ||
541362306a36Sopenharmony_ci	    IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
541462306a36Sopenharmony_ci		mcp->in_mb |= MBX_1;
541562306a36Sopenharmony_ci	if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) ||
541662306a36Sopenharmony_ci	    IS_QLA28XX(ha))
541762306a36Sopenharmony_ci		mcp->in_mb |= MBX_3;
541862306a36Sopenharmony_ci
541962306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
542062306a36Sopenharmony_ci	mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
542162306a36Sopenharmony_ci	mcp->buf_size = mreq->transfer_size;
542262306a36Sopenharmony_ci
542362306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
542462306a36Sopenharmony_ci
542562306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
542662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10fb,
542762306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x.\n",
542862306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1]);
542962306a36Sopenharmony_ci	} else {
543062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10fc,
543162306a36Sopenharmony_ci		    "Done %s.\n", __func__);
543262306a36Sopenharmony_ci	}
543362306a36Sopenharmony_ci
543462306a36Sopenharmony_ci	/* Copy mailbox information */
543562306a36Sopenharmony_ci	memcpy(mresp, mcp->mb, 64);
543662306a36Sopenharmony_ci	return rval;
543762306a36Sopenharmony_ci}
543862306a36Sopenharmony_ci
543962306a36Sopenharmony_ciint
544062306a36Sopenharmony_ciqla84xx_reset_chip(scsi_qla_host_t *vha, uint16_t enable_diagnostic)
544162306a36Sopenharmony_ci{
544262306a36Sopenharmony_ci	int rval;
544362306a36Sopenharmony_ci	mbx_cmd_t mc;
544462306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
544562306a36Sopenharmony_ci
544662306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10fd,
544762306a36Sopenharmony_ci	    "Entered %s enable_diag=%d.\n", __func__, enable_diagnostic);
544862306a36Sopenharmony_ci
544962306a36Sopenharmony_ci	mcp->mb[0] = MBC_ISP84XX_RESET;
545062306a36Sopenharmony_ci	mcp->mb[1] = enable_diagnostic;
545162306a36Sopenharmony_ci	mcp->out_mb = MBX_1|MBX_0;
545262306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
545362306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
545462306a36Sopenharmony_ci	mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
545562306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
545662306a36Sopenharmony_ci
545762306a36Sopenharmony_ci	if (rval != QLA_SUCCESS)
545862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10fe, "Failed=%x.\n", rval);
545962306a36Sopenharmony_ci	else
546062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ff,
546162306a36Sopenharmony_ci		    "Done %s.\n", __func__);
546262306a36Sopenharmony_ci
546362306a36Sopenharmony_ci	return rval;
546462306a36Sopenharmony_ci}
546562306a36Sopenharmony_ci
546662306a36Sopenharmony_ciint
546762306a36Sopenharmony_ciqla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data)
546862306a36Sopenharmony_ci{
546962306a36Sopenharmony_ci	int rval;
547062306a36Sopenharmony_ci	mbx_cmd_t mc;
547162306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
547262306a36Sopenharmony_ci
547362306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1100,
547462306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
547562306a36Sopenharmony_ci
547662306a36Sopenharmony_ci	if (!IS_FWI2_CAPABLE(vha->hw))
547762306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
547862306a36Sopenharmony_ci
547962306a36Sopenharmony_ci	mcp->mb[0] = MBC_WRITE_RAM_WORD_EXTENDED;
548062306a36Sopenharmony_ci	mcp->mb[1] = LSW(risc_addr);
548162306a36Sopenharmony_ci	mcp->mb[2] = LSW(data);
548262306a36Sopenharmony_ci	mcp->mb[3] = MSW(data);
548362306a36Sopenharmony_ci	mcp->mb[8] = MSW(risc_addr);
548462306a36Sopenharmony_ci	mcp->out_mb = MBX_8|MBX_3|MBX_2|MBX_1|MBX_0;
548562306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
548662306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
548762306a36Sopenharmony_ci	mcp->flags = 0;
548862306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
548962306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
549062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1101,
549162306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x.\n",
549262306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1]);
549362306a36Sopenharmony_ci	} else {
549462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1102,
549562306a36Sopenharmony_ci		    "Done %s.\n", __func__);
549662306a36Sopenharmony_ci	}
549762306a36Sopenharmony_ci
549862306a36Sopenharmony_ci	return rval;
549962306a36Sopenharmony_ci}
550062306a36Sopenharmony_ci
550162306a36Sopenharmony_ciint
550262306a36Sopenharmony_ciqla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb)
550362306a36Sopenharmony_ci{
550462306a36Sopenharmony_ci	int rval;
550562306a36Sopenharmony_ci	uint32_t stat, timer;
550662306a36Sopenharmony_ci	uint16_t mb0 = 0;
550762306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
550862306a36Sopenharmony_ci	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
550962306a36Sopenharmony_ci
551062306a36Sopenharmony_ci	rval = QLA_SUCCESS;
551162306a36Sopenharmony_ci
551262306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1103,
551362306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
551462306a36Sopenharmony_ci
551562306a36Sopenharmony_ci	clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
551662306a36Sopenharmony_ci
551762306a36Sopenharmony_ci	/* Write the MBC data to the registers */
551862306a36Sopenharmony_ci	wrt_reg_word(&reg->mailbox0, MBC_WRITE_MPI_REGISTER);
551962306a36Sopenharmony_ci	wrt_reg_word(&reg->mailbox1, mb[0]);
552062306a36Sopenharmony_ci	wrt_reg_word(&reg->mailbox2, mb[1]);
552162306a36Sopenharmony_ci	wrt_reg_word(&reg->mailbox3, mb[2]);
552262306a36Sopenharmony_ci	wrt_reg_word(&reg->mailbox4, mb[3]);
552362306a36Sopenharmony_ci
552462306a36Sopenharmony_ci	wrt_reg_dword(&reg->hccr, HCCRX_SET_HOST_INT);
552562306a36Sopenharmony_ci
552662306a36Sopenharmony_ci	/* Poll for MBC interrupt */
552762306a36Sopenharmony_ci	for (timer = 6000000; timer; timer--) {
552862306a36Sopenharmony_ci		/* Check for pending interrupts. */
552962306a36Sopenharmony_ci		stat = rd_reg_dword(&reg->host_status);
553062306a36Sopenharmony_ci		if (stat & HSRX_RISC_INT) {
553162306a36Sopenharmony_ci			stat &= 0xff;
553262306a36Sopenharmony_ci
553362306a36Sopenharmony_ci			if (stat == 0x1 || stat == 0x2 ||
553462306a36Sopenharmony_ci			    stat == 0x10 || stat == 0x11) {
553562306a36Sopenharmony_ci				set_bit(MBX_INTERRUPT,
553662306a36Sopenharmony_ci				    &ha->mbx_cmd_flags);
553762306a36Sopenharmony_ci				mb0 = rd_reg_word(&reg->mailbox0);
553862306a36Sopenharmony_ci				wrt_reg_dword(&reg->hccr,
553962306a36Sopenharmony_ci				    HCCRX_CLR_RISC_INT);
554062306a36Sopenharmony_ci				rd_reg_dword(&reg->hccr);
554162306a36Sopenharmony_ci				break;
554262306a36Sopenharmony_ci			}
554362306a36Sopenharmony_ci		}
554462306a36Sopenharmony_ci		udelay(5);
554562306a36Sopenharmony_ci	}
554662306a36Sopenharmony_ci
554762306a36Sopenharmony_ci	if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags))
554862306a36Sopenharmony_ci		rval = mb0 & MBS_MASK;
554962306a36Sopenharmony_ci	else
555062306a36Sopenharmony_ci		rval = QLA_FUNCTION_FAILED;
555162306a36Sopenharmony_ci
555262306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
555362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1104,
555462306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mb[0]);
555562306a36Sopenharmony_ci	} else {
555662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1105,
555762306a36Sopenharmony_ci		    "Done %s.\n", __func__);
555862306a36Sopenharmony_ci	}
555962306a36Sopenharmony_ci
556062306a36Sopenharmony_ci	return rval;
556162306a36Sopenharmony_ci}
556262306a36Sopenharmony_ci
556362306a36Sopenharmony_ci/* Set the specified data rate */
556462306a36Sopenharmony_ciint
556562306a36Sopenharmony_ciqla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode)
556662306a36Sopenharmony_ci{
556762306a36Sopenharmony_ci	int rval;
556862306a36Sopenharmony_ci	mbx_cmd_t mc;
556962306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
557062306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
557162306a36Sopenharmony_ci	uint16_t val;
557262306a36Sopenharmony_ci
557362306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1106,
557462306a36Sopenharmony_ci	    "Entered %s speed:0x%x mode:0x%x.\n", __func__, ha->set_data_rate,
557562306a36Sopenharmony_ci	    mode);
557662306a36Sopenharmony_ci
557762306a36Sopenharmony_ci	if (!IS_FWI2_CAPABLE(ha))
557862306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
557962306a36Sopenharmony_ci
558062306a36Sopenharmony_ci	memset(mcp, 0, sizeof(*mcp));
558162306a36Sopenharmony_ci	switch (ha->set_data_rate) {
558262306a36Sopenharmony_ci	case PORT_SPEED_AUTO:
558362306a36Sopenharmony_ci	case PORT_SPEED_4GB:
558462306a36Sopenharmony_ci	case PORT_SPEED_8GB:
558562306a36Sopenharmony_ci	case PORT_SPEED_16GB:
558662306a36Sopenharmony_ci	case PORT_SPEED_32GB:
558762306a36Sopenharmony_ci		val = ha->set_data_rate;
558862306a36Sopenharmony_ci		break;
558962306a36Sopenharmony_ci	default:
559062306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x1199,
559162306a36Sopenharmony_ci		    "Unrecognized speed setting:%d. Setting Autoneg\n",
559262306a36Sopenharmony_ci		    ha->set_data_rate);
559362306a36Sopenharmony_ci		val = ha->set_data_rate = PORT_SPEED_AUTO;
559462306a36Sopenharmony_ci		break;
559562306a36Sopenharmony_ci	}
559662306a36Sopenharmony_ci
559762306a36Sopenharmony_ci	mcp->mb[0] = MBC_DATA_RATE;
559862306a36Sopenharmony_ci	mcp->mb[1] = mode;
559962306a36Sopenharmony_ci	mcp->mb[2] = val;
560062306a36Sopenharmony_ci
560162306a36Sopenharmony_ci	mcp->out_mb = MBX_2|MBX_1|MBX_0;
560262306a36Sopenharmony_ci	mcp->in_mb = MBX_2|MBX_1|MBX_0;
560362306a36Sopenharmony_ci	if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
560462306a36Sopenharmony_ci		mcp->in_mb |= MBX_4|MBX_3;
560562306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
560662306a36Sopenharmony_ci	mcp->flags = 0;
560762306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
560862306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
560962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1107,
561062306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
561162306a36Sopenharmony_ci	} else {
561262306a36Sopenharmony_ci		if (mcp->mb[1] != 0x7)
561362306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x1179,
561462306a36Sopenharmony_ci				"Speed set:0x%x\n", mcp->mb[1]);
561562306a36Sopenharmony_ci
561662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1108,
561762306a36Sopenharmony_ci		    "Done %s.\n", __func__);
561862306a36Sopenharmony_ci	}
561962306a36Sopenharmony_ci
562062306a36Sopenharmony_ci	return rval;
562162306a36Sopenharmony_ci}
562262306a36Sopenharmony_ci
562362306a36Sopenharmony_ciint
562462306a36Sopenharmony_ciqla2x00_get_data_rate(scsi_qla_host_t *vha)
562562306a36Sopenharmony_ci{
562662306a36Sopenharmony_ci	int rval;
562762306a36Sopenharmony_ci	mbx_cmd_t mc;
562862306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
562962306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
563062306a36Sopenharmony_ci
563162306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1106,
563262306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
563362306a36Sopenharmony_ci
563462306a36Sopenharmony_ci	if (!IS_FWI2_CAPABLE(ha))
563562306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
563662306a36Sopenharmony_ci
563762306a36Sopenharmony_ci	mcp->mb[0] = MBC_DATA_RATE;
563862306a36Sopenharmony_ci	mcp->mb[1] = QLA_GET_DATA_RATE;
563962306a36Sopenharmony_ci	mcp->out_mb = MBX_1|MBX_0;
564062306a36Sopenharmony_ci	mcp->in_mb = MBX_2|MBX_1|MBX_0;
564162306a36Sopenharmony_ci	if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
564262306a36Sopenharmony_ci		mcp->in_mb |= MBX_4|MBX_3;
564362306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
564462306a36Sopenharmony_ci	mcp->flags = 0;
564562306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
564662306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
564762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1107,
564862306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
564962306a36Sopenharmony_ci	} else {
565062306a36Sopenharmony_ci		if (mcp->mb[1] != 0x7)
565162306a36Sopenharmony_ci			ha->link_data_rate = mcp->mb[1];
565262306a36Sopenharmony_ci
565362306a36Sopenharmony_ci		if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
565462306a36Sopenharmony_ci			if (mcp->mb[4] & BIT_0)
565562306a36Sopenharmony_ci				ql_log(ql_log_info, vha, 0x11a2,
565662306a36Sopenharmony_ci				    "FEC=enabled (data rate).\n");
565762306a36Sopenharmony_ci		}
565862306a36Sopenharmony_ci
565962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1108,
566062306a36Sopenharmony_ci		    "Done %s.\n", __func__);
566162306a36Sopenharmony_ci		if (mcp->mb[1] != 0x7)
566262306a36Sopenharmony_ci			ha->link_data_rate = mcp->mb[1];
566362306a36Sopenharmony_ci	}
566462306a36Sopenharmony_ci
566562306a36Sopenharmony_ci	return rval;
566662306a36Sopenharmony_ci}
566762306a36Sopenharmony_ci
566862306a36Sopenharmony_ciint
566962306a36Sopenharmony_ciqla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb)
567062306a36Sopenharmony_ci{
567162306a36Sopenharmony_ci	int rval;
567262306a36Sopenharmony_ci	mbx_cmd_t mc;
567362306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
567462306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
567562306a36Sopenharmony_ci
567662306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1109,
567762306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
567862306a36Sopenharmony_ci
567962306a36Sopenharmony_ci	if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && !IS_QLA8044(ha) &&
568062306a36Sopenharmony_ci	    !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
568162306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
568262306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_PORT_CONFIG;
568362306a36Sopenharmony_ci	mcp->out_mb = MBX_0;
568462306a36Sopenharmony_ci	mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
568562306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
568662306a36Sopenharmony_ci	mcp->flags = 0;
568762306a36Sopenharmony_ci
568862306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
568962306a36Sopenharmony_ci
569062306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
569162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x110a,
569262306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
569362306a36Sopenharmony_ci	} else {
569462306a36Sopenharmony_ci		/* Copy all bits to preserve original value */
569562306a36Sopenharmony_ci		memcpy(mb, &mcp->mb[1], sizeof(uint16_t) * 4);
569662306a36Sopenharmony_ci
569762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110b,
569862306a36Sopenharmony_ci		    "Done %s.\n", __func__);
569962306a36Sopenharmony_ci	}
570062306a36Sopenharmony_ci	return rval;
570162306a36Sopenharmony_ci}
570262306a36Sopenharmony_ci
570362306a36Sopenharmony_ciint
570462306a36Sopenharmony_ciqla81xx_set_port_config(scsi_qla_host_t *vha, uint16_t *mb)
570562306a36Sopenharmony_ci{
570662306a36Sopenharmony_ci	int rval;
570762306a36Sopenharmony_ci	mbx_cmd_t mc;
570862306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
570962306a36Sopenharmony_ci
571062306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110c,
571162306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
571262306a36Sopenharmony_ci
571362306a36Sopenharmony_ci	mcp->mb[0] = MBC_SET_PORT_CONFIG;
571462306a36Sopenharmony_ci	/* Copy all bits to preserve original setting */
571562306a36Sopenharmony_ci	memcpy(&mcp->mb[1], mb, sizeof(uint16_t) * 4);
571662306a36Sopenharmony_ci	mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
571762306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
571862306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
571962306a36Sopenharmony_ci	mcp->flags = 0;
572062306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
572162306a36Sopenharmony_ci
572262306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
572362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x110d,
572462306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
572562306a36Sopenharmony_ci	} else
572662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110e,
572762306a36Sopenharmony_ci		    "Done %s.\n", __func__);
572862306a36Sopenharmony_ci
572962306a36Sopenharmony_ci	return rval;
573062306a36Sopenharmony_ci}
573162306a36Sopenharmony_ci
573262306a36Sopenharmony_ci
573362306a36Sopenharmony_ciint
573462306a36Sopenharmony_ciqla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority,
573562306a36Sopenharmony_ci		uint16_t *mb)
573662306a36Sopenharmony_ci{
573762306a36Sopenharmony_ci	int rval;
573862306a36Sopenharmony_ci	mbx_cmd_t mc;
573962306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
574062306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
574162306a36Sopenharmony_ci
574262306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110f,
574362306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
574462306a36Sopenharmony_ci
574562306a36Sopenharmony_ci	if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha))
574662306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
574762306a36Sopenharmony_ci
574862306a36Sopenharmony_ci	mcp->mb[0] = MBC_PORT_PARAMS;
574962306a36Sopenharmony_ci	mcp->mb[1] = loop_id;
575062306a36Sopenharmony_ci	if (ha->flags.fcp_prio_enabled)
575162306a36Sopenharmony_ci		mcp->mb[2] = BIT_1;
575262306a36Sopenharmony_ci	else
575362306a36Sopenharmony_ci		mcp->mb[2] = BIT_2;
575462306a36Sopenharmony_ci	mcp->mb[4] = priority & 0xf;
575562306a36Sopenharmony_ci	mcp->mb[9] = vha->vp_idx;
575662306a36Sopenharmony_ci	mcp->out_mb = MBX_9|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
575762306a36Sopenharmony_ci	mcp->in_mb = MBX_4|MBX_3|MBX_1|MBX_0;
575862306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
575962306a36Sopenharmony_ci	mcp->flags = 0;
576062306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
576162306a36Sopenharmony_ci	if (mb != NULL) {
576262306a36Sopenharmony_ci		mb[0] = mcp->mb[0];
576362306a36Sopenharmony_ci		mb[1] = mcp->mb[1];
576462306a36Sopenharmony_ci		mb[3] = mcp->mb[3];
576562306a36Sopenharmony_ci		mb[4] = mcp->mb[4];
576662306a36Sopenharmony_ci	}
576762306a36Sopenharmony_ci
576862306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
576962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10cd, "Failed=%x.\n", rval);
577062306a36Sopenharmony_ci	} else {
577162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10cc,
577262306a36Sopenharmony_ci		    "Done %s.\n", __func__);
577362306a36Sopenharmony_ci	}
577462306a36Sopenharmony_ci
577562306a36Sopenharmony_ci	return rval;
577662306a36Sopenharmony_ci}
577762306a36Sopenharmony_ci
577862306a36Sopenharmony_ciint
577962306a36Sopenharmony_ciqla2x00_get_thermal_temp(scsi_qla_host_t *vha, uint16_t *temp)
578062306a36Sopenharmony_ci{
578162306a36Sopenharmony_ci	int rval = QLA_FUNCTION_FAILED;
578262306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
578362306a36Sopenharmony_ci	uint8_t byte;
578462306a36Sopenharmony_ci
578562306a36Sopenharmony_ci	if (!IS_FWI2_CAPABLE(ha) || IS_QLA24XX_TYPE(ha) || IS_QLA81XX(ha)) {
578662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1150,
578762306a36Sopenharmony_ci		    "Thermal not supported by this card.\n");
578862306a36Sopenharmony_ci		return rval;
578962306a36Sopenharmony_ci	}
579062306a36Sopenharmony_ci
579162306a36Sopenharmony_ci	if (IS_QLA25XX(ha)) {
579262306a36Sopenharmony_ci		if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
579362306a36Sopenharmony_ci		    ha->pdev->subsystem_device == 0x0175) {
579462306a36Sopenharmony_ci			rval = qla2x00_read_sfp(vha, 0, &byte,
579562306a36Sopenharmony_ci			    0x98, 0x1, 1, BIT_13|BIT_0);
579662306a36Sopenharmony_ci			*temp = byte;
579762306a36Sopenharmony_ci			return rval;
579862306a36Sopenharmony_ci		}
579962306a36Sopenharmony_ci		if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP &&
580062306a36Sopenharmony_ci		    ha->pdev->subsystem_device == 0x338e) {
580162306a36Sopenharmony_ci			rval = qla2x00_read_sfp(vha, 0, &byte,
580262306a36Sopenharmony_ci			    0x98, 0x1, 1, BIT_15|BIT_14|BIT_0);
580362306a36Sopenharmony_ci			*temp = byte;
580462306a36Sopenharmony_ci			return rval;
580562306a36Sopenharmony_ci		}
580662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10c9,
580762306a36Sopenharmony_ci		    "Thermal not supported by this card.\n");
580862306a36Sopenharmony_ci		return rval;
580962306a36Sopenharmony_ci	}
581062306a36Sopenharmony_ci
581162306a36Sopenharmony_ci	if (IS_QLA82XX(ha)) {
581262306a36Sopenharmony_ci		*temp = qla82xx_read_temperature(vha);
581362306a36Sopenharmony_ci		rval = QLA_SUCCESS;
581462306a36Sopenharmony_ci		return rval;
581562306a36Sopenharmony_ci	} else if (IS_QLA8044(ha)) {
581662306a36Sopenharmony_ci		*temp = qla8044_read_temperature(vha);
581762306a36Sopenharmony_ci		rval = QLA_SUCCESS;
581862306a36Sopenharmony_ci		return rval;
581962306a36Sopenharmony_ci	}
582062306a36Sopenharmony_ci
582162306a36Sopenharmony_ci	rval = qla2x00_read_asic_temperature(vha, temp);
582262306a36Sopenharmony_ci	return rval;
582362306a36Sopenharmony_ci}
582462306a36Sopenharmony_ci
582562306a36Sopenharmony_ciint
582662306a36Sopenharmony_ciqla82xx_mbx_intr_enable(scsi_qla_host_t *vha)
582762306a36Sopenharmony_ci{
582862306a36Sopenharmony_ci	int rval;
582962306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
583062306a36Sopenharmony_ci	mbx_cmd_t mc;
583162306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
583262306a36Sopenharmony_ci
583362306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1017,
583462306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
583562306a36Sopenharmony_ci
583662306a36Sopenharmony_ci	if (!IS_FWI2_CAPABLE(ha))
583762306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
583862306a36Sopenharmony_ci
583962306a36Sopenharmony_ci	memset(mcp, 0, sizeof(mbx_cmd_t));
584062306a36Sopenharmony_ci	mcp->mb[0] = MBC_TOGGLE_INTERRUPT;
584162306a36Sopenharmony_ci	mcp->mb[1] = 1;
584262306a36Sopenharmony_ci
584362306a36Sopenharmony_ci	mcp->out_mb = MBX_1|MBX_0;
584462306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
584562306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
584662306a36Sopenharmony_ci	mcp->flags = 0;
584762306a36Sopenharmony_ci
584862306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
584962306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
585062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1016,
585162306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
585262306a36Sopenharmony_ci	} else {
585362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x100e,
585462306a36Sopenharmony_ci		    "Done %s.\n", __func__);
585562306a36Sopenharmony_ci	}
585662306a36Sopenharmony_ci
585762306a36Sopenharmony_ci	return rval;
585862306a36Sopenharmony_ci}
585962306a36Sopenharmony_ci
586062306a36Sopenharmony_ciint
586162306a36Sopenharmony_ciqla82xx_mbx_intr_disable(scsi_qla_host_t *vha)
586262306a36Sopenharmony_ci{
586362306a36Sopenharmony_ci	int rval;
586462306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
586562306a36Sopenharmony_ci	mbx_cmd_t mc;
586662306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
586762306a36Sopenharmony_ci
586862306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x100d,
586962306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
587062306a36Sopenharmony_ci
587162306a36Sopenharmony_ci	if (!IS_P3P_TYPE(ha))
587262306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
587362306a36Sopenharmony_ci
587462306a36Sopenharmony_ci	memset(mcp, 0, sizeof(mbx_cmd_t));
587562306a36Sopenharmony_ci	mcp->mb[0] = MBC_TOGGLE_INTERRUPT;
587662306a36Sopenharmony_ci	mcp->mb[1] = 0;
587762306a36Sopenharmony_ci
587862306a36Sopenharmony_ci	mcp->out_mb = MBX_1|MBX_0;
587962306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
588062306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
588162306a36Sopenharmony_ci	mcp->flags = 0;
588262306a36Sopenharmony_ci
588362306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
588462306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
588562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x100c,
588662306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
588762306a36Sopenharmony_ci	} else {
588862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x100b,
588962306a36Sopenharmony_ci		    "Done %s.\n", __func__);
589062306a36Sopenharmony_ci	}
589162306a36Sopenharmony_ci
589262306a36Sopenharmony_ci	return rval;
589362306a36Sopenharmony_ci}
589462306a36Sopenharmony_ci
589562306a36Sopenharmony_ciint
589662306a36Sopenharmony_ciqla82xx_md_get_template_size(scsi_qla_host_t *vha)
589762306a36Sopenharmony_ci{
589862306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
589962306a36Sopenharmony_ci	mbx_cmd_t mc;
590062306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
590162306a36Sopenharmony_ci	int rval = QLA_FUNCTION_FAILED;
590262306a36Sopenharmony_ci
590362306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x111f,
590462306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
590562306a36Sopenharmony_ci
590662306a36Sopenharmony_ci	memset(mcp->mb, 0 , sizeof(mcp->mb));
590762306a36Sopenharmony_ci	mcp->mb[0] = LSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
590862306a36Sopenharmony_ci	mcp->mb[1] = MSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
590962306a36Sopenharmony_ci	mcp->mb[2] = LSW(RQST_TMPLT_SIZE);
591062306a36Sopenharmony_ci	mcp->mb[3] = MSW(RQST_TMPLT_SIZE);
591162306a36Sopenharmony_ci
591262306a36Sopenharmony_ci	mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
591362306a36Sopenharmony_ci	mcp->in_mb = MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|
591462306a36Sopenharmony_ci	    MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
591562306a36Sopenharmony_ci
591662306a36Sopenharmony_ci	mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
591762306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
591862306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
591962306a36Sopenharmony_ci
592062306a36Sopenharmony_ci	/* Always copy back return mailbox values. */
592162306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
592262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1120,
592362306a36Sopenharmony_ci		    "mailbox command FAILED=0x%x, subcode=%x.\n",
592462306a36Sopenharmony_ci		    (mcp->mb[1] << 16) | mcp->mb[0],
592562306a36Sopenharmony_ci		    (mcp->mb[3] << 16) | mcp->mb[2]);
592662306a36Sopenharmony_ci	} else {
592762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1121,
592862306a36Sopenharmony_ci		    "Done %s.\n", __func__);
592962306a36Sopenharmony_ci		ha->md_template_size = ((mcp->mb[3] << 16) | mcp->mb[2]);
593062306a36Sopenharmony_ci		if (!ha->md_template_size) {
593162306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x1122,
593262306a36Sopenharmony_ci			    "Null template size obtained.\n");
593362306a36Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
593462306a36Sopenharmony_ci		}
593562306a36Sopenharmony_ci	}
593662306a36Sopenharmony_ci	return rval;
593762306a36Sopenharmony_ci}
593862306a36Sopenharmony_ci
593962306a36Sopenharmony_ciint
594062306a36Sopenharmony_ciqla82xx_md_get_template(scsi_qla_host_t *vha)
594162306a36Sopenharmony_ci{
594262306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
594362306a36Sopenharmony_ci	mbx_cmd_t mc;
594462306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
594562306a36Sopenharmony_ci	int rval = QLA_FUNCTION_FAILED;
594662306a36Sopenharmony_ci
594762306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1123,
594862306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
594962306a36Sopenharmony_ci
595062306a36Sopenharmony_ci	ha->md_tmplt_hdr = dma_alloc_coherent(&ha->pdev->dev,
595162306a36Sopenharmony_ci	   ha->md_template_size, &ha->md_tmplt_hdr_dma, GFP_KERNEL);
595262306a36Sopenharmony_ci	if (!ha->md_tmplt_hdr) {
595362306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x1124,
595462306a36Sopenharmony_ci		    "Unable to allocate memory for Minidump template.\n");
595562306a36Sopenharmony_ci		return rval;
595662306a36Sopenharmony_ci	}
595762306a36Sopenharmony_ci
595862306a36Sopenharmony_ci	memset(mcp->mb, 0 , sizeof(mcp->mb));
595962306a36Sopenharmony_ci	mcp->mb[0] = LSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
596062306a36Sopenharmony_ci	mcp->mb[1] = MSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
596162306a36Sopenharmony_ci	mcp->mb[2] = LSW(RQST_TMPLT);
596262306a36Sopenharmony_ci	mcp->mb[3] = MSW(RQST_TMPLT);
596362306a36Sopenharmony_ci	mcp->mb[4] = LSW(LSD(ha->md_tmplt_hdr_dma));
596462306a36Sopenharmony_ci	mcp->mb[5] = MSW(LSD(ha->md_tmplt_hdr_dma));
596562306a36Sopenharmony_ci	mcp->mb[6] = LSW(MSD(ha->md_tmplt_hdr_dma));
596662306a36Sopenharmony_ci	mcp->mb[7] = MSW(MSD(ha->md_tmplt_hdr_dma));
596762306a36Sopenharmony_ci	mcp->mb[8] = LSW(ha->md_template_size);
596862306a36Sopenharmony_ci	mcp->mb[9] = MSW(ha->md_template_size);
596962306a36Sopenharmony_ci
597062306a36Sopenharmony_ci	mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
597162306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
597262306a36Sopenharmony_ci	mcp->out_mb = MBX_11|MBX_10|MBX_9|MBX_8|
597362306a36Sopenharmony_ci	    MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
597462306a36Sopenharmony_ci	mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
597562306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
597662306a36Sopenharmony_ci
597762306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
597862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1125,
597962306a36Sopenharmony_ci		    "mailbox command FAILED=0x%x, subcode=%x.\n",
598062306a36Sopenharmony_ci		    ((mcp->mb[1] << 16) | mcp->mb[0]),
598162306a36Sopenharmony_ci		    ((mcp->mb[3] << 16) | mcp->mb[2]));
598262306a36Sopenharmony_ci	} else
598362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1126,
598462306a36Sopenharmony_ci		    "Done %s.\n", __func__);
598562306a36Sopenharmony_ci	return rval;
598662306a36Sopenharmony_ci}
598762306a36Sopenharmony_ci
598862306a36Sopenharmony_ciint
598962306a36Sopenharmony_ciqla8044_md_get_template(scsi_qla_host_t *vha)
599062306a36Sopenharmony_ci{
599162306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
599262306a36Sopenharmony_ci	mbx_cmd_t mc;
599362306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
599462306a36Sopenharmony_ci	int rval = QLA_FUNCTION_FAILED;
599562306a36Sopenharmony_ci	int offset = 0, size = MINIDUMP_SIZE_36K;
599662306a36Sopenharmony_ci
599762306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0xb11f,
599862306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
599962306a36Sopenharmony_ci
600062306a36Sopenharmony_ci	ha->md_tmplt_hdr = dma_alloc_coherent(&ha->pdev->dev,
600162306a36Sopenharmony_ci	   ha->md_template_size, &ha->md_tmplt_hdr_dma, GFP_KERNEL);
600262306a36Sopenharmony_ci	if (!ha->md_tmplt_hdr) {
600362306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0xb11b,
600462306a36Sopenharmony_ci		    "Unable to allocate memory for Minidump template.\n");
600562306a36Sopenharmony_ci		return rval;
600662306a36Sopenharmony_ci	}
600762306a36Sopenharmony_ci
600862306a36Sopenharmony_ci	memset(mcp->mb, 0 , sizeof(mcp->mb));
600962306a36Sopenharmony_ci	while (offset < ha->md_template_size) {
601062306a36Sopenharmony_ci		mcp->mb[0] = LSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
601162306a36Sopenharmony_ci		mcp->mb[1] = MSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
601262306a36Sopenharmony_ci		mcp->mb[2] = LSW(RQST_TMPLT);
601362306a36Sopenharmony_ci		mcp->mb[3] = MSW(RQST_TMPLT);
601462306a36Sopenharmony_ci		mcp->mb[4] = LSW(LSD(ha->md_tmplt_hdr_dma + offset));
601562306a36Sopenharmony_ci		mcp->mb[5] = MSW(LSD(ha->md_tmplt_hdr_dma + offset));
601662306a36Sopenharmony_ci		mcp->mb[6] = LSW(MSD(ha->md_tmplt_hdr_dma + offset));
601762306a36Sopenharmony_ci		mcp->mb[7] = MSW(MSD(ha->md_tmplt_hdr_dma + offset));
601862306a36Sopenharmony_ci		mcp->mb[8] = LSW(size);
601962306a36Sopenharmony_ci		mcp->mb[9] = MSW(size);
602062306a36Sopenharmony_ci		mcp->mb[10] = offset & 0x0000FFFF;
602162306a36Sopenharmony_ci		mcp->mb[11] = offset & 0xFFFF0000;
602262306a36Sopenharmony_ci		mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
602362306a36Sopenharmony_ci		mcp->tov = MBX_TOV_SECONDS;
602462306a36Sopenharmony_ci		mcp->out_mb = MBX_11|MBX_10|MBX_9|MBX_8|
602562306a36Sopenharmony_ci			MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
602662306a36Sopenharmony_ci		mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
602762306a36Sopenharmony_ci		rval = qla2x00_mailbox_command(vha, mcp);
602862306a36Sopenharmony_ci
602962306a36Sopenharmony_ci		if (rval != QLA_SUCCESS) {
603062306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0xb11c,
603162306a36Sopenharmony_ci				"mailbox command FAILED=0x%x, subcode=%x.\n",
603262306a36Sopenharmony_ci				((mcp->mb[1] << 16) | mcp->mb[0]),
603362306a36Sopenharmony_ci				((mcp->mb[3] << 16) | mcp->mb[2]));
603462306a36Sopenharmony_ci			return rval;
603562306a36Sopenharmony_ci		} else
603662306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0xb11d,
603762306a36Sopenharmony_ci				"Done %s.\n", __func__);
603862306a36Sopenharmony_ci		offset = offset + size;
603962306a36Sopenharmony_ci	}
604062306a36Sopenharmony_ci	return rval;
604162306a36Sopenharmony_ci}
604262306a36Sopenharmony_ci
604362306a36Sopenharmony_ciint
604462306a36Sopenharmony_ciqla81xx_set_led_config(scsi_qla_host_t *vha, uint16_t *led_cfg)
604562306a36Sopenharmony_ci{
604662306a36Sopenharmony_ci	int rval;
604762306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
604862306a36Sopenharmony_ci	mbx_cmd_t mc;
604962306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
605062306a36Sopenharmony_ci
605162306a36Sopenharmony_ci	if (!IS_QLA81XX(ha) && !IS_QLA8031(ha))
605262306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
605362306a36Sopenharmony_ci
605462306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1133,
605562306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
605662306a36Sopenharmony_ci
605762306a36Sopenharmony_ci	memset(mcp, 0, sizeof(mbx_cmd_t));
605862306a36Sopenharmony_ci	mcp->mb[0] = MBC_SET_LED_CONFIG;
605962306a36Sopenharmony_ci	mcp->mb[1] = led_cfg[0];
606062306a36Sopenharmony_ci	mcp->mb[2] = led_cfg[1];
606162306a36Sopenharmony_ci	if (IS_QLA8031(ha)) {
606262306a36Sopenharmony_ci		mcp->mb[3] = led_cfg[2];
606362306a36Sopenharmony_ci		mcp->mb[4] = led_cfg[3];
606462306a36Sopenharmony_ci		mcp->mb[5] = led_cfg[4];
606562306a36Sopenharmony_ci		mcp->mb[6] = led_cfg[5];
606662306a36Sopenharmony_ci	}
606762306a36Sopenharmony_ci
606862306a36Sopenharmony_ci	mcp->out_mb = MBX_2|MBX_1|MBX_0;
606962306a36Sopenharmony_ci	if (IS_QLA8031(ha))
607062306a36Sopenharmony_ci		mcp->out_mb |= MBX_6|MBX_5|MBX_4|MBX_3;
607162306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
607262306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
607362306a36Sopenharmony_ci	mcp->flags = 0;
607462306a36Sopenharmony_ci
607562306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
607662306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
607762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1134,
607862306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
607962306a36Sopenharmony_ci	} else {
608062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1135,
608162306a36Sopenharmony_ci		    "Done %s.\n", __func__);
608262306a36Sopenharmony_ci	}
608362306a36Sopenharmony_ci
608462306a36Sopenharmony_ci	return rval;
608562306a36Sopenharmony_ci}
608662306a36Sopenharmony_ci
608762306a36Sopenharmony_ciint
608862306a36Sopenharmony_ciqla81xx_get_led_config(scsi_qla_host_t *vha, uint16_t *led_cfg)
608962306a36Sopenharmony_ci{
609062306a36Sopenharmony_ci	int rval;
609162306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
609262306a36Sopenharmony_ci	mbx_cmd_t mc;
609362306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
609462306a36Sopenharmony_ci
609562306a36Sopenharmony_ci	if (!IS_QLA81XX(ha) && !IS_QLA8031(ha))
609662306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
609762306a36Sopenharmony_ci
609862306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1136,
609962306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
610062306a36Sopenharmony_ci
610162306a36Sopenharmony_ci	memset(mcp, 0, sizeof(mbx_cmd_t));
610262306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_LED_CONFIG;
610362306a36Sopenharmony_ci
610462306a36Sopenharmony_ci	mcp->out_mb = MBX_0;
610562306a36Sopenharmony_ci	mcp->in_mb = MBX_2|MBX_1|MBX_0;
610662306a36Sopenharmony_ci	if (IS_QLA8031(ha))
610762306a36Sopenharmony_ci		mcp->in_mb |= MBX_6|MBX_5|MBX_4|MBX_3;
610862306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
610962306a36Sopenharmony_ci	mcp->flags = 0;
611062306a36Sopenharmony_ci
611162306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
611262306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
611362306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1137,
611462306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
611562306a36Sopenharmony_ci	} else {
611662306a36Sopenharmony_ci		led_cfg[0] = mcp->mb[1];
611762306a36Sopenharmony_ci		led_cfg[1] = mcp->mb[2];
611862306a36Sopenharmony_ci		if (IS_QLA8031(ha)) {
611962306a36Sopenharmony_ci			led_cfg[2] = mcp->mb[3];
612062306a36Sopenharmony_ci			led_cfg[3] = mcp->mb[4];
612162306a36Sopenharmony_ci			led_cfg[4] = mcp->mb[5];
612262306a36Sopenharmony_ci			led_cfg[5] = mcp->mb[6];
612362306a36Sopenharmony_ci		}
612462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1138,
612562306a36Sopenharmony_ci		    "Done %s.\n", __func__);
612662306a36Sopenharmony_ci	}
612762306a36Sopenharmony_ci
612862306a36Sopenharmony_ci	return rval;
612962306a36Sopenharmony_ci}
613062306a36Sopenharmony_ci
613162306a36Sopenharmony_ciint
613262306a36Sopenharmony_ciqla82xx_mbx_beacon_ctl(scsi_qla_host_t *vha, int enable)
613362306a36Sopenharmony_ci{
613462306a36Sopenharmony_ci	int rval;
613562306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
613662306a36Sopenharmony_ci	mbx_cmd_t mc;
613762306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
613862306a36Sopenharmony_ci
613962306a36Sopenharmony_ci	if (!IS_P3P_TYPE(ha))
614062306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
614162306a36Sopenharmony_ci
614262306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1127,
614362306a36Sopenharmony_ci		"Entered %s.\n", __func__);
614462306a36Sopenharmony_ci
614562306a36Sopenharmony_ci	memset(mcp, 0, sizeof(mbx_cmd_t));
614662306a36Sopenharmony_ci	mcp->mb[0] = MBC_SET_LED_CONFIG;
614762306a36Sopenharmony_ci	if (enable)
614862306a36Sopenharmony_ci		mcp->mb[7] = 0xE;
614962306a36Sopenharmony_ci	else
615062306a36Sopenharmony_ci		mcp->mb[7] = 0xD;
615162306a36Sopenharmony_ci
615262306a36Sopenharmony_ci	mcp->out_mb = MBX_7|MBX_0;
615362306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
615462306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
615562306a36Sopenharmony_ci	mcp->flags = 0;
615662306a36Sopenharmony_ci
615762306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
615862306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
615962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1128,
616062306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
616162306a36Sopenharmony_ci	} else {
616262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1129,
616362306a36Sopenharmony_ci		    "Done %s.\n", __func__);
616462306a36Sopenharmony_ci	}
616562306a36Sopenharmony_ci
616662306a36Sopenharmony_ci	return rval;
616762306a36Sopenharmony_ci}
616862306a36Sopenharmony_ci
616962306a36Sopenharmony_ciint
617062306a36Sopenharmony_ciqla83xx_wr_reg(scsi_qla_host_t *vha, uint32_t reg, uint32_t data)
617162306a36Sopenharmony_ci{
617262306a36Sopenharmony_ci	int rval;
617362306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
617462306a36Sopenharmony_ci	mbx_cmd_t mc;
617562306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
617662306a36Sopenharmony_ci
617762306a36Sopenharmony_ci	if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
617862306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
617962306a36Sopenharmony_ci
618062306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1130,
618162306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
618262306a36Sopenharmony_ci
618362306a36Sopenharmony_ci	mcp->mb[0] = MBC_WRITE_REMOTE_REG;
618462306a36Sopenharmony_ci	mcp->mb[1] = LSW(reg);
618562306a36Sopenharmony_ci	mcp->mb[2] = MSW(reg);
618662306a36Sopenharmony_ci	mcp->mb[3] = LSW(data);
618762306a36Sopenharmony_ci	mcp->mb[4] = MSW(data);
618862306a36Sopenharmony_ci	mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
618962306a36Sopenharmony_ci
619062306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
619162306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
619262306a36Sopenharmony_ci	mcp->flags = 0;
619362306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
619462306a36Sopenharmony_ci
619562306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
619662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1131,
619762306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
619862306a36Sopenharmony_ci	} else {
619962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1132,
620062306a36Sopenharmony_ci		    "Done %s.\n", __func__);
620162306a36Sopenharmony_ci	}
620262306a36Sopenharmony_ci
620362306a36Sopenharmony_ci	return rval;
620462306a36Sopenharmony_ci}
620562306a36Sopenharmony_ci
620662306a36Sopenharmony_ciint
620762306a36Sopenharmony_ciqla2x00_port_logout(scsi_qla_host_t *vha, struct fc_port *fcport)
620862306a36Sopenharmony_ci{
620962306a36Sopenharmony_ci	int rval;
621062306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
621162306a36Sopenharmony_ci	mbx_cmd_t mc;
621262306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
621362306a36Sopenharmony_ci
621462306a36Sopenharmony_ci	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
621562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x113b,
621662306a36Sopenharmony_ci		    "Implicit LOGO Unsupported.\n");
621762306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
621862306a36Sopenharmony_ci	}
621962306a36Sopenharmony_ci
622062306a36Sopenharmony_ci
622162306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x113c,
622262306a36Sopenharmony_ci	    "Entering %s.\n",  __func__);
622362306a36Sopenharmony_ci
622462306a36Sopenharmony_ci	/* Perform Implicit LOGO. */
622562306a36Sopenharmony_ci	mcp->mb[0] = MBC_PORT_LOGOUT;
622662306a36Sopenharmony_ci	mcp->mb[1] = fcport->loop_id;
622762306a36Sopenharmony_ci	mcp->mb[10] = BIT_15;
622862306a36Sopenharmony_ci	mcp->out_mb = MBX_10|MBX_1|MBX_0;
622962306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
623062306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
623162306a36Sopenharmony_ci	mcp->flags = 0;
623262306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
623362306a36Sopenharmony_ci	if (rval != QLA_SUCCESS)
623462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x113d,
623562306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
623662306a36Sopenharmony_ci	else
623762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x113e,
623862306a36Sopenharmony_ci		    "Done %s.\n", __func__);
623962306a36Sopenharmony_ci
624062306a36Sopenharmony_ci	return rval;
624162306a36Sopenharmony_ci}
624262306a36Sopenharmony_ci
624362306a36Sopenharmony_ciint
624462306a36Sopenharmony_ciqla83xx_rd_reg(scsi_qla_host_t *vha, uint32_t reg, uint32_t *data)
624562306a36Sopenharmony_ci{
624662306a36Sopenharmony_ci	int rval;
624762306a36Sopenharmony_ci	mbx_cmd_t mc;
624862306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
624962306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
625062306a36Sopenharmony_ci	unsigned long retry_max_time = jiffies + (2 * HZ);
625162306a36Sopenharmony_ci
625262306a36Sopenharmony_ci	if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
625362306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
625462306a36Sopenharmony_ci
625562306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx, vha, 0x114b, "Entered %s.\n", __func__);
625662306a36Sopenharmony_ci
625762306a36Sopenharmony_ciretry_rd_reg:
625862306a36Sopenharmony_ci	mcp->mb[0] = MBC_READ_REMOTE_REG;
625962306a36Sopenharmony_ci	mcp->mb[1] = LSW(reg);
626062306a36Sopenharmony_ci	mcp->mb[2] = MSW(reg);
626162306a36Sopenharmony_ci	mcp->out_mb = MBX_2|MBX_1|MBX_0;
626262306a36Sopenharmony_ci	mcp->in_mb = MBX_4|MBX_3|MBX_1|MBX_0;
626362306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
626462306a36Sopenharmony_ci	mcp->flags = 0;
626562306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
626662306a36Sopenharmony_ci
626762306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
626862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x114c,
626962306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x.\n",
627062306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1]);
627162306a36Sopenharmony_ci	} else {
627262306a36Sopenharmony_ci		*data = (mcp->mb[3] | (mcp->mb[4] << 16));
627362306a36Sopenharmony_ci		if (*data == QLA8XXX_BAD_VALUE) {
627462306a36Sopenharmony_ci			/*
627562306a36Sopenharmony_ci			 * During soft-reset CAMRAM register reads might
627662306a36Sopenharmony_ci			 * return 0xbad0bad0. So retry for MAX of 2 sec
627762306a36Sopenharmony_ci			 * while reading camram registers.
627862306a36Sopenharmony_ci			 */
627962306a36Sopenharmony_ci			if (time_after(jiffies, retry_max_time)) {
628062306a36Sopenharmony_ci				ql_dbg(ql_dbg_mbx, vha, 0x1141,
628162306a36Sopenharmony_ci				    "Failure to read CAMRAM register. "
628262306a36Sopenharmony_ci				    "data=0x%x.\n", *data);
628362306a36Sopenharmony_ci				return QLA_FUNCTION_FAILED;
628462306a36Sopenharmony_ci			}
628562306a36Sopenharmony_ci			msleep(100);
628662306a36Sopenharmony_ci			goto retry_rd_reg;
628762306a36Sopenharmony_ci		}
628862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1142, "Done %s.\n", __func__);
628962306a36Sopenharmony_ci	}
629062306a36Sopenharmony_ci
629162306a36Sopenharmony_ci	return rval;
629262306a36Sopenharmony_ci}
629362306a36Sopenharmony_ci
629462306a36Sopenharmony_ciint
629562306a36Sopenharmony_ciqla83xx_restart_nic_firmware(scsi_qla_host_t *vha)
629662306a36Sopenharmony_ci{
629762306a36Sopenharmony_ci	int rval;
629862306a36Sopenharmony_ci	mbx_cmd_t mc;
629962306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
630062306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
630162306a36Sopenharmony_ci
630262306a36Sopenharmony_ci	if (!IS_QLA83XX(ha))
630362306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
630462306a36Sopenharmony_ci
630562306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx, vha, 0x1143, "Entered %s.\n", __func__);
630662306a36Sopenharmony_ci
630762306a36Sopenharmony_ci	mcp->mb[0] = MBC_RESTART_NIC_FIRMWARE;
630862306a36Sopenharmony_ci	mcp->out_mb = MBX_0;
630962306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
631062306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
631162306a36Sopenharmony_ci	mcp->flags = 0;
631262306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
631362306a36Sopenharmony_ci
631462306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
631562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1144,
631662306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x.\n",
631762306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1]);
631862306a36Sopenharmony_ci		qla2xxx_dump_fw(vha);
631962306a36Sopenharmony_ci	} else {
632062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1145, "Done %s.\n", __func__);
632162306a36Sopenharmony_ci	}
632262306a36Sopenharmony_ci
632362306a36Sopenharmony_ci	return rval;
632462306a36Sopenharmony_ci}
632562306a36Sopenharmony_ci
632662306a36Sopenharmony_ciint
632762306a36Sopenharmony_ciqla83xx_access_control(scsi_qla_host_t *vha, uint16_t options,
632862306a36Sopenharmony_ci	uint32_t start_addr, uint32_t end_addr, uint16_t *sector_size)
632962306a36Sopenharmony_ci{
633062306a36Sopenharmony_ci	int rval;
633162306a36Sopenharmony_ci	mbx_cmd_t mc;
633262306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
633362306a36Sopenharmony_ci	uint8_t subcode = (uint8_t)options;
633462306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
633562306a36Sopenharmony_ci
633662306a36Sopenharmony_ci	if (!IS_QLA8031(ha))
633762306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
633862306a36Sopenharmony_ci
633962306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx, vha, 0x1146, "Entered %s.\n", __func__);
634062306a36Sopenharmony_ci
634162306a36Sopenharmony_ci	mcp->mb[0] = MBC_SET_ACCESS_CONTROL;
634262306a36Sopenharmony_ci	mcp->mb[1] = options;
634362306a36Sopenharmony_ci	mcp->out_mb = MBX_1|MBX_0;
634462306a36Sopenharmony_ci	if (subcode & BIT_2) {
634562306a36Sopenharmony_ci		mcp->mb[2] = LSW(start_addr);
634662306a36Sopenharmony_ci		mcp->mb[3] = MSW(start_addr);
634762306a36Sopenharmony_ci		mcp->mb[4] = LSW(end_addr);
634862306a36Sopenharmony_ci		mcp->mb[5] = MSW(end_addr);
634962306a36Sopenharmony_ci		mcp->out_mb |= MBX_5|MBX_4|MBX_3|MBX_2;
635062306a36Sopenharmony_ci	}
635162306a36Sopenharmony_ci	mcp->in_mb = MBX_2|MBX_1|MBX_0;
635262306a36Sopenharmony_ci	if (!(subcode & (BIT_2 | BIT_5)))
635362306a36Sopenharmony_ci		mcp->in_mb |= MBX_4|MBX_3;
635462306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
635562306a36Sopenharmony_ci	mcp->flags = 0;
635662306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
635762306a36Sopenharmony_ci
635862306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
635962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1147,
636062306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[3]=%x mb[4]=%x.\n",
636162306a36Sopenharmony_ci		    rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3],
636262306a36Sopenharmony_ci		    mcp->mb[4]);
636362306a36Sopenharmony_ci		qla2xxx_dump_fw(vha);
636462306a36Sopenharmony_ci	} else {
636562306a36Sopenharmony_ci		if (subcode & BIT_5)
636662306a36Sopenharmony_ci			*sector_size = mcp->mb[1];
636762306a36Sopenharmony_ci		else if (subcode & (BIT_6 | BIT_7)) {
636862306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x1148,
636962306a36Sopenharmony_ci			    "Driver-lock id=%x%x", mcp->mb[4], mcp->mb[3]);
637062306a36Sopenharmony_ci		} else if (subcode & (BIT_3 | BIT_4)) {
637162306a36Sopenharmony_ci			ql_dbg(ql_dbg_mbx, vha, 0x1149,
637262306a36Sopenharmony_ci			    "Flash-lock id=%x%x", mcp->mb[4], mcp->mb[3]);
637362306a36Sopenharmony_ci		}
637462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x114a, "Done %s.\n", __func__);
637562306a36Sopenharmony_ci	}
637662306a36Sopenharmony_ci
637762306a36Sopenharmony_ci	return rval;
637862306a36Sopenharmony_ci}
637962306a36Sopenharmony_ci
638062306a36Sopenharmony_ciint
638162306a36Sopenharmony_ciqla2x00_dump_mctp_data(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr,
638262306a36Sopenharmony_ci	uint32_t size)
638362306a36Sopenharmony_ci{
638462306a36Sopenharmony_ci	int rval;
638562306a36Sopenharmony_ci	mbx_cmd_t mc;
638662306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
638762306a36Sopenharmony_ci
638862306a36Sopenharmony_ci	if (!IS_MCTP_CAPABLE(vha->hw))
638962306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
639062306a36Sopenharmony_ci
639162306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x114f,
639262306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
639362306a36Sopenharmony_ci
639462306a36Sopenharmony_ci	mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED;
639562306a36Sopenharmony_ci	mcp->mb[1] = LSW(addr);
639662306a36Sopenharmony_ci	mcp->mb[2] = MSW(req_dma);
639762306a36Sopenharmony_ci	mcp->mb[3] = LSW(req_dma);
639862306a36Sopenharmony_ci	mcp->mb[4] = MSW(size);
639962306a36Sopenharmony_ci	mcp->mb[5] = LSW(size);
640062306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(req_dma));
640162306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(req_dma));
640262306a36Sopenharmony_ci	mcp->mb[8] = MSW(addr);
640362306a36Sopenharmony_ci	/* Setting RAM ID to valid */
640462306a36Sopenharmony_ci	/* For MCTP RAM ID is 0x40 */
640562306a36Sopenharmony_ci	mcp->mb[10] = BIT_7 | 0x40;
640662306a36Sopenharmony_ci
640762306a36Sopenharmony_ci	mcp->out_mb |= MBX_10|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|
640862306a36Sopenharmony_ci	    MBX_0;
640962306a36Sopenharmony_ci
641062306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
641162306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
641262306a36Sopenharmony_ci	mcp->flags = 0;
641362306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
641462306a36Sopenharmony_ci
641562306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
641662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x114e,
641762306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
641862306a36Sopenharmony_ci	} else {
641962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x114d,
642062306a36Sopenharmony_ci		    "Done %s.\n", __func__);
642162306a36Sopenharmony_ci	}
642262306a36Sopenharmony_ci
642362306a36Sopenharmony_ci	return rval;
642462306a36Sopenharmony_ci}
642562306a36Sopenharmony_ci
642662306a36Sopenharmony_ciint
642762306a36Sopenharmony_ciqla26xx_dport_diagnostics(scsi_qla_host_t *vha,
642862306a36Sopenharmony_ci	void *dd_buf, uint size, uint options)
642962306a36Sopenharmony_ci{
643062306a36Sopenharmony_ci	int rval;
643162306a36Sopenharmony_ci	mbx_cmd_t mc;
643262306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
643362306a36Sopenharmony_ci	dma_addr_t dd_dma;
643462306a36Sopenharmony_ci
643562306a36Sopenharmony_ci	if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) &&
643662306a36Sopenharmony_ci	    !IS_QLA28XX(vha->hw))
643762306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
643862306a36Sopenharmony_ci
643962306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x119f,
644062306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
644162306a36Sopenharmony_ci
644262306a36Sopenharmony_ci	dd_dma = dma_map_single(&vha->hw->pdev->dev,
644362306a36Sopenharmony_ci	    dd_buf, size, DMA_FROM_DEVICE);
644462306a36Sopenharmony_ci	if (dma_mapping_error(&vha->hw->pdev->dev, dd_dma)) {
644562306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x1194, "Failed to map dma buffer.\n");
644662306a36Sopenharmony_ci		return QLA_MEMORY_ALLOC_FAILED;
644762306a36Sopenharmony_ci	}
644862306a36Sopenharmony_ci
644962306a36Sopenharmony_ci	memset(dd_buf, 0, size);
645062306a36Sopenharmony_ci
645162306a36Sopenharmony_ci	mcp->mb[0] = MBC_DPORT_DIAGNOSTICS;
645262306a36Sopenharmony_ci	mcp->mb[1] = options;
645362306a36Sopenharmony_ci	mcp->mb[2] = MSW(LSD(dd_dma));
645462306a36Sopenharmony_ci	mcp->mb[3] = LSW(LSD(dd_dma));
645562306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(dd_dma));
645662306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(dd_dma));
645762306a36Sopenharmony_ci	mcp->mb[8] = size;
645862306a36Sopenharmony_ci	mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
645962306a36Sopenharmony_ci	mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
646062306a36Sopenharmony_ci	mcp->buf_size = size;
646162306a36Sopenharmony_ci	mcp->flags = MBX_DMA_IN;
646262306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS * 4;
646362306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
646462306a36Sopenharmony_ci
646562306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
646662306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1195, "Failed=%x.\n", rval);
646762306a36Sopenharmony_ci	} else {
646862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1196,
646962306a36Sopenharmony_ci		    "Done %s.\n", __func__);
647062306a36Sopenharmony_ci	}
647162306a36Sopenharmony_ci
647262306a36Sopenharmony_ci	dma_unmap_single(&vha->hw->pdev->dev, dd_dma,
647362306a36Sopenharmony_ci	    size, DMA_FROM_DEVICE);
647462306a36Sopenharmony_ci
647562306a36Sopenharmony_ci	return rval;
647662306a36Sopenharmony_ci}
647762306a36Sopenharmony_ci
647862306a36Sopenharmony_ciint
647962306a36Sopenharmony_ciqla26xx_dport_diagnostics_v2(scsi_qla_host_t *vha,
648062306a36Sopenharmony_ci			     struct qla_dport_diag_v2 *dd,  mbx_cmd_t *mcp)
648162306a36Sopenharmony_ci{
648262306a36Sopenharmony_ci	int rval;
648362306a36Sopenharmony_ci	dma_addr_t dd_dma;
648462306a36Sopenharmony_ci	uint size = sizeof(dd->buf);
648562306a36Sopenharmony_ci	uint16_t options = dd->options;
648662306a36Sopenharmony_ci
648762306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x119f,
648862306a36Sopenharmony_ci	       "Entered %s.\n", __func__);
648962306a36Sopenharmony_ci
649062306a36Sopenharmony_ci	dd_dma = dma_map_single(&vha->hw->pdev->dev,
649162306a36Sopenharmony_ci				dd->buf, size, DMA_FROM_DEVICE);
649262306a36Sopenharmony_ci	if (dma_mapping_error(&vha->hw->pdev->dev, dd_dma)) {
649362306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0x1194,
649462306a36Sopenharmony_ci		       "Failed to map dma buffer.\n");
649562306a36Sopenharmony_ci		return QLA_MEMORY_ALLOC_FAILED;
649662306a36Sopenharmony_ci	}
649762306a36Sopenharmony_ci
649862306a36Sopenharmony_ci	memset(dd->buf, 0, size);
649962306a36Sopenharmony_ci
650062306a36Sopenharmony_ci	mcp->mb[0] = MBC_DPORT_DIAGNOSTICS;
650162306a36Sopenharmony_ci	mcp->mb[1] = options;
650262306a36Sopenharmony_ci	mcp->mb[2] = MSW(LSD(dd_dma));
650362306a36Sopenharmony_ci	mcp->mb[3] = LSW(LSD(dd_dma));
650462306a36Sopenharmony_ci	mcp->mb[6] = MSW(MSD(dd_dma));
650562306a36Sopenharmony_ci	mcp->mb[7] = LSW(MSD(dd_dma));
650662306a36Sopenharmony_ci	mcp->mb[8] = size;
650762306a36Sopenharmony_ci	mcp->out_mb = MBX_8 | MBX_7 | MBX_6 | MBX_3 | MBX_2 | MBX_1 | MBX_0;
650862306a36Sopenharmony_ci	mcp->in_mb = MBX_3 | MBX_2 | MBX_1 | MBX_0;
650962306a36Sopenharmony_ci	mcp->buf_size = size;
651062306a36Sopenharmony_ci	mcp->flags = MBX_DMA_IN;
651162306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS * 4;
651262306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
651362306a36Sopenharmony_ci
651462306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
651562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1195, "Failed=%x.\n", rval);
651662306a36Sopenharmony_ci	} else {
651762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1196,
651862306a36Sopenharmony_ci		       "Done %s.\n", __func__);
651962306a36Sopenharmony_ci	}
652062306a36Sopenharmony_ci
652162306a36Sopenharmony_ci	dma_unmap_single(&vha->hw->pdev->dev, dd_dma, size, DMA_FROM_DEVICE);
652262306a36Sopenharmony_ci
652362306a36Sopenharmony_ci	return rval;
652462306a36Sopenharmony_ci}
652562306a36Sopenharmony_ci
652662306a36Sopenharmony_cistatic void qla2x00_async_mb_sp_done(srb_t *sp, int res)
652762306a36Sopenharmony_ci{
652862306a36Sopenharmony_ci	sp->u.iocb_cmd.u.mbx.rc = res;
652962306a36Sopenharmony_ci
653062306a36Sopenharmony_ci	complete(&sp->u.iocb_cmd.u.mbx.comp);
653162306a36Sopenharmony_ci	/* don't free sp here. Let the caller do the free */
653262306a36Sopenharmony_ci}
653362306a36Sopenharmony_ci
653462306a36Sopenharmony_ci/*
653562306a36Sopenharmony_ci * This mailbox uses the iocb interface to send MB command.
653662306a36Sopenharmony_ci * This allows non-critial (non chip setup) command to go
653762306a36Sopenharmony_ci * out in parrallel.
653862306a36Sopenharmony_ci */
653962306a36Sopenharmony_ciint qla24xx_send_mb_cmd(struct scsi_qla_host *vha, mbx_cmd_t *mcp)
654062306a36Sopenharmony_ci{
654162306a36Sopenharmony_ci	int rval = QLA_FUNCTION_FAILED;
654262306a36Sopenharmony_ci	srb_t *sp;
654362306a36Sopenharmony_ci	struct srb_iocb *c;
654462306a36Sopenharmony_ci
654562306a36Sopenharmony_ci	if (!vha->hw->flags.fw_started)
654662306a36Sopenharmony_ci		goto done;
654762306a36Sopenharmony_ci
654862306a36Sopenharmony_ci	/* ref: INIT */
654962306a36Sopenharmony_ci	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
655062306a36Sopenharmony_ci	if (!sp)
655162306a36Sopenharmony_ci		goto done;
655262306a36Sopenharmony_ci
655362306a36Sopenharmony_ci	c = &sp->u.iocb_cmd;
655462306a36Sopenharmony_ci	init_completion(&c->u.mbx.comp);
655562306a36Sopenharmony_ci
655662306a36Sopenharmony_ci	sp->type = SRB_MB_IOCB;
655762306a36Sopenharmony_ci	sp->name = mb_to_str(mcp->mb[0]);
655862306a36Sopenharmony_ci	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
655962306a36Sopenharmony_ci			      qla2x00_async_mb_sp_done);
656062306a36Sopenharmony_ci
656162306a36Sopenharmony_ci	memcpy(sp->u.iocb_cmd.u.mbx.out_mb, mcp->mb, SIZEOF_IOCB_MB_REG);
656262306a36Sopenharmony_ci
656362306a36Sopenharmony_ci	rval = qla2x00_start_sp(sp);
656462306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
656562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1018,
656662306a36Sopenharmony_ci		    "%s: %s Failed submission. %x.\n",
656762306a36Sopenharmony_ci		    __func__, sp->name, rval);
656862306a36Sopenharmony_ci		goto done_free_sp;
656962306a36Sopenharmony_ci	}
657062306a36Sopenharmony_ci
657162306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx, vha, 0x113f, "MB:%s hndl %x submitted\n",
657262306a36Sopenharmony_ci	    sp->name, sp->handle);
657362306a36Sopenharmony_ci
657462306a36Sopenharmony_ci	wait_for_completion(&c->u.mbx.comp);
657562306a36Sopenharmony_ci	memcpy(mcp->mb, sp->u.iocb_cmd.u.mbx.in_mb, SIZEOF_IOCB_MB_REG);
657662306a36Sopenharmony_ci
657762306a36Sopenharmony_ci	rval = c->u.mbx.rc;
657862306a36Sopenharmony_ci	switch (rval) {
657962306a36Sopenharmony_ci	case QLA_FUNCTION_TIMEOUT:
658062306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1140, "%s: %s Timeout. %x.\n",
658162306a36Sopenharmony_ci		    __func__, sp->name, rval);
658262306a36Sopenharmony_ci		break;
658362306a36Sopenharmony_ci	case  QLA_SUCCESS:
658462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x119d, "%s: %s done.\n",
658562306a36Sopenharmony_ci		    __func__, sp->name);
658662306a36Sopenharmony_ci		break;
658762306a36Sopenharmony_ci	default:
658862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x119e, "%s: %s Failed. %x.\n",
658962306a36Sopenharmony_ci		    __func__, sp->name, rval);
659062306a36Sopenharmony_ci		break;
659162306a36Sopenharmony_ci	}
659262306a36Sopenharmony_ci
659362306a36Sopenharmony_cidone_free_sp:
659462306a36Sopenharmony_ci	/* ref: INIT */
659562306a36Sopenharmony_ci	kref_put(&sp->cmd_kref, qla2x00_sp_release);
659662306a36Sopenharmony_cidone:
659762306a36Sopenharmony_ci	return rval;
659862306a36Sopenharmony_ci}
659962306a36Sopenharmony_ci
660062306a36Sopenharmony_ci/*
660162306a36Sopenharmony_ci * qla24xx_gpdb_wait
660262306a36Sopenharmony_ci * NOTE: Do not call this routine from DPC thread
660362306a36Sopenharmony_ci */
660462306a36Sopenharmony_ciint qla24xx_gpdb_wait(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
660562306a36Sopenharmony_ci{
660662306a36Sopenharmony_ci	int rval = QLA_FUNCTION_FAILED;
660762306a36Sopenharmony_ci	dma_addr_t pd_dma;
660862306a36Sopenharmony_ci	struct port_database_24xx *pd;
660962306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
661062306a36Sopenharmony_ci	mbx_cmd_t mc;
661162306a36Sopenharmony_ci
661262306a36Sopenharmony_ci	if (!vha->hw->flags.fw_started)
661362306a36Sopenharmony_ci		goto done;
661462306a36Sopenharmony_ci
661562306a36Sopenharmony_ci	pd = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
661662306a36Sopenharmony_ci	if (pd  == NULL) {
661762306a36Sopenharmony_ci		ql_log(ql_log_warn, vha, 0xd047,
661862306a36Sopenharmony_ci		    "Failed to allocate port database structure.\n");
661962306a36Sopenharmony_ci		goto done_free_sp;
662062306a36Sopenharmony_ci	}
662162306a36Sopenharmony_ci
662262306a36Sopenharmony_ci	memset(&mc, 0, sizeof(mc));
662362306a36Sopenharmony_ci	mc.mb[0] = MBC_GET_PORT_DATABASE;
662462306a36Sopenharmony_ci	mc.mb[1] = fcport->loop_id;
662562306a36Sopenharmony_ci	mc.mb[2] = MSW(pd_dma);
662662306a36Sopenharmony_ci	mc.mb[3] = LSW(pd_dma);
662762306a36Sopenharmony_ci	mc.mb[6] = MSW(MSD(pd_dma));
662862306a36Sopenharmony_ci	mc.mb[7] = LSW(MSD(pd_dma));
662962306a36Sopenharmony_ci	mc.mb[9] = vha->vp_idx;
663062306a36Sopenharmony_ci	mc.mb[10] = opt;
663162306a36Sopenharmony_ci
663262306a36Sopenharmony_ci	rval = qla24xx_send_mb_cmd(vha, &mc);
663362306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
663462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x1193,
663562306a36Sopenharmony_ci		    "%s: %8phC fail\n", __func__, fcport->port_name);
663662306a36Sopenharmony_ci		goto done_free_sp;
663762306a36Sopenharmony_ci	}
663862306a36Sopenharmony_ci
663962306a36Sopenharmony_ci	rval = __qla24xx_parse_gpdb(vha, fcport, pd);
664062306a36Sopenharmony_ci
664162306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx, vha, 0x1197, "%s: %8phC done\n",
664262306a36Sopenharmony_ci	    __func__, fcport->port_name);
664362306a36Sopenharmony_ci
664462306a36Sopenharmony_cidone_free_sp:
664562306a36Sopenharmony_ci	if (pd)
664662306a36Sopenharmony_ci		dma_pool_free(ha->s_dma_pool, pd, pd_dma);
664762306a36Sopenharmony_cidone:
664862306a36Sopenharmony_ci	return rval;
664962306a36Sopenharmony_ci}
665062306a36Sopenharmony_ci
665162306a36Sopenharmony_ciint __qla24xx_parse_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport,
665262306a36Sopenharmony_ci    struct port_database_24xx *pd)
665362306a36Sopenharmony_ci{
665462306a36Sopenharmony_ci	int rval = QLA_SUCCESS;
665562306a36Sopenharmony_ci	uint64_t zero = 0;
665662306a36Sopenharmony_ci	u8 current_login_state, last_login_state;
665762306a36Sopenharmony_ci
665862306a36Sopenharmony_ci	if (NVME_TARGET(vha->hw, fcport)) {
665962306a36Sopenharmony_ci		current_login_state = pd->current_login_state >> 4;
666062306a36Sopenharmony_ci		last_login_state = pd->last_login_state >> 4;
666162306a36Sopenharmony_ci	} else {
666262306a36Sopenharmony_ci		current_login_state = pd->current_login_state & 0xf;
666362306a36Sopenharmony_ci		last_login_state = pd->last_login_state & 0xf;
666462306a36Sopenharmony_ci	}
666562306a36Sopenharmony_ci
666662306a36Sopenharmony_ci	/* Check for logged in state. */
666762306a36Sopenharmony_ci	if (current_login_state != PDS_PRLI_COMPLETE) {
666862306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x119a,
666962306a36Sopenharmony_ci		    "Unable to verify login-state (%x/%x) for loop_id %x.\n",
667062306a36Sopenharmony_ci		    current_login_state, last_login_state, fcport->loop_id);
667162306a36Sopenharmony_ci		rval = QLA_FUNCTION_FAILED;
667262306a36Sopenharmony_ci		goto gpd_error_out;
667362306a36Sopenharmony_ci	}
667462306a36Sopenharmony_ci
667562306a36Sopenharmony_ci	if (fcport->loop_id == FC_NO_LOOP_ID ||
667662306a36Sopenharmony_ci	    (memcmp(fcport->port_name, (uint8_t *)&zero, 8) &&
667762306a36Sopenharmony_ci	     memcmp(fcport->port_name, pd->port_name, 8))) {
667862306a36Sopenharmony_ci		/* We lost the device mid way. */
667962306a36Sopenharmony_ci		rval = QLA_NOT_LOGGED_IN;
668062306a36Sopenharmony_ci		goto gpd_error_out;
668162306a36Sopenharmony_ci	}
668262306a36Sopenharmony_ci
668362306a36Sopenharmony_ci	/* Names are little-endian. */
668462306a36Sopenharmony_ci	memcpy(fcport->node_name, pd->node_name, WWN_SIZE);
668562306a36Sopenharmony_ci	memcpy(fcport->port_name, pd->port_name, WWN_SIZE);
668662306a36Sopenharmony_ci
668762306a36Sopenharmony_ci	/* Get port_id of device. */
668862306a36Sopenharmony_ci	fcport->d_id.b.domain = pd->port_id[0];
668962306a36Sopenharmony_ci	fcport->d_id.b.area = pd->port_id[1];
669062306a36Sopenharmony_ci	fcport->d_id.b.al_pa = pd->port_id[2];
669162306a36Sopenharmony_ci	fcport->d_id.b.rsvd_1 = 0;
669262306a36Sopenharmony_ci
669362306a36Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x2062,
669462306a36Sopenharmony_ci	     "%8phC SVC Param w3 %02x%02x",
669562306a36Sopenharmony_ci	     fcport->port_name,
669662306a36Sopenharmony_ci	     pd->prli_svc_param_word_3[1],
669762306a36Sopenharmony_ci	     pd->prli_svc_param_word_3[0]);
669862306a36Sopenharmony_ci
669962306a36Sopenharmony_ci	if (NVME_TARGET(vha->hw, fcport)) {
670062306a36Sopenharmony_ci		fcport->port_type = FCT_NVME;
670162306a36Sopenharmony_ci		if ((pd->prli_svc_param_word_3[0] & BIT_5) == 0)
670262306a36Sopenharmony_ci			fcport->port_type |= FCT_NVME_INITIATOR;
670362306a36Sopenharmony_ci		if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
670462306a36Sopenharmony_ci			fcport->port_type |= FCT_NVME_TARGET;
670562306a36Sopenharmony_ci		if ((pd->prli_svc_param_word_3[0] & BIT_3) == 0)
670662306a36Sopenharmony_ci			fcport->port_type |= FCT_NVME_DISCOVERY;
670762306a36Sopenharmony_ci	} else {
670862306a36Sopenharmony_ci		/* If not target must be initiator or unknown type. */
670962306a36Sopenharmony_ci		if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
671062306a36Sopenharmony_ci			fcport->port_type = FCT_INITIATOR;
671162306a36Sopenharmony_ci		else
671262306a36Sopenharmony_ci			fcport->port_type = FCT_TARGET;
671362306a36Sopenharmony_ci	}
671462306a36Sopenharmony_ci	/* Passback COS information. */
671562306a36Sopenharmony_ci	fcport->supported_classes = (pd->flags & PDF_CLASS_2) ?
671662306a36Sopenharmony_ci		FC_COS_CLASS2 : FC_COS_CLASS3;
671762306a36Sopenharmony_ci
671862306a36Sopenharmony_ci	if (pd->prli_svc_param_word_3[0] & BIT_7) {
671962306a36Sopenharmony_ci		fcport->flags |= FCF_CONF_COMP_SUPPORTED;
672062306a36Sopenharmony_ci		fcport->conf_compl_supported = 1;
672162306a36Sopenharmony_ci	}
672262306a36Sopenharmony_ci
672362306a36Sopenharmony_cigpd_error_out:
672462306a36Sopenharmony_ci	return rval;
672562306a36Sopenharmony_ci}
672662306a36Sopenharmony_ci
672762306a36Sopenharmony_ci/*
672862306a36Sopenharmony_ci * qla24xx_gidlist__wait
672962306a36Sopenharmony_ci * NOTE: don't call this routine from DPC thread.
673062306a36Sopenharmony_ci */
673162306a36Sopenharmony_ciint qla24xx_gidlist_wait(struct scsi_qla_host *vha,
673262306a36Sopenharmony_ci	void *id_list, dma_addr_t id_list_dma, uint16_t *entries)
673362306a36Sopenharmony_ci{
673462306a36Sopenharmony_ci	int rval = QLA_FUNCTION_FAILED;
673562306a36Sopenharmony_ci	mbx_cmd_t mc;
673662306a36Sopenharmony_ci
673762306a36Sopenharmony_ci	if (!vha->hw->flags.fw_started)
673862306a36Sopenharmony_ci		goto done;
673962306a36Sopenharmony_ci
674062306a36Sopenharmony_ci	memset(&mc, 0, sizeof(mc));
674162306a36Sopenharmony_ci	mc.mb[0] = MBC_GET_ID_LIST;
674262306a36Sopenharmony_ci	mc.mb[2] = MSW(id_list_dma);
674362306a36Sopenharmony_ci	mc.mb[3] = LSW(id_list_dma);
674462306a36Sopenharmony_ci	mc.mb[6] = MSW(MSD(id_list_dma));
674562306a36Sopenharmony_ci	mc.mb[7] = LSW(MSD(id_list_dma));
674662306a36Sopenharmony_ci	mc.mb[8] = 0;
674762306a36Sopenharmony_ci	mc.mb[9] = vha->vp_idx;
674862306a36Sopenharmony_ci
674962306a36Sopenharmony_ci	rval = qla24xx_send_mb_cmd(vha, &mc);
675062306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
675162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x119b,
675262306a36Sopenharmony_ci		    "%s:  fail\n", __func__);
675362306a36Sopenharmony_ci	} else {
675462306a36Sopenharmony_ci		*entries = mc.mb[1];
675562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x119c,
675662306a36Sopenharmony_ci		    "%s:  done\n", __func__);
675762306a36Sopenharmony_ci	}
675862306a36Sopenharmony_cidone:
675962306a36Sopenharmony_ci	return rval;
676062306a36Sopenharmony_ci}
676162306a36Sopenharmony_ci
676262306a36Sopenharmony_ciint qla27xx_set_zio_threshold(scsi_qla_host_t *vha, uint16_t value)
676362306a36Sopenharmony_ci{
676462306a36Sopenharmony_ci	int rval;
676562306a36Sopenharmony_ci	mbx_cmd_t	mc;
676662306a36Sopenharmony_ci	mbx_cmd_t	*mcp = &mc;
676762306a36Sopenharmony_ci
676862306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1200,
676962306a36Sopenharmony_ci	    "Entered %s\n", __func__);
677062306a36Sopenharmony_ci
677162306a36Sopenharmony_ci	memset(mcp->mb, 0 , sizeof(mcp->mb));
677262306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_SET_ZIO_THRESHOLD;
677362306a36Sopenharmony_ci	mcp->mb[1] = 1;
677462306a36Sopenharmony_ci	mcp->mb[2] = value;
677562306a36Sopenharmony_ci	mcp->out_mb = MBX_2 | MBX_1 | MBX_0;
677662306a36Sopenharmony_ci	mcp->in_mb = MBX_2 | MBX_0;
677762306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
677862306a36Sopenharmony_ci	mcp->flags = 0;
677962306a36Sopenharmony_ci
678062306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
678162306a36Sopenharmony_ci
678262306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx, vha, 0x1201, "%s %x\n",
678362306a36Sopenharmony_ci	    (rval != QLA_SUCCESS) ? "Failed"  : "Done", rval);
678462306a36Sopenharmony_ci
678562306a36Sopenharmony_ci	return rval;
678662306a36Sopenharmony_ci}
678762306a36Sopenharmony_ci
678862306a36Sopenharmony_ciint qla27xx_get_zio_threshold(scsi_qla_host_t *vha, uint16_t *value)
678962306a36Sopenharmony_ci{
679062306a36Sopenharmony_ci	int rval;
679162306a36Sopenharmony_ci	mbx_cmd_t	mc;
679262306a36Sopenharmony_ci	mbx_cmd_t	*mcp = &mc;
679362306a36Sopenharmony_ci
679462306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1203,
679562306a36Sopenharmony_ci	    "Entered %s\n", __func__);
679662306a36Sopenharmony_ci
679762306a36Sopenharmony_ci	memset(mcp->mb, 0, sizeof(mcp->mb));
679862306a36Sopenharmony_ci	mcp->mb[0] = MBC_GET_SET_ZIO_THRESHOLD;
679962306a36Sopenharmony_ci	mcp->mb[1] = 0;
680062306a36Sopenharmony_ci	mcp->out_mb = MBX_1 | MBX_0;
680162306a36Sopenharmony_ci	mcp->in_mb = MBX_2 | MBX_0;
680262306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
680362306a36Sopenharmony_ci	mcp->flags = 0;
680462306a36Sopenharmony_ci
680562306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
680662306a36Sopenharmony_ci	if (rval == QLA_SUCCESS)
680762306a36Sopenharmony_ci		*value = mc.mb[2];
680862306a36Sopenharmony_ci
680962306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx, vha, 0x1205, "%s %x\n",
681062306a36Sopenharmony_ci	    (rval != QLA_SUCCESS) ? "Failed" : "Done", rval);
681162306a36Sopenharmony_ci
681262306a36Sopenharmony_ci	return rval;
681362306a36Sopenharmony_ci}
681462306a36Sopenharmony_ci
681562306a36Sopenharmony_ciint
681662306a36Sopenharmony_ciqla2x00_read_sfp_dev(struct scsi_qla_host *vha, char *buf, int count)
681762306a36Sopenharmony_ci{
681862306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
681962306a36Sopenharmony_ci	uint16_t iter, addr, offset;
682062306a36Sopenharmony_ci	dma_addr_t phys_addr;
682162306a36Sopenharmony_ci	int rval, c;
682262306a36Sopenharmony_ci	u8 *sfp_data;
682362306a36Sopenharmony_ci
682462306a36Sopenharmony_ci	memset(ha->sfp_data, 0, SFP_DEV_SIZE);
682562306a36Sopenharmony_ci	addr = 0xa0;
682662306a36Sopenharmony_ci	phys_addr = ha->sfp_data_dma;
682762306a36Sopenharmony_ci	sfp_data = ha->sfp_data;
682862306a36Sopenharmony_ci	offset = c = 0;
682962306a36Sopenharmony_ci
683062306a36Sopenharmony_ci	for (iter = 0; iter < SFP_DEV_SIZE / SFP_BLOCK_SIZE; iter++) {
683162306a36Sopenharmony_ci		if (iter == 4) {
683262306a36Sopenharmony_ci			/* Skip to next device address. */
683362306a36Sopenharmony_ci			addr = 0xa2;
683462306a36Sopenharmony_ci			offset = 0;
683562306a36Sopenharmony_ci		}
683662306a36Sopenharmony_ci
683762306a36Sopenharmony_ci		rval = qla2x00_read_sfp(vha, phys_addr, sfp_data,
683862306a36Sopenharmony_ci		    addr, offset, SFP_BLOCK_SIZE, BIT_1);
683962306a36Sopenharmony_ci		if (rval != QLA_SUCCESS) {
684062306a36Sopenharmony_ci			ql_log(ql_log_warn, vha, 0x706d,
684162306a36Sopenharmony_ci			    "Unable to read SFP data (%x/%x/%x).\n", rval,
684262306a36Sopenharmony_ci			    addr, offset);
684362306a36Sopenharmony_ci
684462306a36Sopenharmony_ci			return rval;
684562306a36Sopenharmony_ci		}
684662306a36Sopenharmony_ci
684762306a36Sopenharmony_ci		if (buf && (c < count)) {
684862306a36Sopenharmony_ci			u16 sz;
684962306a36Sopenharmony_ci
685062306a36Sopenharmony_ci			if ((count - c) >= SFP_BLOCK_SIZE)
685162306a36Sopenharmony_ci				sz = SFP_BLOCK_SIZE;
685262306a36Sopenharmony_ci			else
685362306a36Sopenharmony_ci				sz = count - c;
685462306a36Sopenharmony_ci
685562306a36Sopenharmony_ci			memcpy(buf, sfp_data, sz);
685662306a36Sopenharmony_ci			buf += SFP_BLOCK_SIZE;
685762306a36Sopenharmony_ci			c += sz;
685862306a36Sopenharmony_ci		}
685962306a36Sopenharmony_ci		phys_addr += SFP_BLOCK_SIZE;
686062306a36Sopenharmony_ci		sfp_data  += SFP_BLOCK_SIZE;
686162306a36Sopenharmony_ci		offset += SFP_BLOCK_SIZE;
686262306a36Sopenharmony_ci	}
686362306a36Sopenharmony_ci
686462306a36Sopenharmony_ci	return rval;
686562306a36Sopenharmony_ci}
686662306a36Sopenharmony_ci
686762306a36Sopenharmony_ciint qla24xx_res_count_wait(struct scsi_qla_host *vha,
686862306a36Sopenharmony_ci    uint16_t *out_mb, int out_mb_sz)
686962306a36Sopenharmony_ci{
687062306a36Sopenharmony_ci	int rval = QLA_FUNCTION_FAILED;
687162306a36Sopenharmony_ci	mbx_cmd_t mc;
687262306a36Sopenharmony_ci
687362306a36Sopenharmony_ci	if (!vha->hw->flags.fw_started)
687462306a36Sopenharmony_ci		goto done;
687562306a36Sopenharmony_ci
687662306a36Sopenharmony_ci	memset(&mc, 0, sizeof(mc));
687762306a36Sopenharmony_ci	mc.mb[0] = MBC_GET_RESOURCE_COUNTS;
687862306a36Sopenharmony_ci
687962306a36Sopenharmony_ci	rval = qla24xx_send_mb_cmd(vha, &mc);
688062306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
688162306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0xffff,
688262306a36Sopenharmony_ci			"%s:  fail\n", __func__);
688362306a36Sopenharmony_ci	} else {
688462306a36Sopenharmony_ci		if (out_mb_sz <= SIZEOF_IOCB_MB_REG)
688562306a36Sopenharmony_ci			memcpy(out_mb, mc.mb, out_mb_sz);
688662306a36Sopenharmony_ci		else
688762306a36Sopenharmony_ci			memcpy(out_mb, mc.mb, SIZEOF_IOCB_MB_REG);
688862306a36Sopenharmony_ci
688962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0xffff,
689062306a36Sopenharmony_ci			"%s:  done\n", __func__);
689162306a36Sopenharmony_ci	}
689262306a36Sopenharmony_cidone:
689362306a36Sopenharmony_ci	return rval;
689462306a36Sopenharmony_ci}
689562306a36Sopenharmony_ci
689662306a36Sopenharmony_ciint qla28xx_secure_flash_update(scsi_qla_host_t *vha, uint16_t opts,
689762306a36Sopenharmony_ci    uint16_t region, uint32_t len, dma_addr_t sfub_dma_addr,
689862306a36Sopenharmony_ci    uint32_t sfub_len)
689962306a36Sopenharmony_ci{
690062306a36Sopenharmony_ci	int		rval;
690162306a36Sopenharmony_ci	mbx_cmd_t mc;
690262306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
690362306a36Sopenharmony_ci
690462306a36Sopenharmony_ci	mcp->mb[0] = MBC_SECURE_FLASH_UPDATE;
690562306a36Sopenharmony_ci	mcp->mb[1] = opts;
690662306a36Sopenharmony_ci	mcp->mb[2] = region;
690762306a36Sopenharmony_ci	mcp->mb[3] = MSW(len);
690862306a36Sopenharmony_ci	mcp->mb[4] = LSW(len);
690962306a36Sopenharmony_ci	mcp->mb[5] = MSW(sfub_dma_addr);
691062306a36Sopenharmony_ci	mcp->mb[6] = LSW(sfub_dma_addr);
691162306a36Sopenharmony_ci	mcp->mb[7] = MSW(MSD(sfub_dma_addr));
691262306a36Sopenharmony_ci	mcp->mb[8] = LSW(MSD(sfub_dma_addr));
691362306a36Sopenharmony_ci	mcp->mb[9] = sfub_len;
691462306a36Sopenharmony_ci	mcp->out_mb =
691562306a36Sopenharmony_ci	    MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
691662306a36Sopenharmony_ci	mcp->in_mb = MBX_2|MBX_1|MBX_0;
691762306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
691862306a36Sopenharmony_ci	mcp->flags = 0;
691962306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
692062306a36Sopenharmony_ci
692162306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
692262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0xffff, "%s(%ld): failed rval 0x%x, %x %x %x",
692362306a36Sopenharmony_ci			__func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1],
692462306a36Sopenharmony_ci			mcp->mb[2]);
692562306a36Sopenharmony_ci	}
692662306a36Sopenharmony_ci
692762306a36Sopenharmony_ci	return rval;
692862306a36Sopenharmony_ci}
692962306a36Sopenharmony_ci
693062306a36Sopenharmony_ciint qla2xxx_write_remote_register(scsi_qla_host_t *vha, uint32_t addr,
693162306a36Sopenharmony_ci    uint32_t data)
693262306a36Sopenharmony_ci{
693362306a36Sopenharmony_ci	int rval;
693462306a36Sopenharmony_ci	mbx_cmd_t mc;
693562306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
693662306a36Sopenharmony_ci
693762306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e8,
693862306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
693962306a36Sopenharmony_ci
694062306a36Sopenharmony_ci	mcp->mb[0] = MBC_WRITE_REMOTE_REG;
694162306a36Sopenharmony_ci	mcp->mb[1] = LSW(addr);
694262306a36Sopenharmony_ci	mcp->mb[2] = MSW(addr);
694362306a36Sopenharmony_ci	mcp->mb[3] = LSW(data);
694462306a36Sopenharmony_ci	mcp->mb[4] = MSW(data);
694562306a36Sopenharmony_ci	mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
694662306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
694762306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
694862306a36Sopenharmony_ci	mcp->flags = 0;
694962306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
695062306a36Sopenharmony_ci
695162306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
695262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10e9,
695362306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
695462306a36Sopenharmony_ci	} else {
695562306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea,
695662306a36Sopenharmony_ci		    "Done %s.\n", __func__);
695762306a36Sopenharmony_ci	}
695862306a36Sopenharmony_ci
695962306a36Sopenharmony_ci	return rval;
696062306a36Sopenharmony_ci}
696162306a36Sopenharmony_ci
696262306a36Sopenharmony_ciint qla2xxx_read_remote_register(scsi_qla_host_t *vha, uint32_t addr,
696362306a36Sopenharmony_ci    uint32_t *data)
696462306a36Sopenharmony_ci{
696562306a36Sopenharmony_ci	int rval;
696662306a36Sopenharmony_ci	mbx_cmd_t mc;
696762306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
696862306a36Sopenharmony_ci
696962306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e8,
697062306a36Sopenharmony_ci	    "Entered %s.\n", __func__);
697162306a36Sopenharmony_ci
697262306a36Sopenharmony_ci	mcp->mb[0] = MBC_READ_REMOTE_REG;
697362306a36Sopenharmony_ci	mcp->mb[1] = LSW(addr);
697462306a36Sopenharmony_ci	mcp->mb[2] = MSW(addr);
697562306a36Sopenharmony_ci	mcp->out_mb = MBX_2|MBX_1|MBX_0;
697662306a36Sopenharmony_ci	mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
697762306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
697862306a36Sopenharmony_ci	mcp->flags = 0;
697962306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
698062306a36Sopenharmony_ci
698162306a36Sopenharmony_ci	*data = (uint32_t)((((uint32_t)mcp->mb[4]) << 16) | mcp->mb[3]);
698262306a36Sopenharmony_ci
698362306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
698462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x10e9,
698562306a36Sopenharmony_ci		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
698662306a36Sopenharmony_ci	} else {
698762306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea,
698862306a36Sopenharmony_ci		    "Done %s.\n", __func__);
698962306a36Sopenharmony_ci	}
699062306a36Sopenharmony_ci
699162306a36Sopenharmony_ci	return rval;
699262306a36Sopenharmony_ci}
699362306a36Sopenharmony_ci
699462306a36Sopenharmony_ciint
699562306a36Sopenharmony_ciql26xx_led_config(scsi_qla_host_t *vha, uint16_t options, uint16_t *led)
699662306a36Sopenharmony_ci{
699762306a36Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
699862306a36Sopenharmony_ci	mbx_cmd_t mc;
699962306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
700062306a36Sopenharmony_ci	int rval;
700162306a36Sopenharmony_ci
700262306a36Sopenharmony_ci	if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
700362306a36Sopenharmony_ci		return QLA_FUNCTION_FAILED;
700462306a36Sopenharmony_ci
700562306a36Sopenharmony_ci	ql_dbg(ql_dbg_mbx, vha, 0x7070, "Entered %s (options=%x).\n",
700662306a36Sopenharmony_ci	    __func__, options);
700762306a36Sopenharmony_ci
700862306a36Sopenharmony_ci	mcp->mb[0] = MBC_SET_GET_FC_LED_CONFIG;
700962306a36Sopenharmony_ci	mcp->mb[1] = options;
701062306a36Sopenharmony_ci	mcp->out_mb = MBX_1|MBX_0;
701162306a36Sopenharmony_ci	mcp->in_mb = MBX_1|MBX_0;
701262306a36Sopenharmony_ci	if (options & BIT_0) {
701362306a36Sopenharmony_ci		if (options & BIT_1) {
701462306a36Sopenharmony_ci			mcp->mb[2] = led[2];
701562306a36Sopenharmony_ci			mcp->out_mb |= MBX_2;
701662306a36Sopenharmony_ci		}
701762306a36Sopenharmony_ci		if (options & BIT_2) {
701862306a36Sopenharmony_ci			mcp->mb[3] = led[0];
701962306a36Sopenharmony_ci			mcp->out_mb |= MBX_3;
702062306a36Sopenharmony_ci		}
702162306a36Sopenharmony_ci		if (options & BIT_3) {
702262306a36Sopenharmony_ci			mcp->mb[4] = led[1];
702362306a36Sopenharmony_ci			mcp->out_mb |= MBX_4;
702462306a36Sopenharmony_ci		}
702562306a36Sopenharmony_ci	} else {
702662306a36Sopenharmony_ci		mcp->in_mb |= MBX_4|MBX_3|MBX_2;
702762306a36Sopenharmony_ci	}
702862306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
702962306a36Sopenharmony_ci	mcp->flags = 0;
703062306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
703162306a36Sopenharmony_ci	if (rval) {
703262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x7071, "Failed %s %x (mb=%x,%x)\n",
703362306a36Sopenharmony_ci		    __func__, rval, mcp->mb[0], mcp->mb[1]);
703462306a36Sopenharmony_ci		return rval;
703562306a36Sopenharmony_ci	}
703662306a36Sopenharmony_ci
703762306a36Sopenharmony_ci	if (options & BIT_0) {
703862306a36Sopenharmony_ci		ha->beacon_blink_led = 0;
703962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x7072, "Done %s\n", __func__);
704062306a36Sopenharmony_ci	} else {
704162306a36Sopenharmony_ci		led[2] = mcp->mb[2];
704262306a36Sopenharmony_ci		led[0] = mcp->mb[3];
704362306a36Sopenharmony_ci		led[1] = mcp->mb[4];
704462306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0x7073, "Done %s (led=%x,%x,%x)\n",
704562306a36Sopenharmony_ci		    __func__, led[0], led[1], led[2]);
704662306a36Sopenharmony_ci	}
704762306a36Sopenharmony_ci
704862306a36Sopenharmony_ci	return rval;
704962306a36Sopenharmony_ci}
705062306a36Sopenharmony_ci
705162306a36Sopenharmony_ci/**
705262306a36Sopenharmony_ci * qla_no_op_mb(): This MB is used to check if FW is still alive and
705362306a36Sopenharmony_ci * able to generate an interrupt. Otherwise, a timeout will trigger
705462306a36Sopenharmony_ci * FW dump + reset
705562306a36Sopenharmony_ci * @vha: host adapter pointer
705662306a36Sopenharmony_ci * Return: None
705762306a36Sopenharmony_ci */
705862306a36Sopenharmony_civoid qla_no_op_mb(struct scsi_qla_host *vha)
705962306a36Sopenharmony_ci{
706062306a36Sopenharmony_ci	mbx_cmd_t mc;
706162306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
706262306a36Sopenharmony_ci	int rval;
706362306a36Sopenharmony_ci
706462306a36Sopenharmony_ci	memset(&mc, 0, sizeof(mc));
706562306a36Sopenharmony_ci	mcp->mb[0] = 0; // noop cmd= 0
706662306a36Sopenharmony_ci	mcp->out_mb = MBX_0;
706762306a36Sopenharmony_ci	mcp->in_mb = MBX_0;
706862306a36Sopenharmony_ci	mcp->tov = 5;
706962306a36Sopenharmony_ci	mcp->flags = 0;
707062306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
707162306a36Sopenharmony_ci
707262306a36Sopenharmony_ci	if (rval) {
707362306a36Sopenharmony_ci		ql_dbg(ql_dbg_async, vha, 0x7071,
707462306a36Sopenharmony_ci			"Failed %s %x\n", __func__, rval);
707562306a36Sopenharmony_ci	}
707662306a36Sopenharmony_ci}
707762306a36Sopenharmony_ci
707862306a36Sopenharmony_ciint qla_mailbox_passthru(scsi_qla_host_t *vha,
707962306a36Sopenharmony_ci			 uint16_t *mbx_in, uint16_t *mbx_out)
708062306a36Sopenharmony_ci{
708162306a36Sopenharmony_ci	mbx_cmd_t mc;
708262306a36Sopenharmony_ci	mbx_cmd_t *mcp = &mc;
708362306a36Sopenharmony_ci	int rval = -EINVAL;
708462306a36Sopenharmony_ci
708562306a36Sopenharmony_ci	memset(&mc, 0, sizeof(mc));
708662306a36Sopenharmony_ci	/* Receiving all 32 register's contents */
708762306a36Sopenharmony_ci	memcpy(&mcp->mb, (char *)mbx_in, (32 * sizeof(uint16_t)));
708862306a36Sopenharmony_ci
708962306a36Sopenharmony_ci	mcp->out_mb = 0xFFFFFFFF;
709062306a36Sopenharmony_ci	mcp->in_mb = 0xFFFFFFFF;
709162306a36Sopenharmony_ci
709262306a36Sopenharmony_ci	mcp->tov = MBX_TOV_SECONDS;
709362306a36Sopenharmony_ci	mcp->flags = 0;
709462306a36Sopenharmony_ci	mcp->bufp = NULL;
709562306a36Sopenharmony_ci
709662306a36Sopenharmony_ci	rval = qla2x00_mailbox_command(vha, mcp);
709762306a36Sopenharmony_ci
709862306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
709962306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx, vha, 0xf0a2,
710062306a36Sopenharmony_ci			"Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
710162306a36Sopenharmony_ci	} else {
710262306a36Sopenharmony_ci		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0xf0a3, "Done %s.\n",
710362306a36Sopenharmony_ci		       __func__);
710462306a36Sopenharmony_ci		/* passing all 32 register's contents */
710562306a36Sopenharmony_ci		memcpy(mbx_out, &mcp->mb, 32 * sizeof(uint16_t));
710662306a36Sopenharmony_ci	}
710762306a36Sopenharmony_ci
710862306a36Sopenharmony_ci	return rval;
710962306a36Sopenharmony_ci}
7110