162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * QLogic iSCSI HBA Driver
462306a36Sopenharmony_ci * Copyright (c)  2003-2013 QLogic Corporation
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/ctype.h>
862306a36Sopenharmony_ci#include "ql4_def.h"
962306a36Sopenharmony_ci#include "ql4_glbl.h"
1062306a36Sopenharmony_ci#include "ql4_dbg.h"
1162306a36Sopenharmony_ci#include "ql4_inline.h"
1262306a36Sopenharmony_ci#include "ql4_version.h"
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_civoid qla4xxx_queue_mbox_cmd(struct scsi_qla_host *ha, uint32_t *mbx_cmd,
1562306a36Sopenharmony_ci			    int in_count)
1662306a36Sopenharmony_ci{
1762306a36Sopenharmony_ci	int i;
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci	/* Load all mailbox registers, except mailbox 0. */
2062306a36Sopenharmony_ci	for (i = 1; i < in_count; i++)
2162306a36Sopenharmony_ci		writel(mbx_cmd[i], &ha->reg->mailbox[i]);
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci	/* Wakeup firmware  */
2462306a36Sopenharmony_ci	writel(mbx_cmd[0], &ha->reg->mailbox[0]);
2562306a36Sopenharmony_ci	readl(&ha->reg->mailbox[0]);
2662306a36Sopenharmony_ci	writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status);
2762306a36Sopenharmony_ci	readl(&ha->reg->ctrl_status);
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_civoid qla4xxx_process_mbox_intr(struct scsi_qla_host *ha, int out_count)
3162306a36Sopenharmony_ci{
3262306a36Sopenharmony_ci	int intr_status;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	intr_status = readl(&ha->reg->ctrl_status);
3562306a36Sopenharmony_ci	if (intr_status & INTR_PENDING) {
3662306a36Sopenharmony_ci		/*
3762306a36Sopenharmony_ci		 * Service the interrupt.
3862306a36Sopenharmony_ci		 * The ISR will save the mailbox status registers
3962306a36Sopenharmony_ci		 * to a temporary storage location in the adapter structure.
4062306a36Sopenharmony_ci		 */
4162306a36Sopenharmony_ci		ha->mbox_status_count = out_count;
4262306a36Sopenharmony_ci		ha->isp_ops->interrupt_service_routine(ha, intr_status);
4362306a36Sopenharmony_ci	}
4462306a36Sopenharmony_ci}
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci/**
4762306a36Sopenharmony_ci * qla4xxx_is_intr_poll_mode - Are we allowed to poll for interrupts?
4862306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
4962306a36Sopenharmony_ci * returns: 1=polling mode, 0=non-polling mode
5062306a36Sopenharmony_ci **/
5162306a36Sopenharmony_cistatic int qla4xxx_is_intr_poll_mode(struct scsi_qla_host *ha)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	int rval = 1;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	if (is_qla8032(ha) || is_qla8042(ha)) {
5662306a36Sopenharmony_ci		if (test_bit(AF_IRQ_ATTACHED, &ha->flags) &&
5762306a36Sopenharmony_ci		    test_bit(AF_83XX_MBOX_INTR_ON, &ha->flags))
5862306a36Sopenharmony_ci			rval = 0;
5962306a36Sopenharmony_ci	} else {
6062306a36Sopenharmony_ci		if (test_bit(AF_IRQ_ATTACHED, &ha->flags) &&
6162306a36Sopenharmony_ci		    test_bit(AF_INTERRUPTS_ON, &ha->flags) &&
6262306a36Sopenharmony_ci		    test_bit(AF_ONLINE, &ha->flags) &&
6362306a36Sopenharmony_ci		    !test_bit(AF_HA_REMOVAL, &ha->flags))
6462306a36Sopenharmony_ci			rval = 0;
6562306a36Sopenharmony_ci	}
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	return rval;
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci/**
7162306a36Sopenharmony_ci * qla4xxx_mailbox_command - issues mailbox commands
7262306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
7362306a36Sopenharmony_ci * @inCount: number of mailbox registers to load.
7462306a36Sopenharmony_ci * @outCount: number of mailbox registers to return.
7562306a36Sopenharmony_ci * @mbx_cmd: data pointer for mailbox in registers.
7662306a36Sopenharmony_ci * @mbx_sts: data pointer for mailbox out registers.
7762306a36Sopenharmony_ci *
7862306a36Sopenharmony_ci * This routine issue mailbox commands and waits for completion.
7962306a36Sopenharmony_ci * If outCount is 0, this routine completes successfully WITHOUT waiting
8062306a36Sopenharmony_ci * for the mailbox command to complete.
8162306a36Sopenharmony_ci **/
8262306a36Sopenharmony_ciint qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
8362306a36Sopenharmony_ci			    uint8_t outCount, uint32_t *mbx_cmd,
8462306a36Sopenharmony_ci			    uint32_t *mbx_sts)
8562306a36Sopenharmony_ci{
8662306a36Sopenharmony_ci	int status = QLA_ERROR;
8762306a36Sopenharmony_ci	uint8_t i;
8862306a36Sopenharmony_ci	u_long wait_count;
8962306a36Sopenharmony_ci	unsigned long flags = 0;
9062306a36Sopenharmony_ci	uint32_t dev_state;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	/* Make sure that pointers are valid */
9362306a36Sopenharmony_ci	if (!mbx_cmd || !mbx_sts) {
9462306a36Sopenharmony_ci		DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts "
9562306a36Sopenharmony_ci			      "pointer\n", ha->host_no, __func__));
9662306a36Sopenharmony_ci		return status;
9762306a36Sopenharmony_ci	}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	if (is_qla40XX(ha)) {
10062306a36Sopenharmony_ci		if (test_bit(AF_HA_REMOVAL, &ha->flags)) {
10162306a36Sopenharmony_ci			DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: "
10262306a36Sopenharmony_ci					  "prematurely completing mbx cmd as "
10362306a36Sopenharmony_ci					  "adapter removal detected\n",
10462306a36Sopenharmony_ci					  ha->host_no, __func__));
10562306a36Sopenharmony_ci			return status;
10662306a36Sopenharmony_ci		}
10762306a36Sopenharmony_ci	}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	if ((is_aer_supported(ha)) &&
11062306a36Sopenharmony_ci	    (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) {
11162306a36Sopenharmony_ci		DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, "
11262306a36Sopenharmony_ci		    "timeout MBX Exiting.\n", ha->host_no, __func__));
11362306a36Sopenharmony_ci		return status;
11462306a36Sopenharmony_ci	}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	/* Mailbox code active */
11762306a36Sopenharmony_ci	wait_count = MBOX_TOV * 100;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	while (wait_count--) {
12062306a36Sopenharmony_ci		mutex_lock(&ha->mbox_sem);
12162306a36Sopenharmony_ci		if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) {
12262306a36Sopenharmony_ci			set_bit(AF_MBOX_COMMAND, &ha->flags);
12362306a36Sopenharmony_ci			mutex_unlock(&ha->mbox_sem);
12462306a36Sopenharmony_ci			break;
12562306a36Sopenharmony_ci		}
12662306a36Sopenharmony_ci		mutex_unlock(&ha->mbox_sem);
12762306a36Sopenharmony_ci		if (!wait_count) {
12862306a36Sopenharmony_ci			DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n",
12962306a36Sopenharmony_ci				ha->host_no, __func__));
13062306a36Sopenharmony_ci			return status;
13162306a36Sopenharmony_ci		}
13262306a36Sopenharmony_ci		msleep(10);
13362306a36Sopenharmony_ci	}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	if (is_qla80XX(ha)) {
13662306a36Sopenharmony_ci		if (test_bit(AF_FW_RECOVERY, &ha->flags)) {
13762306a36Sopenharmony_ci			DEBUG2(ql4_printk(KERN_WARNING, ha,
13862306a36Sopenharmony_ci					  "scsi%ld: %s: prematurely completing mbx cmd as firmware recovery detected\n",
13962306a36Sopenharmony_ci					  ha->host_no, __func__));
14062306a36Sopenharmony_ci			goto mbox_exit;
14162306a36Sopenharmony_ci		}
14262306a36Sopenharmony_ci		/* Do not send any mbx cmd if h/w is in failed state*/
14362306a36Sopenharmony_ci		ha->isp_ops->idc_lock(ha);
14462306a36Sopenharmony_ci		dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE);
14562306a36Sopenharmony_ci		ha->isp_ops->idc_unlock(ha);
14662306a36Sopenharmony_ci		if (dev_state == QLA8XXX_DEV_FAILED) {
14762306a36Sopenharmony_ci			ql4_printk(KERN_WARNING, ha,
14862306a36Sopenharmony_ci				   "scsi%ld: %s: H/W is in failed state, do not send any mailbox commands\n",
14962306a36Sopenharmony_ci				   ha->host_no, __func__);
15062306a36Sopenharmony_ci			goto mbox_exit;
15162306a36Sopenharmony_ci		}
15262306a36Sopenharmony_ci	}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	spin_lock_irqsave(&ha->hardware_lock, flags);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	ha->mbox_status_count = outCount;
15762306a36Sopenharmony_ci	for (i = 0; i < outCount; i++)
15862306a36Sopenharmony_ci		ha->mbox_status[i] = 0;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	/* Queue the mailbox command to the firmware */
16162306a36Sopenharmony_ci	ha->isp_ops->queue_mailbox_command(ha, mbx_cmd, inCount);
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	spin_unlock_irqrestore(&ha->hardware_lock, flags);
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	/* Wait for completion */
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	/*
16862306a36Sopenharmony_ci	 * If we don't want status, don't wait for the mailbox command to
16962306a36Sopenharmony_ci	 * complete.  For example, MBOX_CMD_RESET_FW doesn't return status,
17062306a36Sopenharmony_ci	 * you must poll the inbound Interrupt Mask for completion.
17162306a36Sopenharmony_ci	 */
17262306a36Sopenharmony_ci	if (outCount == 0) {
17362306a36Sopenharmony_ci		status = QLA_SUCCESS;
17462306a36Sopenharmony_ci		goto mbox_exit;
17562306a36Sopenharmony_ci	}
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	/*
17862306a36Sopenharmony_ci	 * Wait for completion: Poll or completion queue
17962306a36Sopenharmony_ci	 */
18062306a36Sopenharmony_ci	if (qla4xxx_is_intr_poll_mode(ha)) {
18162306a36Sopenharmony_ci		/* Poll for command to complete */
18262306a36Sopenharmony_ci		wait_count = jiffies + MBOX_TOV * HZ;
18362306a36Sopenharmony_ci		while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) {
18462306a36Sopenharmony_ci			if (time_after_eq(jiffies, wait_count))
18562306a36Sopenharmony_ci				break;
18662306a36Sopenharmony_ci			/*
18762306a36Sopenharmony_ci			 * Service the interrupt.
18862306a36Sopenharmony_ci			 * The ISR will save the mailbox status registers
18962306a36Sopenharmony_ci			 * to a temporary storage location in the adapter
19062306a36Sopenharmony_ci			 * structure.
19162306a36Sopenharmony_ci			 */
19262306a36Sopenharmony_ci			spin_lock_irqsave(&ha->hardware_lock, flags);
19362306a36Sopenharmony_ci			ha->isp_ops->process_mailbox_interrupt(ha, outCount);
19462306a36Sopenharmony_ci			spin_unlock_irqrestore(&ha->hardware_lock, flags);
19562306a36Sopenharmony_ci			msleep(10);
19662306a36Sopenharmony_ci		}
19762306a36Sopenharmony_ci	} else {
19862306a36Sopenharmony_ci		/* Do not poll for completion. Use completion queue */
19962306a36Sopenharmony_ci		set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
20062306a36Sopenharmony_ci		wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ);
20162306a36Sopenharmony_ci		clear_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
20262306a36Sopenharmony_ci	}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	/* Check for mailbox timeout. */
20562306a36Sopenharmony_ci	if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) {
20662306a36Sopenharmony_ci		if (is_qla80XX(ha) &&
20762306a36Sopenharmony_ci		    test_bit(AF_FW_RECOVERY, &ha->flags)) {
20862306a36Sopenharmony_ci			DEBUG2(ql4_printk(KERN_INFO, ha,
20962306a36Sopenharmony_ci			    "scsi%ld: %s: prematurely completing mbx cmd as "
21062306a36Sopenharmony_ci			    "firmware recovery detected\n",
21162306a36Sopenharmony_ci			    ha->host_no, __func__));
21262306a36Sopenharmony_ci			goto mbox_exit;
21362306a36Sopenharmony_ci		}
21462306a36Sopenharmony_ci		ql4_printk(KERN_WARNING, ha, "scsi%ld: Mailbox Cmd 0x%08X timed out, Scheduling Adapter Reset\n",
21562306a36Sopenharmony_ci			   ha->host_no, mbx_cmd[0]);
21662306a36Sopenharmony_ci		ha->mailbox_timeout_count++;
21762306a36Sopenharmony_ci		mbx_sts[0] = (-1);
21862306a36Sopenharmony_ci		set_bit(DPC_RESET_HA, &ha->dpc_flags);
21962306a36Sopenharmony_ci		if (is_qla8022(ha)) {
22062306a36Sopenharmony_ci			ql4_printk(KERN_INFO, ha,
22162306a36Sopenharmony_ci				   "disabling pause transmit on port 0 & 1.\n");
22262306a36Sopenharmony_ci			qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
22362306a36Sopenharmony_ci					CRB_NIU_XG_PAUSE_CTL_P0 |
22462306a36Sopenharmony_ci					CRB_NIU_XG_PAUSE_CTL_P1);
22562306a36Sopenharmony_ci		} else if (is_qla8032(ha) || is_qla8042(ha)) {
22662306a36Sopenharmony_ci			ql4_printk(KERN_INFO, ha, " %s: disabling pause transmit on port 0 & 1.\n",
22762306a36Sopenharmony_ci				   __func__);
22862306a36Sopenharmony_ci			qla4_83xx_disable_pause(ha);
22962306a36Sopenharmony_ci		}
23062306a36Sopenharmony_ci		goto mbox_exit;
23162306a36Sopenharmony_ci	}
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	/*
23462306a36Sopenharmony_ci	 * Copy the mailbox out registers to the caller's mailbox in/out
23562306a36Sopenharmony_ci	 * structure.
23662306a36Sopenharmony_ci	 */
23762306a36Sopenharmony_ci	spin_lock_irqsave(&ha->hardware_lock, flags);
23862306a36Sopenharmony_ci	for (i = 0; i < outCount; i++)
23962306a36Sopenharmony_ci		mbx_sts[i] = ha->mbox_status[i];
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	/* Set return status and error flags (if applicable). */
24262306a36Sopenharmony_ci	switch (ha->mbox_status[0]) {
24362306a36Sopenharmony_ci	case MBOX_STS_COMMAND_COMPLETE:
24462306a36Sopenharmony_ci		status = QLA_SUCCESS;
24562306a36Sopenharmony_ci		break;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	case MBOX_STS_INTERMEDIATE_COMPLETION:
24862306a36Sopenharmony_ci		status = QLA_SUCCESS;
24962306a36Sopenharmony_ci		break;
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	case MBOX_STS_BUSY:
25262306a36Sopenharmony_ci		ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Cmd = %08X, ISP BUSY\n",
25362306a36Sopenharmony_ci			   ha->host_no, __func__, mbx_cmd[0]);
25462306a36Sopenharmony_ci		ha->mailbox_timeout_count++;
25562306a36Sopenharmony_ci		break;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	default:
25862306a36Sopenharmony_ci		ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: FAILED, MBOX CMD = %08X, MBOX STS = %08X %08X %08X %08X %08X %08X %08X %08X\n",
25962306a36Sopenharmony_ci			   ha->host_no, __func__, mbx_cmd[0], mbx_sts[0],
26062306a36Sopenharmony_ci			   mbx_sts[1], mbx_sts[2], mbx_sts[3], mbx_sts[4],
26162306a36Sopenharmony_ci			   mbx_sts[5], mbx_sts[6], mbx_sts[7]);
26262306a36Sopenharmony_ci		break;
26362306a36Sopenharmony_ci	}
26462306a36Sopenharmony_ci	spin_unlock_irqrestore(&ha->hardware_lock, flags);
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_cimbox_exit:
26762306a36Sopenharmony_ci	mutex_lock(&ha->mbox_sem);
26862306a36Sopenharmony_ci	clear_bit(AF_MBOX_COMMAND, &ha->flags);
26962306a36Sopenharmony_ci	mutex_unlock(&ha->mbox_sem);
27062306a36Sopenharmony_ci	clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	return status;
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci/**
27662306a36Sopenharmony_ci * qla4xxx_get_minidump_template - Get the firmware template
27762306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
27862306a36Sopenharmony_ci * @phys_addr: dma address for template
27962306a36Sopenharmony_ci *
28062306a36Sopenharmony_ci * Obtain the minidump template from firmware during initialization
28162306a36Sopenharmony_ci * as it may not be available when minidump is desired.
28262306a36Sopenharmony_ci **/
28362306a36Sopenharmony_ciint qla4xxx_get_minidump_template(struct scsi_qla_host *ha,
28462306a36Sopenharmony_ci				  dma_addr_t phys_addr)
28562306a36Sopenharmony_ci{
28662306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
28762306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
28862306a36Sopenharmony_ci	int status;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
29162306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_MINIDUMP;
29462306a36Sopenharmony_ci	mbox_cmd[1] = MINIDUMP_GET_TMPLT_SUBCOMMAND;
29562306a36Sopenharmony_ci	mbox_cmd[2] = LSDW(phys_addr);
29662306a36Sopenharmony_ci	mbox_cmd[3] = MSDW(phys_addr);
29762306a36Sopenharmony_ci	mbox_cmd[4] = ha->fw_dump_tmplt_size;
29862306a36Sopenharmony_ci	mbox_cmd[5] = 0;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
30162306a36Sopenharmony_ci					 &mbox_sts[0]);
30262306a36Sopenharmony_ci	if (status != QLA_SUCCESS) {
30362306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_INFO, ha,
30462306a36Sopenharmony_ci				  "scsi%ld: %s: Cmd = %08X, mbx[0] = 0x%04x, mbx[1] = 0x%04x\n",
30562306a36Sopenharmony_ci				  ha->host_no, __func__, mbox_cmd[0],
30662306a36Sopenharmony_ci				  mbox_sts[0], mbox_sts[1]));
30762306a36Sopenharmony_ci	}
30862306a36Sopenharmony_ci	return status;
30962306a36Sopenharmony_ci}
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci/**
31262306a36Sopenharmony_ci * qla4xxx_req_template_size - Get minidump template size from firmware.
31362306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
31462306a36Sopenharmony_ci **/
31562306a36Sopenharmony_ciint qla4xxx_req_template_size(struct scsi_qla_host *ha)
31662306a36Sopenharmony_ci{
31762306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
31862306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
31962306a36Sopenharmony_ci	int status;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
32262306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_MINIDUMP;
32562306a36Sopenharmony_ci	mbox_cmd[1] = MINIDUMP_GET_SIZE_SUBCOMMAND;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0],
32862306a36Sopenharmony_ci					 &mbox_sts[0]);
32962306a36Sopenharmony_ci	if (status == QLA_SUCCESS) {
33062306a36Sopenharmony_ci		ha->fw_dump_tmplt_size = mbox_sts[1];
33162306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_INFO, ha,
33262306a36Sopenharmony_ci				  "%s: sts[0]=0x%04x, template  size=0x%04x, size_cm_02=0x%04x, size_cm_04=0x%04x, size_cm_08=0x%04x, size_cm_10=0x%04x, size_cm_FF=0x%04x, version=0x%04x\n",
33362306a36Sopenharmony_ci				  __func__, mbox_sts[0], mbox_sts[1],
33462306a36Sopenharmony_ci				  mbox_sts[2], mbox_sts[3], mbox_sts[4],
33562306a36Sopenharmony_ci				  mbox_sts[5], mbox_sts[6], mbox_sts[7]));
33662306a36Sopenharmony_ci		if (ha->fw_dump_tmplt_size == 0)
33762306a36Sopenharmony_ci			status = QLA_ERROR;
33862306a36Sopenharmony_ci	} else {
33962306a36Sopenharmony_ci		ql4_printk(KERN_WARNING, ha,
34062306a36Sopenharmony_ci			   "%s: Error sts[0]=0x%04x, mbx[1]=0x%04x\n",
34162306a36Sopenharmony_ci			   __func__, mbox_sts[0], mbox_sts[1]);
34262306a36Sopenharmony_ci		status = QLA_ERROR;
34362306a36Sopenharmony_ci	}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	return status;
34662306a36Sopenharmony_ci}
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_civoid qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha)
34962306a36Sopenharmony_ci{
35062306a36Sopenharmony_ci	set_bit(AF_FW_RECOVERY, &ha->flags);
35162306a36Sopenharmony_ci	ql4_printk(KERN_INFO, ha, "scsi%ld: %s: set FW RECOVERY!\n",
35262306a36Sopenharmony_ci	    ha->host_no, __func__);
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	if (test_bit(AF_MBOX_COMMAND, &ha->flags)) {
35562306a36Sopenharmony_ci		if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags)) {
35662306a36Sopenharmony_ci			complete(&ha->mbx_intr_comp);
35762306a36Sopenharmony_ci			ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw "
35862306a36Sopenharmony_ci			    "recovery, doing premature completion of "
35962306a36Sopenharmony_ci			    "mbx cmd\n", ha->host_no, __func__);
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci		} else {
36262306a36Sopenharmony_ci			set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
36362306a36Sopenharmony_ci			ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw "
36462306a36Sopenharmony_ci			    "recovery, doing premature completion of "
36562306a36Sopenharmony_ci			    "polling mbx cmd\n", ha->host_no, __func__);
36662306a36Sopenharmony_ci		}
36762306a36Sopenharmony_ci	}
36862306a36Sopenharmony_ci}
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_cistatic uint8_t
37162306a36Sopenharmony_ciqla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
37262306a36Sopenharmony_ci		 uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)
37362306a36Sopenharmony_ci{
37462306a36Sopenharmony_ci	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
37562306a36Sopenharmony_ci	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	if (is_qla8022(ha))
37862306a36Sopenharmony_ci		qla4_82xx_wr_32(ha, ha->nx_db_wr_ptr, 0);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE;
38162306a36Sopenharmony_ci	mbox_cmd[1] = 0;
38262306a36Sopenharmony_ci	mbox_cmd[2] = LSDW(init_fw_cb_dma);
38362306a36Sopenharmony_ci	mbox_cmd[3] = MSDW(init_fw_cb_dma);
38462306a36Sopenharmony_ci	mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	if (qla4xxx_mailbox_command(ha, 6, 6, mbox_cmd, mbox_sts) !=
38762306a36Sopenharmony_ci	    QLA_SUCCESS) {
38862306a36Sopenharmony_ci		DEBUG2(printk(KERN_WARNING "scsi%ld: %s: "
38962306a36Sopenharmony_ci			      "MBOX_CMD_INITIALIZE_FIRMWARE"
39062306a36Sopenharmony_ci			      " failed w/ status %04X\n",
39162306a36Sopenharmony_ci			      ha->host_no, __func__, mbox_sts[0]));
39262306a36Sopenharmony_ci		return QLA_ERROR;
39362306a36Sopenharmony_ci	}
39462306a36Sopenharmony_ci	return QLA_SUCCESS;
39562306a36Sopenharmony_ci}
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ciuint8_t
39862306a36Sopenharmony_ciqla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
39962306a36Sopenharmony_ci		 uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)
40062306a36Sopenharmony_ci{
40162306a36Sopenharmony_ci	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
40262306a36Sopenharmony_ci	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
40362306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
40462306a36Sopenharmony_ci	mbox_cmd[2] = LSDW(init_fw_cb_dma);
40562306a36Sopenharmony_ci	mbox_cmd[3] = MSDW(init_fw_cb_dma);
40662306a36Sopenharmony_ci	mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	if (qla4xxx_mailbox_command(ha, 5, 5, mbox_cmd, mbox_sts) !=
40962306a36Sopenharmony_ci	    QLA_SUCCESS) {
41062306a36Sopenharmony_ci		DEBUG2(printk(KERN_WARNING "scsi%ld: %s: "
41162306a36Sopenharmony_ci			      "MBOX_CMD_GET_INIT_FW_CTRL_BLOCK"
41262306a36Sopenharmony_ci			      " failed w/ status %04X\n",
41362306a36Sopenharmony_ci			      ha->host_no, __func__, mbox_sts[0]));
41462306a36Sopenharmony_ci		return QLA_ERROR;
41562306a36Sopenharmony_ci	}
41662306a36Sopenharmony_ci	return QLA_SUCCESS;
41762306a36Sopenharmony_ci}
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ciuint8_t qla4xxx_set_ipaddr_state(uint8_t fw_ipaddr_state)
42062306a36Sopenharmony_ci{
42162306a36Sopenharmony_ci	uint8_t ipaddr_state;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	switch (fw_ipaddr_state) {
42462306a36Sopenharmony_ci	case IP_ADDRSTATE_UNCONFIGURED:
42562306a36Sopenharmony_ci		ipaddr_state = ISCSI_IPDDRESS_STATE_UNCONFIGURED;
42662306a36Sopenharmony_ci		break;
42762306a36Sopenharmony_ci	case IP_ADDRSTATE_INVALID:
42862306a36Sopenharmony_ci		ipaddr_state = ISCSI_IPDDRESS_STATE_INVALID;
42962306a36Sopenharmony_ci		break;
43062306a36Sopenharmony_ci	case IP_ADDRSTATE_ACQUIRING:
43162306a36Sopenharmony_ci		ipaddr_state = ISCSI_IPDDRESS_STATE_ACQUIRING;
43262306a36Sopenharmony_ci		break;
43362306a36Sopenharmony_ci	case IP_ADDRSTATE_TENTATIVE:
43462306a36Sopenharmony_ci		ipaddr_state = ISCSI_IPDDRESS_STATE_TENTATIVE;
43562306a36Sopenharmony_ci		break;
43662306a36Sopenharmony_ci	case IP_ADDRSTATE_DEPRICATED:
43762306a36Sopenharmony_ci		ipaddr_state = ISCSI_IPDDRESS_STATE_DEPRECATED;
43862306a36Sopenharmony_ci		break;
43962306a36Sopenharmony_ci	case IP_ADDRSTATE_PREFERRED:
44062306a36Sopenharmony_ci		ipaddr_state = ISCSI_IPDDRESS_STATE_VALID;
44162306a36Sopenharmony_ci		break;
44262306a36Sopenharmony_ci	case IP_ADDRSTATE_DISABLING:
44362306a36Sopenharmony_ci		ipaddr_state = ISCSI_IPDDRESS_STATE_DISABLING;
44462306a36Sopenharmony_ci		break;
44562306a36Sopenharmony_ci	default:
44662306a36Sopenharmony_ci		ipaddr_state = ISCSI_IPDDRESS_STATE_UNCONFIGURED;
44762306a36Sopenharmony_ci	}
44862306a36Sopenharmony_ci	return ipaddr_state;
44962306a36Sopenharmony_ci}
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_cistatic void
45262306a36Sopenharmony_ciqla4xxx_update_local_ip(struct scsi_qla_host *ha,
45362306a36Sopenharmony_ci			struct addr_ctrl_blk *init_fw_cb)
45462306a36Sopenharmony_ci{
45562306a36Sopenharmony_ci	ha->ip_config.tcp_options = le16_to_cpu(init_fw_cb->ipv4_tcp_opts);
45662306a36Sopenharmony_ci	ha->ip_config.ipv4_options = le16_to_cpu(init_fw_cb->ipv4_ip_opts);
45762306a36Sopenharmony_ci	ha->ip_config.ipv4_addr_state =
45862306a36Sopenharmony_ci			qla4xxx_set_ipaddr_state(init_fw_cb->ipv4_addr_state);
45962306a36Sopenharmony_ci	ha->ip_config.eth_mtu_size =
46062306a36Sopenharmony_ci				le16_to_cpu(init_fw_cb->eth_mtu_size);
46162306a36Sopenharmony_ci	ha->ip_config.ipv4_port = le16_to_cpu(init_fw_cb->ipv4_port);
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci	if (ha->acb_version == ACB_SUPPORTED) {
46462306a36Sopenharmony_ci		ha->ip_config.ipv6_options = le16_to_cpu(init_fw_cb->ipv6_opts);
46562306a36Sopenharmony_ci		ha->ip_config.ipv6_addl_options =
46662306a36Sopenharmony_ci				le16_to_cpu(init_fw_cb->ipv6_addtl_opts);
46762306a36Sopenharmony_ci		ha->ip_config.ipv6_tcp_options =
46862306a36Sopenharmony_ci				le16_to_cpu(init_fw_cb->ipv6_tcp_opts);
46962306a36Sopenharmony_ci	}
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci	/* Save IPv4 Address Info */
47262306a36Sopenharmony_ci	memcpy(ha->ip_config.ip_address, init_fw_cb->ipv4_addr,
47362306a36Sopenharmony_ci	       min(sizeof(ha->ip_config.ip_address),
47462306a36Sopenharmony_ci		   sizeof(init_fw_cb->ipv4_addr)));
47562306a36Sopenharmony_ci	memcpy(ha->ip_config.subnet_mask, init_fw_cb->ipv4_subnet,
47662306a36Sopenharmony_ci	       min(sizeof(ha->ip_config.subnet_mask),
47762306a36Sopenharmony_ci		   sizeof(init_fw_cb->ipv4_subnet)));
47862306a36Sopenharmony_ci	memcpy(ha->ip_config.gateway, init_fw_cb->ipv4_gw_addr,
47962306a36Sopenharmony_ci	       min(sizeof(ha->ip_config.gateway),
48062306a36Sopenharmony_ci		   sizeof(init_fw_cb->ipv4_gw_addr)));
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	ha->ip_config.ipv4_vlan_tag = be16_to_cpu(init_fw_cb->ipv4_vlan_tag);
48362306a36Sopenharmony_ci	ha->ip_config.control = init_fw_cb->control;
48462306a36Sopenharmony_ci	ha->ip_config.tcp_wsf = init_fw_cb->ipv4_tcp_wsf;
48562306a36Sopenharmony_ci	ha->ip_config.ipv4_tos = init_fw_cb->ipv4_tos;
48662306a36Sopenharmony_ci	ha->ip_config.ipv4_cache_id = init_fw_cb->ipv4_cacheid;
48762306a36Sopenharmony_ci	ha->ip_config.ipv4_alt_cid_len = init_fw_cb->ipv4_dhcp_alt_cid_len;
48862306a36Sopenharmony_ci	memcpy(ha->ip_config.ipv4_alt_cid, init_fw_cb->ipv4_dhcp_alt_cid,
48962306a36Sopenharmony_ci	       min(sizeof(ha->ip_config.ipv4_alt_cid),
49062306a36Sopenharmony_ci		   sizeof(init_fw_cb->ipv4_dhcp_alt_cid)));
49162306a36Sopenharmony_ci	ha->ip_config.ipv4_vid_len = init_fw_cb->ipv4_dhcp_vid_len;
49262306a36Sopenharmony_ci	memcpy(ha->ip_config.ipv4_vid, init_fw_cb->ipv4_dhcp_vid,
49362306a36Sopenharmony_ci	       min(sizeof(ha->ip_config.ipv4_vid),
49462306a36Sopenharmony_ci		   sizeof(init_fw_cb->ipv4_dhcp_vid)));
49562306a36Sopenharmony_ci	ha->ip_config.ipv4_ttl = init_fw_cb->ipv4_ttl;
49662306a36Sopenharmony_ci	ha->ip_config.def_timeout = le16_to_cpu(init_fw_cb->def_timeout);
49762306a36Sopenharmony_ci	ha->ip_config.abort_timer = init_fw_cb->abort_timer;
49862306a36Sopenharmony_ci	ha->ip_config.iscsi_options = le16_to_cpu(init_fw_cb->iscsi_opts);
49962306a36Sopenharmony_ci	ha->ip_config.iscsi_max_pdu_size =
50062306a36Sopenharmony_ci				le16_to_cpu(init_fw_cb->iscsi_max_pdu_size);
50162306a36Sopenharmony_ci	ha->ip_config.iscsi_first_burst_len =
50262306a36Sopenharmony_ci				le16_to_cpu(init_fw_cb->iscsi_fburst_len);
50362306a36Sopenharmony_ci	ha->ip_config.iscsi_max_outstnd_r2t =
50462306a36Sopenharmony_ci				le16_to_cpu(init_fw_cb->iscsi_max_outstnd_r2t);
50562306a36Sopenharmony_ci	ha->ip_config.iscsi_max_burst_len =
50662306a36Sopenharmony_ci				le16_to_cpu(init_fw_cb->iscsi_max_burst_len);
50762306a36Sopenharmony_ci	memcpy(ha->ip_config.iscsi_name, init_fw_cb->iscsi_name,
50862306a36Sopenharmony_ci	       min(sizeof(ha->ip_config.iscsi_name),
50962306a36Sopenharmony_ci		   sizeof(init_fw_cb->iscsi_name)));
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	if (is_ipv6_enabled(ha)) {
51262306a36Sopenharmony_ci		/* Save IPv6 Address */
51362306a36Sopenharmony_ci		ha->ip_config.ipv6_link_local_state =
51462306a36Sopenharmony_ci		  qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_lnk_lcl_addr_state);
51562306a36Sopenharmony_ci		ha->ip_config.ipv6_addr0_state =
51662306a36Sopenharmony_ci			qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_addr0_state);
51762306a36Sopenharmony_ci		ha->ip_config.ipv6_addr1_state =
51862306a36Sopenharmony_ci			qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_addr1_state);
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci		switch (le16_to_cpu(init_fw_cb->ipv6_dflt_rtr_state)) {
52162306a36Sopenharmony_ci		case IPV6_RTRSTATE_UNKNOWN:
52262306a36Sopenharmony_ci			ha->ip_config.ipv6_default_router_state =
52362306a36Sopenharmony_ci						ISCSI_ROUTER_STATE_UNKNOWN;
52462306a36Sopenharmony_ci			break;
52562306a36Sopenharmony_ci		case IPV6_RTRSTATE_MANUAL:
52662306a36Sopenharmony_ci			ha->ip_config.ipv6_default_router_state =
52762306a36Sopenharmony_ci						ISCSI_ROUTER_STATE_MANUAL;
52862306a36Sopenharmony_ci			break;
52962306a36Sopenharmony_ci		case IPV6_RTRSTATE_ADVERTISED:
53062306a36Sopenharmony_ci			ha->ip_config.ipv6_default_router_state =
53162306a36Sopenharmony_ci						ISCSI_ROUTER_STATE_ADVERTISED;
53262306a36Sopenharmony_ci			break;
53362306a36Sopenharmony_ci		case IPV6_RTRSTATE_STALE:
53462306a36Sopenharmony_ci			ha->ip_config.ipv6_default_router_state =
53562306a36Sopenharmony_ci						ISCSI_ROUTER_STATE_STALE;
53662306a36Sopenharmony_ci			break;
53762306a36Sopenharmony_ci		default:
53862306a36Sopenharmony_ci			ha->ip_config.ipv6_default_router_state =
53962306a36Sopenharmony_ci						ISCSI_ROUTER_STATE_UNKNOWN;
54062306a36Sopenharmony_ci		}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci		ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[0] = 0xFE;
54362306a36Sopenharmony_ci		ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[1] = 0x80;
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci		memcpy(&ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[8],
54662306a36Sopenharmony_ci		       init_fw_cb->ipv6_if_id,
54762306a36Sopenharmony_ci		       min(sizeof(ha->ip_config.ipv6_link_local_addr)/2,
54862306a36Sopenharmony_ci			   sizeof(init_fw_cb->ipv6_if_id)));
54962306a36Sopenharmony_ci		memcpy(&ha->ip_config.ipv6_addr0, init_fw_cb->ipv6_addr0,
55062306a36Sopenharmony_ci		       min(sizeof(ha->ip_config.ipv6_addr0),
55162306a36Sopenharmony_ci			   sizeof(init_fw_cb->ipv6_addr0)));
55262306a36Sopenharmony_ci		memcpy(&ha->ip_config.ipv6_addr1, init_fw_cb->ipv6_addr1,
55362306a36Sopenharmony_ci		       min(sizeof(ha->ip_config.ipv6_addr1),
55462306a36Sopenharmony_ci			   sizeof(init_fw_cb->ipv6_addr1)));
55562306a36Sopenharmony_ci		memcpy(&ha->ip_config.ipv6_default_router_addr,
55662306a36Sopenharmony_ci		       init_fw_cb->ipv6_dflt_rtr_addr,
55762306a36Sopenharmony_ci		       min(sizeof(ha->ip_config.ipv6_default_router_addr),
55862306a36Sopenharmony_ci			   sizeof(init_fw_cb->ipv6_dflt_rtr_addr)));
55962306a36Sopenharmony_ci		ha->ip_config.ipv6_vlan_tag =
56062306a36Sopenharmony_ci				be16_to_cpu(init_fw_cb->ipv6_vlan_tag);
56162306a36Sopenharmony_ci		ha->ip_config.ipv6_port = le16_to_cpu(init_fw_cb->ipv6_port);
56262306a36Sopenharmony_ci		ha->ip_config.ipv6_cache_id = init_fw_cb->ipv6_cache_id;
56362306a36Sopenharmony_ci		ha->ip_config.ipv6_flow_lbl =
56462306a36Sopenharmony_ci				le16_to_cpu(init_fw_cb->ipv6_flow_lbl);
56562306a36Sopenharmony_ci		ha->ip_config.ipv6_traffic_class =
56662306a36Sopenharmony_ci				init_fw_cb->ipv6_traffic_class;
56762306a36Sopenharmony_ci		ha->ip_config.ipv6_hop_limit = init_fw_cb->ipv6_hop_limit;
56862306a36Sopenharmony_ci		ha->ip_config.ipv6_nd_reach_time =
56962306a36Sopenharmony_ci				le32_to_cpu(init_fw_cb->ipv6_nd_reach_time);
57062306a36Sopenharmony_ci		ha->ip_config.ipv6_nd_rexmit_timer =
57162306a36Sopenharmony_ci				le32_to_cpu(init_fw_cb->ipv6_nd_rexmit_timer);
57262306a36Sopenharmony_ci		ha->ip_config.ipv6_nd_stale_timeout =
57362306a36Sopenharmony_ci				le32_to_cpu(init_fw_cb->ipv6_nd_stale_timeout);
57462306a36Sopenharmony_ci		ha->ip_config.ipv6_dup_addr_detect_count =
57562306a36Sopenharmony_ci					init_fw_cb->ipv6_dup_addr_detect_count;
57662306a36Sopenharmony_ci		ha->ip_config.ipv6_gw_advrt_mtu =
57762306a36Sopenharmony_ci				le32_to_cpu(init_fw_cb->ipv6_gw_advrt_mtu);
57862306a36Sopenharmony_ci		ha->ip_config.ipv6_tcp_wsf = init_fw_cb->ipv6_tcp_wsf;
57962306a36Sopenharmony_ci	}
58062306a36Sopenharmony_ci}
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ciuint8_t
58362306a36Sopenharmony_ciqla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
58462306a36Sopenharmony_ci			  uint32_t *mbox_cmd,
58562306a36Sopenharmony_ci			  uint32_t *mbox_sts,
58662306a36Sopenharmony_ci			  struct addr_ctrl_blk  *init_fw_cb,
58762306a36Sopenharmony_ci			  dma_addr_t init_fw_cb_dma)
58862306a36Sopenharmony_ci{
58962306a36Sopenharmony_ci	if (qla4xxx_get_ifcb(ha, mbox_cmd, mbox_sts, init_fw_cb_dma)
59062306a36Sopenharmony_ci	    != QLA_SUCCESS) {
59162306a36Sopenharmony_ci		DEBUG2(printk(KERN_WARNING
59262306a36Sopenharmony_ci			      "scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",
59362306a36Sopenharmony_ci			      ha->host_no, __func__));
59462306a36Sopenharmony_ci		return QLA_ERROR;
59562306a36Sopenharmony_ci	}
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	DEBUG2(qla4xxx_dump_buffer(init_fw_cb, sizeof(struct addr_ctrl_blk)));
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	/* Save some info in adapter structure. */
60062306a36Sopenharmony_ci	ha->acb_version = init_fw_cb->acb_version;
60162306a36Sopenharmony_ci	ha->firmware_options = le16_to_cpu(init_fw_cb->fw_options);
60262306a36Sopenharmony_ci	ha->heartbeat_interval = init_fw_cb->hb_interval;
60362306a36Sopenharmony_ci	memcpy(ha->name_string, init_fw_cb->iscsi_name,
60462306a36Sopenharmony_ci		min(sizeof(ha->name_string),
60562306a36Sopenharmony_ci		sizeof(init_fw_cb->iscsi_name)));
60662306a36Sopenharmony_ci	ha->def_timeout = le16_to_cpu(init_fw_cb->def_timeout);
60762306a36Sopenharmony_ci	/*memcpy(ha->alias, init_fw_cb->Alias,
60862306a36Sopenharmony_ci	       min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	qla4xxx_update_local_ip(ha, init_fw_cb);
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci	return QLA_SUCCESS;
61362306a36Sopenharmony_ci}
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci/**
61662306a36Sopenharmony_ci * qla4xxx_initialize_fw_cb - initializes firmware control block.
61762306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
61862306a36Sopenharmony_ci **/
61962306a36Sopenharmony_ciint qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
62062306a36Sopenharmony_ci{
62162306a36Sopenharmony_ci	struct addr_ctrl_blk *init_fw_cb;
62262306a36Sopenharmony_ci	dma_addr_t init_fw_cb_dma;
62362306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
62462306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
62562306a36Sopenharmony_ci	int status = QLA_ERROR;
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci	init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
62862306a36Sopenharmony_ci					sizeof(struct addr_ctrl_blk),
62962306a36Sopenharmony_ci					&init_fw_cb_dma, GFP_KERNEL);
63062306a36Sopenharmony_ci	if (init_fw_cb == NULL) {
63162306a36Sopenharmony_ci		DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n",
63262306a36Sopenharmony_ci			      ha->host_no, __func__));
63362306a36Sopenharmony_ci		goto exit_init_fw_cb_no_free;
63462306a36Sopenharmony_ci	}
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	/* Get Initialize Firmware Control Block. */
63762306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
63862306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) !=
64162306a36Sopenharmony_ci	    QLA_SUCCESS) {
64262306a36Sopenharmony_ci		goto exit_init_fw_cb;
64362306a36Sopenharmony_ci	}
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	/* Fill in the request and response queue information. */
64662306a36Sopenharmony_ci	init_fw_cb->rqq_consumer_idx = cpu_to_le16(ha->request_out);
64762306a36Sopenharmony_ci	init_fw_cb->compq_producer_idx = cpu_to_le16(ha->response_in);
64862306a36Sopenharmony_ci	init_fw_cb->rqq_len = cpu_to_le16(REQUEST_QUEUE_DEPTH);
64962306a36Sopenharmony_ci	init_fw_cb->compq_len = cpu_to_le16(RESPONSE_QUEUE_DEPTH);
65062306a36Sopenharmony_ci	init_fw_cb->rqq_addr_lo = cpu_to_le32(LSDW(ha->request_dma));
65162306a36Sopenharmony_ci	init_fw_cb->rqq_addr_hi = cpu_to_le32(MSDW(ha->request_dma));
65262306a36Sopenharmony_ci	init_fw_cb->compq_addr_lo = cpu_to_le32(LSDW(ha->response_dma));
65362306a36Sopenharmony_ci	init_fw_cb->compq_addr_hi = cpu_to_le32(MSDW(ha->response_dma));
65462306a36Sopenharmony_ci	init_fw_cb->shdwreg_addr_lo = cpu_to_le32(LSDW(ha->shadow_regs_dma));
65562306a36Sopenharmony_ci	init_fw_cb->shdwreg_addr_hi = cpu_to_le32(MSDW(ha->shadow_regs_dma));
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	/* Set up required options. */
65862306a36Sopenharmony_ci	init_fw_cb->fw_options |=
65962306a36Sopenharmony_ci		cpu_to_le16(FWOPT_SESSION_MODE |
66062306a36Sopenharmony_ci			    FWOPT_INITIATOR_MODE);
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci	if (is_qla80XX(ha))
66362306a36Sopenharmony_ci		init_fw_cb->fw_options |=
66462306a36Sopenharmony_ci		    cpu_to_le16(FWOPT_ENABLE_CRBDB);
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	init_fw_cb->fw_options &= cpu_to_le16(~FWOPT_TARGET_MODE);
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci	init_fw_cb->add_fw_options = 0;
66962306a36Sopenharmony_ci	init_fw_cb->add_fw_options |=
67062306a36Sopenharmony_ci			cpu_to_le16(ADFWOPT_SERIALIZE_TASK_MGMT);
67162306a36Sopenharmony_ci	init_fw_cb->add_fw_options |=
67262306a36Sopenharmony_ci			cpu_to_le16(ADFWOPT_AUTOCONN_DISABLE);
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci	if (qla4xxx_set_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)
67562306a36Sopenharmony_ci		!= QLA_SUCCESS) {
67662306a36Sopenharmony_ci		DEBUG2(printk(KERN_WARNING
67762306a36Sopenharmony_ci			      "scsi%ld: %s: Failed to set init_fw_ctrl_blk\n",
67862306a36Sopenharmony_ci			      ha->host_no, __func__));
67962306a36Sopenharmony_ci		goto exit_init_fw_cb;
68062306a36Sopenharmony_ci	}
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	if (qla4xxx_update_local_ifcb(ha, &mbox_cmd[0], &mbox_sts[0],
68362306a36Sopenharmony_ci		init_fw_cb, init_fw_cb_dma) != QLA_SUCCESS) {
68462306a36Sopenharmony_ci		DEBUG2(printk("scsi%ld: %s: Failed to update local ifcb\n",
68562306a36Sopenharmony_ci				ha->host_no, __func__));
68662306a36Sopenharmony_ci		goto exit_init_fw_cb;
68762306a36Sopenharmony_ci	}
68862306a36Sopenharmony_ci	status = QLA_SUCCESS;
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ciexit_init_fw_cb:
69162306a36Sopenharmony_ci	dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
69262306a36Sopenharmony_ci				init_fw_cb, init_fw_cb_dma);
69362306a36Sopenharmony_ciexit_init_fw_cb_no_free:
69462306a36Sopenharmony_ci	return status;
69562306a36Sopenharmony_ci}
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci/**
69862306a36Sopenharmony_ci * qla4xxx_get_dhcp_ip_address - gets HBA ip address via DHCP
69962306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
70062306a36Sopenharmony_ci **/
70162306a36Sopenharmony_ciint qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha)
70262306a36Sopenharmony_ci{
70362306a36Sopenharmony_ci	struct addr_ctrl_blk *init_fw_cb;
70462306a36Sopenharmony_ci	dma_addr_t init_fw_cb_dma;
70562306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
70662306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci	init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
70962306a36Sopenharmony_ci					sizeof(struct addr_ctrl_blk),
71062306a36Sopenharmony_ci					&init_fw_cb_dma, GFP_KERNEL);
71162306a36Sopenharmony_ci	if (init_fw_cb == NULL) {
71262306a36Sopenharmony_ci		printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no,
71362306a36Sopenharmony_ci		       __func__);
71462306a36Sopenharmony_ci		return QLA_ERROR;
71562306a36Sopenharmony_ci	}
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci	/* Get Initialize Firmware Control Block. */
71862306a36Sopenharmony_ci	if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) !=
71962306a36Sopenharmony_ci	    QLA_SUCCESS) {
72062306a36Sopenharmony_ci		DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",
72162306a36Sopenharmony_ci			      ha->host_no, __func__));
72262306a36Sopenharmony_ci		dma_free_coherent(&ha->pdev->dev,
72362306a36Sopenharmony_ci				  sizeof(struct addr_ctrl_blk),
72462306a36Sopenharmony_ci				  init_fw_cb, init_fw_cb_dma);
72562306a36Sopenharmony_ci		return QLA_ERROR;
72662306a36Sopenharmony_ci	}
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci	/* Save IP Address. */
72962306a36Sopenharmony_ci	qla4xxx_update_local_ip(ha, init_fw_cb);
73062306a36Sopenharmony_ci	dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
73162306a36Sopenharmony_ci				init_fw_cb, init_fw_cb_dma);
73262306a36Sopenharmony_ci
73362306a36Sopenharmony_ci	return QLA_SUCCESS;
73462306a36Sopenharmony_ci}
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci/**
73762306a36Sopenharmony_ci * qla4xxx_get_firmware_state - gets firmware state of HBA
73862306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
73962306a36Sopenharmony_ci **/
74062306a36Sopenharmony_ciint qla4xxx_get_firmware_state(struct scsi_qla_host * ha)
74162306a36Sopenharmony_ci{
74262306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
74362306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci	/* Get firmware version */
74662306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
74762306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_GET_FW_STATE;
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 4, &mbox_cmd[0], &mbox_sts[0]) !=
75262306a36Sopenharmony_ci	    QLA_SUCCESS) {
75362306a36Sopenharmony_ci		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ "
75462306a36Sopenharmony_ci			      "status %04X\n", ha->host_no, __func__,
75562306a36Sopenharmony_ci			      mbox_sts[0]));
75662306a36Sopenharmony_ci		return QLA_ERROR;
75762306a36Sopenharmony_ci	}
75862306a36Sopenharmony_ci	ha->firmware_state = mbox_sts[1];
75962306a36Sopenharmony_ci	ha->board_id = mbox_sts[2];
76062306a36Sopenharmony_ci	ha->addl_fw_state = mbox_sts[3];
76162306a36Sopenharmony_ci	DEBUG2(printk("scsi%ld: %s firmware_state=0x%x\n",
76262306a36Sopenharmony_ci		      ha->host_no, __func__, ha->firmware_state);)
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_ci	return QLA_SUCCESS;
76562306a36Sopenharmony_ci}
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci/**
76862306a36Sopenharmony_ci * qla4xxx_get_firmware_status - retrieves firmware status
76962306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
77062306a36Sopenharmony_ci **/
77162306a36Sopenharmony_ciint qla4xxx_get_firmware_status(struct scsi_qla_host * ha)
77262306a36Sopenharmony_ci{
77362306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
77462306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci	/* Get firmware version */
77762306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
77862306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
77962306a36Sopenharmony_ci
78062306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS;
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) !=
78362306a36Sopenharmony_ci	    QLA_SUCCESS) {
78462306a36Sopenharmony_ci		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ "
78562306a36Sopenharmony_ci			      "status %04X\n", ha->host_no, __func__,
78662306a36Sopenharmony_ci			      mbox_sts[0]));
78762306a36Sopenharmony_ci		return QLA_ERROR;
78862306a36Sopenharmony_ci	}
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci	/* High-water mark of IOCBs */
79162306a36Sopenharmony_ci	ha->iocb_hiwat = mbox_sts[2];
79262306a36Sopenharmony_ci	DEBUG2(ql4_printk(KERN_INFO, ha,
79362306a36Sopenharmony_ci			  "%s: firmware IOCBs available = %d\n", __func__,
79462306a36Sopenharmony_ci			  ha->iocb_hiwat));
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci	if (ha->iocb_hiwat > IOCB_HIWAT_CUSHION)
79762306a36Sopenharmony_ci		ha->iocb_hiwat -= IOCB_HIWAT_CUSHION;
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci	/* Ideally, we should not enter this code, as the # of firmware
80062306a36Sopenharmony_ci	 * IOCBs is hard-coded in the firmware. We set a default
80162306a36Sopenharmony_ci	 * iocb_hiwat here just in case */
80262306a36Sopenharmony_ci	if (ha->iocb_hiwat == 0) {
80362306a36Sopenharmony_ci		ha->iocb_hiwat = REQUEST_QUEUE_DEPTH / 4;
80462306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_WARNING, ha,
80562306a36Sopenharmony_ci				  "%s: Setting IOCB's to = %d\n", __func__,
80662306a36Sopenharmony_ci				  ha->iocb_hiwat));
80762306a36Sopenharmony_ci	}
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci	return QLA_SUCCESS;
81062306a36Sopenharmony_ci}
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci/*
81362306a36Sopenharmony_ci * qla4xxx_get_fwddb_entry - retrieves firmware ddb entry
81462306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
81562306a36Sopenharmony_ci * @fw_ddb_index: Firmware's device database index
81662306a36Sopenharmony_ci * @fw_ddb_entry: Pointer to firmware's device database entry structure
81762306a36Sopenharmony_ci * @num_valid_ddb_entries: Pointer to number of valid ddb entries
81862306a36Sopenharmony_ci * @next_ddb_index: Pointer to next valid device database index
81962306a36Sopenharmony_ci * @fw_ddb_device_state: Pointer to device state
82062306a36Sopenharmony_ci **/
82162306a36Sopenharmony_ciint qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
82262306a36Sopenharmony_ci			    uint16_t fw_ddb_index,
82362306a36Sopenharmony_ci			    struct dev_db_entry *fw_ddb_entry,
82462306a36Sopenharmony_ci			    dma_addr_t fw_ddb_entry_dma,
82562306a36Sopenharmony_ci			    uint32_t *num_valid_ddb_entries,
82662306a36Sopenharmony_ci			    uint32_t *next_ddb_index,
82762306a36Sopenharmony_ci			    uint32_t *fw_ddb_device_state,
82862306a36Sopenharmony_ci			    uint32_t *conn_err_detail,
82962306a36Sopenharmony_ci			    uint16_t *tcp_source_port_num,
83062306a36Sopenharmony_ci			    uint16_t *connection_id)
83162306a36Sopenharmony_ci{
83262306a36Sopenharmony_ci	int status = QLA_ERROR;
83362306a36Sopenharmony_ci	uint16_t options;
83462306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
83562306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	/* Make sure the device index is valid */
83862306a36Sopenharmony_ci	if (fw_ddb_index >= MAX_DDB_ENTRIES) {
83962306a36Sopenharmony_ci		DEBUG2(printk("scsi%ld: %s: ddb [%d] out of range.\n",
84062306a36Sopenharmony_ci			      ha->host_no, __func__, fw_ddb_index));
84162306a36Sopenharmony_ci		goto exit_get_fwddb;
84262306a36Sopenharmony_ci	}
84362306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
84462306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
84562306a36Sopenharmony_ci	if (fw_ddb_entry)
84662306a36Sopenharmony_ci		memset(fw_ddb_entry, 0, sizeof(struct dev_db_entry));
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY;
84962306a36Sopenharmony_ci	mbox_cmd[1] = (uint32_t) fw_ddb_index;
85062306a36Sopenharmony_ci	mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
85162306a36Sopenharmony_ci	mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
85262306a36Sopenharmony_ci	mbox_cmd[4] = sizeof(struct dev_db_entry);
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 7, &mbox_cmd[0], &mbox_sts[0]) ==
85562306a36Sopenharmony_ci	    QLA_ERROR) {
85662306a36Sopenharmony_ci		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed"
85762306a36Sopenharmony_ci			      " with status 0x%04X\n", ha->host_no, __func__,
85862306a36Sopenharmony_ci			      mbox_sts[0]));
85962306a36Sopenharmony_ci		goto exit_get_fwddb;
86062306a36Sopenharmony_ci	}
86162306a36Sopenharmony_ci	if (fw_ddb_index != mbox_sts[1]) {
86262306a36Sopenharmony_ci		DEBUG2(printk("scsi%ld: %s: ddb mismatch [%d] != [%d].\n",
86362306a36Sopenharmony_ci			      ha->host_no, __func__, fw_ddb_index,
86462306a36Sopenharmony_ci			      mbox_sts[1]));
86562306a36Sopenharmony_ci		goto exit_get_fwddb;
86662306a36Sopenharmony_ci	}
86762306a36Sopenharmony_ci	if (fw_ddb_entry) {
86862306a36Sopenharmony_ci		options = le16_to_cpu(fw_ddb_entry->options);
86962306a36Sopenharmony_ci		if (options & DDB_OPT_IPV6_DEVICE) {
87062306a36Sopenharmony_ci			ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d "
87162306a36Sopenharmony_ci				"Next %d State %04x ConnErr %08x %pI6 "
87262306a36Sopenharmony_ci				":%04d \"%s\"\n", __func__, fw_ddb_index,
87362306a36Sopenharmony_ci				mbox_sts[0], mbox_sts[2], mbox_sts[3],
87462306a36Sopenharmony_ci				mbox_sts[4], mbox_sts[5],
87562306a36Sopenharmony_ci				fw_ddb_entry->ip_addr,
87662306a36Sopenharmony_ci				le16_to_cpu(fw_ddb_entry->port),
87762306a36Sopenharmony_ci				fw_ddb_entry->iscsi_name);
87862306a36Sopenharmony_ci		} else {
87962306a36Sopenharmony_ci			ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d "
88062306a36Sopenharmony_ci				"Next %d State %04x ConnErr %08x %pI4 "
88162306a36Sopenharmony_ci				":%04d \"%s\"\n", __func__, fw_ddb_index,
88262306a36Sopenharmony_ci				mbox_sts[0], mbox_sts[2], mbox_sts[3],
88362306a36Sopenharmony_ci				mbox_sts[4], mbox_sts[5],
88462306a36Sopenharmony_ci				fw_ddb_entry->ip_addr,
88562306a36Sopenharmony_ci				le16_to_cpu(fw_ddb_entry->port),
88662306a36Sopenharmony_ci				fw_ddb_entry->iscsi_name);
88762306a36Sopenharmony_ci		}
88862306a36Sopenharmony_ci	}
88962306a36Sopenharmony_ci	if (num_valid_ddb_entries)
89062306a36Sopenharmony_ci		*num_valid_ddb_entries = mbox_sts[2];
89162306a36Sopenharmony_ci	if (next_ddb_index)
89262306a36Sopenharmony_ci		*next_ddb_index = mbox_sts[3];
89362306a36Sopenharmony_ci	if (fw_ddb_device_state)
89462306a36Sopenharmony_ci		*fw_ddb_device_state = mbox_sts[4];
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci	/*
89762306a36Sopenharmony_ci	 * RA: This mailbox has been changed to pass connection error and
89862306a36Sopenharmony_ci	 * details.  Its true for ISP4010 as per Version E - Not sure when it
89962306a36Sopenharmony_ci	 * was changed.	 Get the time2wait from the fw_dd_entry field :
90062306a36Sopenharmony_ci	 * default_time2wait which we call it as minTime2Wait DEV_DB_ENTRY
90162306a36Sopenharmony_ci	 * struct.
90262306a36Sopenharmony_ci	 */
90362306a36Sopenharmony_ci	if (conn_err_detail)
90462306a36Sopenharmony_ci		*conn_err_detail = mbox_sts[5];
90562306a36Sopenharmony_ci	if (tcp_source_port_num)
90662306a36Sopenharmony_ci		*tcp_source_port_num = (uint16_t) (mbox_sts[6] >> 16);
90762306a36Sopenharmony_ci	if (connection_id)
90862306a36Sopenharmony_ci		*connection_id = (uint16_t) mbox_sts[6] & 0x00FF;
90962306a36Sopenharmony_ci	status = QLA_SUCCESS;
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ciexit_get_fwddb:
91262306a36Sopenharmony_ci	return status;
91362306a36Sopenharmony_ci}
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ciint qla4xxx_conn_open(struct scsi_qla_host *ha, uint16_t fw_ddb_index)
91662306a36Sopenharmony_ci{
91762306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
91862306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
91962306a36Sopenharmony_ci	int status;
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
92262306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_CONN_OPEN;
92562306a36Sopenharmony_ci	mbox_cmd[1] = fw_ddb_index;
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
92862306a36Sopenharmony_ci					 &mbox_sts[0]);
92962306a36Sopenharmony_ci	DEBUG2(ql4_printk(KERN_INFO, ha,
93062306a36Sopenharmony_ci			  "%s: status = %d mbx0 = 0x%x mbx1 = 0x%x\n",
93162306a36Sopenharmony_ci			  __func__, status, mbox_sts[0], mbox_sts[1]));
93262306a36Sopenharmony_ci	return status;
93362306a36Sopenharmony_ci}
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci/**
93662306a36Sopenharmony_ci * qla4xxx_set_ddb_entry - sets a ddb entry.
93762306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
93862306a36Sopenharmony_ci * @fw_ddb_index: Firmware's device database index
93962306a36Sopenharmony_ci * @fw_ddb_entry_dma: dma address of ddb entry
94062306a36Sopenharmony_ci * @mbx_sts: mailbox 0 to be returned or NULL
94162306a36Sopenharmony_ci *
94262306a36Sopenharmony_ci * This routine initializes or updates the adapter's device database
94362306a36Sopenharmony_ci * entry for the specified device.
94462306a36Sopenharmony_ci **/
94562306a36Sopenharmony_ciint qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
94662306a36Sopenharmony_ci			  dma_addr_t fw_ddb_entry_dma, uint32_t *mbx_sts)
94762306a36Sopenharmony_ci{
94862306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
94962306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
95062306a36Sopenharmony_ci	int status;
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci	/* Do not wait for completion. The firmware will send us an
95362306a36Sopenharmony_ci	 * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status.
95462306a36Sopenharmony_ci	 */
95562306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
95662306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_SET_DATABASE_ENTRY;
95962306a36Sopenharmony_ci	mbox_cmd[1] = (uint32_t) fw_ddb_index;
96062306a36Sopenharmony_ci	mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
96162306a36Sopenharmony_ci	mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
96262306a36Sopenharmony_ci	mbox_cmd[4] = sizeof(struct dev_db_entry);
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0],
96562306a36Sopenharmony_ci					 &mbox_sts[0]);
96662306a36Sopenharmony_ci	if (mbx_sts)
96762306a36Sopenharmony_ci		*mbx_sts = mbox_sts[0];
96862306a36Sopenharmony_ci	DEBUG2(printk("scsi%ld: %s: status=%d mbx0=0x%x mbx4=0x%x\n",
96962306a36Sopenharmony_ci	    ha->host_no, __func__, status, mbox_sts[0], mbox_sts[4]);)
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_ci	return status;
97262306a36Sopenharmony_ci}
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ciint qla4xxx_session_logout_ddb(struct scsi_qla_host *ha,
97562306a36Sopenharmony_ci			       struct ddb_entry *ddb_entry, int options)
97662306a36Sopenharmony_ci{
97762306a36Sopenharmony_ci	int status;
97862306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
97962306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
98262306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
98562306a36Sopenharmony_ci	mbox_cmd[1] = ddb_entry->fw_ddb_index;
98662306a36Sopenharmony_ci	mbox_cmd[3] = options;
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
98962306a36Sopenharmony_ci					 &mbox_sts[0]);
99062306a36Sopenharmony_ci	if (status != QLA_SUCCESS) {
99162306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_INFO, ha,
99262306a36Sopenharmony_ci				  "%s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
99362306a36Sopenharmony_ci				  "failed sts %04X %04X", __func__,
99462306a36Sopenharmony_ci				  mbox_sts[0], mbox_sts[1]));
99562306a36Sopenharmony_ci		if ((mbox_sts[0] == MBOX_STS_COMMAND_ERROR) &&
99662306a36Sopenharmony_ci		    (mbox_sts[1] == DDB_NOT_LOGGED_IN)) {
99762306a36Sopenharmony_ci			set_bit(DDB_CONN_CLOSE_FAILURE, &ddb_entry->flags);
99862306a36Sopenharmony_ci		}
99962306a36Sopenharmony_ci	}
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_ci	return status;
100262306a36Sopenharmony_ci}
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci/**
100562306a36Sopenharmony_ci * qla4xxx_get_crash_record - retrieves crash record.
100662306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
100762306a36Sopenharmony_ci *
100862306a36Sopenharmony_ci * This routine retrieves a crash record from the QLA4010 after an 8002h aen.
100962306a36Sopenharmony_ci **/
101062306a36Sopenharmony_civoid qla4xxx_get_crash_record(struct scsi_qla_host * ha)
101162306a36Sopenharmony_ci{
101262306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
101362306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
101462306a36Sopenharmony_ci	struct crash_record *crash_record = NULL;
101562306a36Sopenharmony_ci	dma_addr_t crash_record_dma = 0;
101662306a36Sopenharmony_ci	uint32_t crash_record_size = 0;
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
101962306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_cmd));
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_ci	/* Get size of crash record. */
102262306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
102562306a36Sopenharmony_ci	    QLA_SUCCESS) {
102662306a36Sopenharmony_ci		DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n",
102762306a36Sopenharmony_ci			      ha->host_no, __func__));
102862306a36Sopenharmony_ci		goto exit_get_crash_record;
102962306a36Sopenharmony_ci	}
103062306a36Sopenharmony_ci	crash_record_size = mbox_sts[4];
103162306a36Sopenharmony_ci	if (crash_record_size == 0) {
103262306a36Sopenharmony_ci		DEBUG2(printk("scsi%ld: %s: ERROR: Crash record size is 0!\n",
103362306a36Sopenharmony_ci			      ha->host_no, __func__));
103462306a36Sopenharmony_ci		goto exit_get_crash_record;
103562306a36Sopenharmony_ci	}
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci	/* Alloc Memory for Crash Record. */
103862306a36Sopenharmony_ci	crash_record = dma_alloc_coherent(&ha->pdev->dev, crash_record_size,
103962306a36Sopenharmony_ci					  &crash_record_dma, GFP_KERNEL);
104062306a36Sopenharmony_ci	if (crash_record == NULL)
104162306a36Sopenharmony_ci		goto exit_get_crash_record;
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci	/* Get Crash Record. */
104462306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
104562306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_cmd));
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
104862306a36Sopenharmony_ci	mbox_cmd[2] = LSDW(crash_record_dma);
104962306a36Sopenharmony_ci	mbox_cmd[3] = MSDW(crash_record_dma);
105062306a36Sopenharmony_ci	mbox_cmd[4] = crash_record_size;
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
105362306a36Sopenharmony_ci	    QLA_SUCCESS)
105462306a36Sopenharmony_ci		goto exit_get_crash_record;
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci	/* Dump Crash Record. */
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ciexit_get_crash_record:
105962306a36Sopenharmony_ci	if (crash_record)
106062306a36Sopenharmony_ci		dma_free_coherent(&ha->pdev->dev, crash_record_size,
106162306a36Sopenharmony_ci				  crash_record, crash_record_dma);
106262306a36Sopenharmony_ci}
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci/**
106562306a36Sopenharmony_ci * qla4xxx_get_conn_event_log - retrieves connection event log
106662306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
106762306a36Sopenharmony_ci **/
106862306a36Sopenharmony_civoid qla4xxx_get_conn_event_log(struct scsi_qla_host * ha)
106962306a36Sopenharmony_ci{
107062306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
107162306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
107262306a36Sopenharmony_ci	struct conn_event_log_entry *event_log = NULL;
107362306a36Sopenharmony_ci	dma_addr_t event_log_dma = 0;
107462306a36Sopenharmony_ci	uint32_t event_log_size = 0;
107562306a36Sopenharmony_ci	uint32_t num_valid_entries;
107662306a36Sopenharmony_ci	uint32_t      oldest_entry = 0;
107762306a36Sopenharmony_ci	uint32_t	max_event_log_entries;
107862306a36Sopenharmony_ci	uint8_t		i;
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
108162306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_cmd));
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	/* Get size of crash record. */
108462306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
108762306a36Sopenharmony_ci	    QLA_SUCCESS)
108862306a36Sopenharmony_ci		goto exit_get_event_log;
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_ci	event_log_size = mbox_sts[4];
109162306a36Sopenharmony_ci	if (event_log_size == 0)
109262306a36Sopenharmony_ci		goto exit_get_event_log;
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_ci	/* Alloc Memory for Crash Record. */
109562306a36Sopenharmony_ci	event_log = dma_alloc_coherent(&ha->pdev->dev, event_log_size,
109662306a36Sopenharmony_ci				       &event_log_dma, GFP_KERNEL);
109762306a36Sopenharmony_ci	if (event_log == NULL)
109862306a36Sopenharmony_ci		goto exit_get_event_log;
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	/* Get Crash Record. */
110162306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
110262306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_cmd));
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
110562306a36Sopenharmony_ci	mbox_cmd[2] = LSDW(event_log_dma);
110662306a36Sopenharmony_ci	mbox_cmd[3] = MSDW(event_log_dma);
110762306a36Sopenharmony_ci
110862306a36Sopenharmony_ci	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
110962306a36Sopenharmony_ci	    QLA_SUCCESS) {
111062306a36Sopenharmony_ci		DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event "
111162306a36Sopenharmony_ci			      "log!\n", ha->host_no, __func__));
111262306a36Sopenharmony_ci		goto exit_get_event_log;
111362306a36Sopenharmony_ci	}
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci	/* Dump Event Log. */
111662306a36Sopenharmony_ci	num_valid_entries = mbox_sts[1];
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci	max_event_log_entries = event_log_size /
111962306a36Sopenharmony_ci		sizeof(struct conn_event_log_entry);
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	if (num_valid_entries > max_event_log_entries)
112262306a36Sopenharmony_ci		oldest_entry = num_valid_entries % max_event_log_entries;
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci	DEBUG3(printk("scsi%ld: Connection Event Log Dump (%d entries):\n",
112562306a36Sopenharmony_ci		      ha->host_no, num_valid_entries));
112662306a36Sopenharmony_ci
112762306a36Sopenharmony_ci	if (ql4xextended_error_logging == 3) {
112862306a36Sopenharmony_ci		if (oldest_entry == 0) {
112962306a36Sopenharmony_ci			/* Circular Buffer has not wrapped around */
113062306a36Sopenharmony_ci			for (i=0; i < num_valid_entries; i++) {
113162306a36Sopenharmony_ci				qla4xxx_dump_buffer((uint8_t *)event_log+
113262306a36Sopenharmony_ci						    (i*sizeof(*event_log)),
113362306a36Sopenharmony_ci						    sizeof(*event_log));
113462306a36Sopenharmony_ci			}
113562306a36Sopenharmony_ci		}
113662306a36Sopenharmony_ci		else {
113762306a36Sopenharmony_ci			/* Circular Buffer has wrapped around -
113862306a36Sopenharmony_ci			 * display accordingly*/
113962306a36Sopenharmony_ci			for (i=oldest_entry; i < max_event_log_entries; i++) {
114062306a36Sopenharmony_ci				qla4xxx_dump_buffer((uint8_t *)event_log+
114162306a36Sopenharmony_ci						    (i*sizeof(*event_log)),
114262306a36Sopenharmony_ci						    sizeof(*event_log));
114362306a36Sopenharmony_ci			}
114462306a36Sopenharmony_ci			for (i=0; i < oldest_entry; i++) {
114562306a36Sopenharmony_ci				qla4xxx_dump_buffer((uint8_t *)event_log+
114662306a36Sopenharmony_ci						    (i*sizeof(*event_log)),
114762306a36Sopenharmony_ci						    sizeof(*event_log));
114862306a36Sopenharmony_ci			}
114962306a36Sopenharmony_ci		}
115062306a36Sopenharmony_ci	}
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_ciexit_get_event_log:
115362306a36Sopenharmony_ci	if (event_log)
115462306a36Sopenharmony_ci		dma_free_coherent(&ha->pdev->dev, event_log_size, event_log,
115562306a36Sopenharmony_ci				  event_log_dma);
115662306a36Sopenharmony_ci}
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci/**
115962306a36Sopenharmony_ci * qla4xxx_abort_task - issues Abort Task
116062306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
116162306a36Sopenharmony_ci * @srb: Pointer to srb entry
116262306a36Sopenharmony_ci *
116362306a36Sopenharmony_ci * This routine performs a LUN RESET on the specified target/lun.
116462306a36Sopenharmony_ci * The caller must ensure that the ddb_entry and lun_entry pointers
116562306a36Sopenharmony_ci * are valid before calling this routine.
116662306a36Sopenharmony_ci **/
116762306a36Sopenharmony_ciint qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb)
116862306a36Sopenharmony_ci{
116962306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
117062306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
117162306a36Sopenharmony_ci	struct scsi_cmnd *cmd = srb->cmd;
117262306a36Sopenharmony_ci	int status = QLA_SUCCESS;
117362306a36Sopenharmony_ci	unsigned long flags = 0;
117462306a36Sopenharmony_ci	uint32_t index;
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_ci	/*
117762306a36Sopenharmony_ci	 * Send abort task command to ISP, so that the ISP will return
117862306a36Sopenharmony_ci	 * request with ABORT status
117962306a36Sopenharmony_ci	 */
118062306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
118162306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ci	spin_lock_irqsave(&ha->hardware_lock, flags);
118462306a36Sopenharmony_ci	index = (unsigned long)(unsigned char *)cmd->host_scribble;
118562306a36Sopenharmony_ci	spin_unlock_irqrestore(&ha->hardware_lock, flags);
118662306a36Sopenharmony_ci
118762306a36Sopenharmony_ci	/* Firmware already posted completion on response queue */
118862306a36Sopenharmony_ci	if (index == MAX_SRBS)
118962306a36Sopenharmony_ci		return status;
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_ABORT_TASK;
119262306a36Sopenharmony_ci	mbox_cmd[1] = srb->ddb->fw_ddb_index;
119362306a36Sopenharmony_ci	mbox_cmd[2] = index;
119462306a36Sopenharmony_ci	/* Immediate Command Enable */
119562306a36Sopenharmony_ci	mbox_cmd[5] = 0x01;
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_ci	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0],
119862306a36Sopenharmony_ci	    &mbox_sts[0]);
119962306a36Sopenharmony_ci	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE) {
120062306a36Sopenharmony_ci		status = QLA_ERROR;
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci		DEBUG2(printk(KERN_WARNING "scsi%ld:%d:%llu: abort task FAILED: "
120362306a36Sopenharmony_ci		    "mbx0=%04X, mb1=%04X, mb2=%04X, mb3=%04X, mb4=%04X\n",
120462306a36Sopenharmony_ci		    ha->host_no, cmd->device->id, cmd->device->lun, mbox_sts[0],
120562306a36Sopenharmony_ci		    mbox_sts[1], mbox_sts[2], mbox_sts[3], mbox_sts[4]));
120662306a36Sopenharmony_ci	}
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci	return status;
120962306a36Sopenharmony_ci}
121062306a36Sopenharmony_ci
121162306a36Sopenharmony_ci/**
121262306a36Sopenharmony_ci * qla4xxx_reset_lun - issues LUN Reset
121362306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
121462306a36Sopenharmony_ci * @ddb_entry: Pointer to device database entry
121562306a36Sopenharmony_ci * @lun: lun number
121662306a36Sopenharmony_ci *
121762306a36Sopenharmony_ci * This routine performs a LUN RESET on the specified target/lun.
121862306a36Sopenharmony_ci * The caller must ensure that the ddb_entry and lun_entry pointers
121962306a36Sopenharmony_ci * are valid before calling this routine.
122062306a36Sopenharmony_ci **/
122162306a36Sopenharmony_ciint qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
122262306a36Sopenharmony_ci		      uint64_t lun)
122362306a36Sopenharmony_ci{
122462306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
122562306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
122662306a36Sopenharmony_ci	uint32_t scsi_lun[2];
122762306a36Sopenharmony_ci	int status = QLA_SUCCESS;
122862306a36Sopenharmony_ci
122962306a36Sopenharmony_ci	DEBUG2(printk("scsi%ld:%d:%llu: lun reset issued\n", ha->host_no,
123062306a36Sopenharmony_ci		      ddb_entry->fw_ddb_index, lun));
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_ci	/*
123362306a36Sopenharmony_ci	 * Send lun reset command to ISP, so that the ISP will return all
123462306a36Sopenharmony_ci	 * outstanding requests with RESET status
123562306a36Sopenharmony_ci	 */
123662306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
123762306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
123862306a36Sopenharmony_ci	int_to_scsilun(lun, (struct scsi_lun *) scsi_lun);
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_LUN_RESET;
124162306a36Sopenharmony_ci	mbox_cmd[1] = ddb_entry->fw_ddb_index;
124262306a36Sopenharmony_ci	/* FW expects LUN bytes 0-3 in Incoming Mailbox 2
124362306a36Sopenharmony_ci	 * (LUN byte 0 is LSByte, byte 3 is MSByte) */
124462306a36Sopenharmony_ci	mbox_cmd[2] = cpu_to_le32(scsi_lun[0]);
124562306a36Sopenharmony_ci	/* FW expects LUN bytes 4-7 in Incoming Mailbox 3
124662306a36Sopenharmony_ci	 * (LUN byte 4 is LSByte, byte 7 is MSByte) */
124762306a36Sopenharmony_ci	mbox_cmd[3] = cpu_to_le32(scsi_lun[1]);
124862306a36Sopenharmony_ci	mbox_cmd[5] = 0x01;	/* Immediate Command Enable */
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ci	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]);
125162306a36Sopenharmony_ci	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
125262306a36Sopenharmony_ci	    mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
125362306a36Sopenharmony_ci		status = QLA_ERROR;
125462306a36Sopenharmony_ci
125562306a36Sopenharmony_ci	return status;
125662306a36Sopenharmony_ci}
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci/**
125962306a36Sopenharmony_ci * qla4xxx_reset_target - issues target Reset
126062306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
126162306a36Sopenharmony_ci * @ddb_entry: Pointer to device database entry
126262306a36Sopenharmony_ci *
126362306a36Sopenharmony_ci * This routine performs a TARGET RESET on the specified target.
126462306a36Sopenharmony_ci * The caller must ensure that the ddb_entry pointers
126562306a36Sopenharmony_ci * are valid before calling this routine.
126662306a36Sopenharmony_ci **/
126762306a36Sopenharmony_ciint qla4xxx_reset_target(struct scsi_qla_host *ha,
126862306a36Sopenharmony_ci			 struct ddb_entry *ddb_entry)
126962306a36Sopenharmony_ci{
127062306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
127162306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
127262306a36Sopenharmony_ci	int status = QLA_SUCCESS;
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_ci	DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no,
127562306a36Sopenharmony_ci		      ddb_entry->fw_ddb_index));
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_ci	/*
127862306a36Sopenharmony_ci	 * Send target reset command to ISP, so that the ISP will return all
127962306a36Sopenharmony_ci	 * outstanding requests with RESET status
128062306a36Sopenharmony_ci	 */
128162306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
128262306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
128362306a36Sopenharmony_ci
128462306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_TARGET_WARM_RESET;
128562306a36Sopenharmony_ci	mbox_cmd[1] = ddb_entry->fw_ddb_index;
128662306a36Sopenharmony_ci	mbox_cmd[5] = 0x01;	/* Immediate Command Enable */
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
128962306a36Sopenharmony_ci				&mbox_sts[0]);
129062306a36Sopenharmony_ci	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
129162306a36Sopenharmony_ci	    mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
129262306a36Sopenharmony_ci		status = QLA_ERROR;
129362306a36Sopenharmony_ci
129462306a36Sopenharmony_ci	return status;
129562306a36Sopenharmony_ci}
129662306a36Sopenharmony_ci
129762306a36Sopenharmony_ciint qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
129862306a36Sopenharmony_ci		      uint32_t offset, uint32_t len)
129962306a36Sopenharmony_ci{
130062306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
130162306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
130462306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_READ_FLASH;
130762306a36Sopenharmony_ci	mbox_cmd[1] = LSDW(dma_addr);
130862306a36Sopenharmony_ci	mbox_cmd[2] = MSDW(dma_addr);
130962306a36Sopenharmony_ci	mbox_cmd[3] = offset;
131062306a36Sopenharmony_ci	mbox_cmd[4] = len;
131162306a36Sopenharmony_ci
131262306a36Sopenharmony_ci	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], &mbox_sts[0]) !=
131362306a36Sopenharmony_ci	    QLA_SUCCESS) {
131462306a36Sopenharmony_ci		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ "
131562306a36Sopenharmony_ci		    "status %04X %04X, offset %08x, len %08x\n", ha->host_no,
131662306a36Sopenharmony_ci		    __func__, mbox_sts[0], mbox_sts[1], offset, len));
131762306a36Sopenharmony_ci		return QLA_ERROR;
131862306a36Sopenharmony_ci	}
131962306a36Sopenharmony_ci	return QLA_SUCCESS;
132062306a36Sopenharmony_ci}
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci/**
132362306a36Sopenharmony_ci * qla4xxx_about_firmware - gets FW, iscsi draft and boot loader version
132462306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
132562306a36Sopenharmony_ci *
132662306a36Sopenharmony_ci * Retrieves the FW version, iSCSI draft version & bootloader version of HBA.
132762306a36Sopenharmony_ci * Mailboxes 2 & 3 may hold an address for data. Make sure that we write 0 to
132862306a36Sopenharmony_ci * those mailboxes, if unused.
132962306a36Sopenharmony_ci **/
133062306a36Sopenharmony_ciint qla4xxx_about_firmware(struct scsi_qla_host *ha)
133162306a36Sopenharmony_ci{
133262306a36Sopenharmony_ci	struct about_fw_info *about_fw = NULL;
133362306a36Sopenharmony_ci	dma_addr_t about_fw_dma;
133462306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
133562306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
133662306a36Sopenharmony_ci	int status = QLA_ERROR;
133762306a36Sopenharmony_ci
133862306a36Sopenharmony_ci	about_fw = dma_alloc_coherent(&ha->pdev->dev,
133962306a36Sopenharmony_ci				      sizeof(struct about_fw_info),
134062306a36Sopenharmony_ci				      &about_fw_dma, GFP_KERNEL);
134162306a36Sopenharmony_ci	if (!about_fw) {
134262306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Unable to alloc memory "
134362306a36Sopenharmony_ci				  "for about_fw\n", __func__));
134462306a36Sopenharmony_ci		return status;
134562306a36Sopenharmony_ci	}
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
134862306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
134962306a36Sopenharmony_ci
135062306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_ABOUT_FW;
135162306a36Sopenharmony_ci	mbox_cmd[2] = LSDW(about_fw_dma);
135262306a36Sopenharmony_ci	mbox_cmd[3] = MSDW(about_fw_dma);
135362306a36Sopenharmony_ci	mbox_cmd[4] = sizeof(struct about_fw_info);
135462306a36Sopenharmony_ci
135562306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT,
135662306a36Sopenharmony_ci					 &mbox_cmd[0], &mbox_sts[0]);
135762306a36Sopenharmony_ci	if (status != QLA_SUCCESS) {
135862306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_ABOUT_FW "
135962306a36Sopenharmony_ci				  "failed w/ status %04X\n", __func__,
136062306a36Sopenharmony_ci				  mbox_sts[0]));
136162306a36Sopenharmony_ci		goto exit_about_fw;
136262306a36Sopenharmony_ci	}
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_ci	/* Save version information. */
136562306a36Sopenharmony_ci	ha->fw_info.fw_major = le16_to_cpu(about_fw->fw_major);
136662306a36Sopenharmony_ci	ha->fw_info.fw_minor = le16_to_cpu(about_fw->fw_minor);
136762306a36Sopenharmony_ci	ha->fw_info.fw_patch = le16_to_cpu(about_fw->fw_patch);
136862306a36Sopenharmony_ci	ha->fw_info.fw_build = le16_to_cpu(about_fw->fw_build);
136962306a36Sopenharmony_ci	memcpy(ha->fw_info.fw_build_date, about_fw->fw_build_date,
137062306a36Sopenharmony_ci	       sizeof(about_fw->fw_build_date));
137162306a36Sopenharmony_ci	memcpy(ha->fw_info.fw_build_time, about_fw->fw_build_time,
137262306a36Sopenharmony_ci	       sizeof(about_fw->fw_build_time));
137362306a36Sopenharmony_ci	strcpy((char *)ha->fw_info.fw_build_user,
137462306a36Sopenharmony_ci	       skip_spaces((char *)about_fw->fw_build_user));
137562306a36Sopenharmony_ci	ha->fw_info.fw_load_source = le16_to_cpu(about_fw->fw_load_source);
137662306a36Sopenharmony_ci	ha->fw_info.iscsi_major = le16_to_cpu(about_fw->iscsi_major);
137762306a36Sopenharmony_ci	ha->fw_info.iscsi_minor = le16_to_cpu(about_fw->iscsi_minor);
137862306a36Sopenharmony_ci	ha->fw_info.bootload_major = le16_to_cpu(about_fw->bootload_major);
137962306a36Sopenharmony_ci	ha->fw_info.bootload_minor = le16_to_cpu(about_fw->bootload_minor);
138062306a36Sopenharmony_ci	ha->fw_info.bootload_patch = le16_to_cpu(about_fw->bootload_patch);
138162306a36Sopenharmony_ci	ha->fw_info.bootload_build = le16_to_cpu(about_fw->bootload_build);
138262306a36Sopenharmony_ci	strcpy((char *)ha->fw_info.extended_timestamp,
138362306a36Sopenharmony_ci	       skip_spaces((char *)about_fw->extended_timestamp));
138462306a36Sopenharmony_ci
138562306a36Sopenharmony_ci	ha->fw_uptime_secs = le32_to_cpu(mbox_sts[5]);
138662306a36Sopenharmony_ci	ha->fw_uptime_msecs = le32_to_cpu(mbox_sts[6]);
138762306a36Sopenharmony_ci	status = QLA_SUCCESS;
138862306a36Sopenharmony_ci
138962306a36Sopenharmony_ciexit_about_fw:
139062306a36Sopenharmony_ci	dma_free_coherent(&ha->pdev->dev, sizeof(struct about_fw_info),
139162306a36Sopenharmony_ci			  about_fw, about_fw_dma);
139262306a36Sopenharmony_ci	return status;
139362306a36Sopenharmony_ci}
139462306a36Sopenharmony_ci
139562306a36Sopenharmony_ciint qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options,
139662306a36Sopenharmony_ci			    dma_addr_t dma_addr)
139762306a36Sopenharmony_ci{
139862306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
139962306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
140062306a36Sopenharmony_ci
140162306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
140262306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS;
140562306a36Sopenharmony_ci	mbox_cmd[1] = options;
140662306a36Sopenharmony_ci	mbox_cmd[2] = LSDW(dma_addr);
140762306a36Sopenharmony_ci	mbox_cmd[3] = MSDW(dma_addr);
140862306a36Sopenharmony_ci
140962306a36Sopenharmony_ci	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=
141062306a36Sopenharmony_ci	    QLA_SUCCESS) {
141162306a36Sopenharmony_ci		DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
141262306a36Sopenharmony_ci		     ha->host_no, __func__, mbox_sts[0]));
141362306a36Sopenharmony_ci		return QLA_ERROR;
141462306a36Sopenharmony_ci	}
141562306a36Sopenharmony_ci	return QLA_SUCCESS;
141662306a36Sopenharmony_ci}
141762306a36Sopenharmony_ci
141862306a36Sopenharmony_ciint qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index,
141962306a36Sopenharmony_ci			  uint32_t *mbx_sts)
142062306a36Sopenharmony_ci{
142162306a36Sopenharmony_ci	int status;
142262306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
142362306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
142462306a36Sopenharmony_ci
142562306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
142662306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY;
142962306a36Sopenharmony_ci	mbox_cmd[1] = ddb_index;
143062306a36Sopenharmony_ci
143162306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
143262306a36Sopenharmony_ci					 &mbox_sts[0]);
143362306a36Sopenharmony_ci	if (status != QLA_SUCCESS) {
143462306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",
143562306a36Sopenharmony_ci				   __func__, mbox_sts[0]));
143662306a36Sopenharmony_ci	}
143762306a36Sopenharmony_ci
143862306a36Sopenharmony_ci	*mbx_sts = mbox_sts[0];
143962306a36Sopenharmony_ci	return status;
144062306a36Sopenharmony_ci}
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_ciint qla4xxx_clear_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index)
144362306a36Sopenharmony_ci{
144462306a36Sopenharmony_ci	int status;
144562306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
144662306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
144762306a36Sopenharmony_ci
144862306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
144962306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
145062306a36Sopenharmony_ci
145162306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY;
145262306a36Sopenharmony_ci	mbox_cmd[1] = ddb_index;
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, 2, 1, &mbox_cmd[0],
145562306a36Sopenharmony_ci					 &mbox_sts[0]);
145662306a36Sopenharmony_ci	if (status != QLA_SUCCESS) {
145762306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",
145862306a36Sopenharmony_ci				   __func__, mbox_sts[0]));
145962306a36Sopenharmony_ci	}
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	return status;
146262306a36Sopenharmony_ci}
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ciint qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
146562306a36Sopenharmony_ci		      uint32_t offset, uint32_t length, uint32_t options)
146662306a36Sopenharmony_ci{
146762306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
146862306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
146962306a36Sopenharmony_ci	int status = QLA_SUCCESS;
147062306a36Sopenharmony_ci
147162306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
147262306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
147362306a36Sopenharmony_ci
147462306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_WRITE_FLASH;
147562306a36Sopenharmony_ci	mbox_cmd[1] = LSDW(dma_addr);
147662306a36Sopenharmony_ci	mbox_cmd[2] = MSDW(dma_addr);
147762306a36Sopenharmony_ci	mbox_cmd[3] = offset;
147862306a36Sopenharmony_ci	mbox_cmd[4] = length;
147962306a36Sopenharmony_ci	mbox_cmd[5] = options;
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, 6, 2, &mbox_cmd[0], &mbox_sts[0]);
148262306a36Sopenharmony_ci	if (status != QLA_SUCCESS) {
148362306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_WRITE_FLASH "
148462306a36Sopenharmony_ci				  "failed w/ status %04X, mbx1 %04X\n",
148562306a36Sopenharmony_ci				  __func__, mbox_sts[0], mbox_sts[1]));
148662306a36Sopenharmony_ci	}
148762306a36Sopenharmony_ci	return status;
148862306a36Sopenharmony_ci}
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_ciint qla4xxx_bootdb_by_index(struct scsi_qla_host *ha,
149162306a36Sopenharmony_ci			    struct dev_db_entry *fw_ddb_entry,
149262306a36Sopenharmony_ci			    dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index)
149362306a36Sopenharmony_ci{
149462306a36Sopenharmony_ci	uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO;
149562306a36Sopenharmony_ci	uint32_t dev_db_end_offset;
149662306a36Sopenharmony_ci	int status = QLA_ERROR;
149762306a36Sopenharmony_ci
149862306a36Sopenharmony_ci	memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry));
149962306a36Sopenharmony_ci
150062306a36Sopenharmony_ci	dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry));
150162306a36Sopenharmony_ci	dev_db_end_offset = FLASH_OFFSET_DB_END;
150262306a36Sopenharmony_ci
150362306a36Sopenharmony_ci	if (dev_db_start_offset > dev_db_end_offset) {
150462306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_ERR, ha,
150562306a36Sopenharmony_ci				  "%s:Invalid DDB index %d", __func__,
150662306a36Sopenharmony_ci				  ddb_index));
150762306a36Sopenharmony_ci		goto exit_bootdb_failed;
150862306a36Sopenharmony_ci	}
150962306a36Sopenharmony_ci
151062306a36Sopenharmony_ci	if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset,
151162306a36Sopenharmony_ci			      sizeof(*fw_ddb_entry)) != QLA_SUCCESS) {
151262306a36Sopenharmony_ci		ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash"
151362306a36Sopenharmony_ci			   "failed\n", ha->host_no, __func__);
151462306a36Sopenharmony_ci		goto exit_bootdb_failed;
151562306a36Sopenharmony_ci	}
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci	if (fw_ddb_entry->cookie == DDB_VALID_COOKIE)
151862306a36Sopenharmony_ci		status = QLA_SUCCESS;
151962306a36Sopenharmony_ci
152062306a36Sopenharmony_ciexit_bootdb_failed:
152162306a36Sopenharmony_ci	return status;
152262306a36Sopenharmony_ci}
152362306a36Sopenharmony_ci
152462306a36Sopenharmony_ciint qla4xxx_flashdb_by_index(struct scsi_qla_host *ha,
152562306a36Sopenharmony_ci			     struct dev_db_entry *fw_ddb_entry,
152662306a36Sopenharmony_ci			     dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index)
152762306a36Sopenharmony_ci{
152862306a36Sopenharmony_ci	uint32_t dev_db_start_offset;
152962306a36Sopenharmony_ci	uint32_t dev_db_end_offset;
153062306a36Sopenharmony_ci	int status = QLA_ERROR;
153162306a36Sopenharmony_ci
153262306a36Sopenharmony_ci	memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry));
153362306a36Sopenharmony_ci
153462306a36Sopenharmony_ci	if (is_qla40XX(ha)) {
153562306a36Sopenharmony_ci		dev_db_start_offset = FLASH_OFFSET_DB_INFO;
153662306a36Sopenharmony_ci		dev_db_end_offset = FLASH_OFFSET_DB_END;
153762306a36Sopenharmony_ci	} else {
153862306a36Sopenharmony_ci		dev_db_start_offset = FLASH_RAW_ACCESS_ADDR +
153962306a36Sopenharmony_ci				      (ha->hw.flt_region_ddb << 2);
154062306a36Sopenharmony_ci		/* flt_ddb_size is DDB table size for both ports
154162306a36Sopenharmony_ci		 * so divide it by 2 to calculate the offset for second port
154262306a36Sopenharmony_ci		 */
154362306a36Sopenharmony_ci		if (ha->port_num == 1)
154462306a36Sopenharmony_ci			dev_db_start_offset += (ha->hw.flt_ddb_size / 2);
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci		dev_db_end_offset = dev_db_start_offset +
154762306a36Sopenharmony_ci				    (ha->hw.flt_ddb_size / 2);
154862306a36Sopenharmony_ci	}
154962306a36Sopenharmony_ci
155062306a36Sopenharmony_ci	dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry));
155162306a36Sopenharmony_ci
155262306a36Sopenharmony_ci	if (dev_db_start_offset > dev_db_end_offset) {
155362306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_ERR, ha,
155462306a36Sopenharmony_ci				  "%s:Invalid DDB index %d", __func__,
155562306a36Sopenharmony_ci				  ddb_index));
155662306a36Sopenharmony_ci		goto exit_fdb_failed;
155762306a36Sopenharmony_ci	}
155862306a36Sopenharmony_ci
155962306a36Sopenharmony_ci	if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset,
156062306a36Sopenharmony_ci			      sizeof(*fw_ddb_entry)) != QLA_SUCCESS) {
156162306a36Sopenharmony_ci		ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash failed\n",
156262306a36Sopenharmony_ci			   ha->host_no, __func__);
156362306a36Sopenharmony_ci		goto exit_fdb_failed;
156462306a36Sopenharmony_ci	}
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_ci	if (fw_ddb_entry->cookie == DDB_VALID_COOKIE)
156762306a36Sopenharmony_ci		status = QLA_SUCCESS;
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_ciexit_fdb_failed:
157062306a36Sopenharmony_ci	return status;
157162306a36Sopenharmony_ci}
157262306a36Sopenharmony_ci
157362306a36Sopenharmony_ciint qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,
157462306a36Sopenharmony_ci		     uint16_t idx)
157562306a36Sopenharmony_ci{
157662306a36Sopenharmony_ci	int ret = 0;
157762306a36Sopenharmony_ci	int rval = QLA_ERROR;
157862306a36Sopenharmony_ci	uint32_t offset = 0, chap_size;
157962306a36Sopenharmony_ci	struct ql4_chap_table *chap_table;
158062306a36Sopenharmony_ci	dma_addr_t chap_dma;
158162306a36Sopenharmony_ci
158262306a36Sopenharmony_ci	chap_table = dma_pool_zalloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);
158362306a36Sopenharmony_ci	if (chap_table == NULL)
158462306a36Sopenharmony_ci		return -ENOMEM;
158562306a36Sopenharmony_ci
158662306a36Sopenharmony_ci	chap_size = sizeof(struct ql4_chap_table);
158762306a36Sopenharmony_ci
158862306a36Sopenharmony_ci	if (is_qla40XX(ha))
158962306a36Sopenharmony_ci		offset = FLASH_CHAP_OFFSET | (idx * chap_size);
159062306a36Sopenharmony_ci	else {
159162306a36Sopenharmony_ci		offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);
159262306a36Sopenharmony_ci		/* flt_chap_size is CHAP table size for both ports
159362306a36Sopenharmony_ci		 * so divide it by 2 to calculate the offset for second port
159462306a36Sopenharmony_ci		 */
159562306a36Sopenharmony_ci		if (ha->port_num == 1)
159662306a36Sopenharmony_ci			offset += (ha->hw.flt_chap_size / 2);
159762306a36Sopenharmony_ci		offset += (idx * chap_size);
159862306a36Sopenharmony_ci	}
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_ci	rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size);
160162306a36Sopenharmony_ci	if (rval != QLA_SUCCESS) {
160262306a36Sopenharmony_ci		ret = -EINVAL;
160362306a36Sopenharmony_ci		goto exit_get_chap;
160462306a36Sopenharmony_ci	}
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci	DEBUG2(ql4_printk(KERN_INFO, ha, "Chap Cookie: x%x\n",
160762306a36Sopenharmony_ci		__le16_to_cpu(chap_table->cookie)));
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_ci	if (__le16_to_cpu(chap_table->cookie) != CHAP_VALID_COOKIE) {
161062306a36Sopenharmony_ci		ql4_printk(KERN_ERR, ha, "No valid chap entry found\n");
161162306a36Sopenharmony_ci		goto exit_get_chap;
161262306a36Sopenharmony_ci	}
161362306a36Sopenharmony_ci
161462306a36Sopenharmony_ci	strscpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
161562306a36Sopenharmony_ci	strscpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
161662306a36Sopenharmony_ci	chap_table->cookie = cpu_to_le16(CHAP_VALID_COOKIE);
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_ciexit_get_chap:
161962306a36Sopenharmony_ci	dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
162062306a36Sopenharmony_ci	return ret;
162162306a36Sopenharmony_ci}
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_ci/**
162462306a36Sopenharmony_ci * qla4xxx_set_chap - Make a chap entry at the given index
162562306a36Sopenharmony_ci * @ha: pointer to adapter structure
162662306a36Sopenharmony_ci * @username: CHAP username to set
162762306a36Sopenharmony_ci * @password: CHAP password to set
162862306a36Sopenharmony_ci * @idx: CHAP index at which to make the entry
162962306a36Sopenharmony_ci * @bidi: type of chap entry (chap_in or chap_out)
163062306a36Sopenharmony_ci *
163162306a36Sopenharmony_ci * Create chap entry at the given index with the information provided.
163262306a36Sopenharmony_ci *
163362306a36Sopenharmony_ci * Note: Caller should acquire the chap lock before getting here.
163462306a36Sopenharmony_ci **/
163562306a36Sopenharmony_ciint qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, char *password,
163662306a36Sopenharmony_ci		     uint16_t idx, int bidi)
163762306a36Sopenharmony_ci{
163862306a36Sopenharmony_ci	int ret = 0;
163962306a36Sopenharmony_ci	int rval = QLA_ERROR;
164062306a36Sopenharmony_ci	uint32_t offset = 0;
164162306a36Sopenharmony_ci	struct ql4_chap_table *chap_table;
164262306a36Sopenharmony_ci	uint32_t chap_size = 0;
164362306a36Sopenharmony_ci	dma_addr_t chap_dma;
164462306a36Sopenharmony_ci
164562306a36Sopenharmony_ci	chap_table = dma_pool_zalloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);
164662306a36Sopenharmony_ci	if (chap_table == NULL) {
164762306a36Sopenharmony_ci		ret =  -ENOMEM;
164862306a36Sopenharmony_ci		goto exit_set_chap;
164962306a36Sopenharmony_ci	}
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_ci	if (bidi)
165262306a36Sopenharmony_ci		chap_table->flags |= BIT_6; /* peer */
165362306a36Sopenharmony_ci	else
165462306a36Sopenharmony_ci		chap_table->flags |= BIT_7; /* local */
165562306a36Sopenharmony_ci	chap_table->secret_len = strlen(password);
165662306a36Sopenharmony_ci	strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN - 1);
165762306a36Sopenharmony_ci	strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN - 1);
165862306a36Sopenharmony_ci	chap_table->cookie = cpu_to_le16(CHAP_VALID_COOKIE);
165962306a36Sopenharmony_ci
166062306a36Sopenharmony_ci	if (is_qla40XX(ha)) {
166162306a36Sopenharmony_ci		chap_size = MAX_CHAP_ENTRIES_40XX * sizeof(*chap_table);
166262306a36Sopenharmony_ci		offset = FLASH_CHAP_OFFSET;
166362306a36Sopenharmony_ci	} else { /* Single region contains CHAP info for both ports which is
166462306a36Sopenharmony_ci		  * divided into half for each port.
166562306a36Sopenharmony_ci		  */
166662306a36Sopenharmony_ci		chap_size = ha->hw.flt_chap_size / 2;
166762306a36Sopenharmony_ci		offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);
166862306a36Sopenharmony_ci		if (ha->port_num == 1)
166962306a36Sopenharmony_ci			offset += chap_size;
167062306a36Sopenharmony_ci	}
167162306a36Sopenharmony_ci
167262306a36Sopenharmony_ci	offset += (idx * sizeof(struct ql4_chap_table));
167362306a36Sopenharmony_ci	rval = qla4xxx_set_flash(ha, chap_dma, offset,
167462306a36Sopenharmony_ci				sizeof(struct ql4_chap_table),
167562306a36Sopenharmony_ci				FLASH_OPT_RMW_COMMIT);
167662306a36Sopenharmony_ci
167762306a36Sopenharmony_ci	if (rval == QLA_SUCCESS && ha->chap_list) {
167862306a36Sopenharmony_ci		/* Update ha chap_list cache */
167962306a36Sopenharmony_ci		memcpy((struct ql4_chap_table *)ha->chap_list + idx,
168062306a36Sopenharmony_ci		       chap_table, sizeof(struct ql4_chap_table));
168162306a36Sopenharmony_ci	}
168262306a36Sopenharmony_ci	dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
168362306a36Sopenharmony_ci	if (rval != QLA_SUCCESS)
168462306a36Sopenharmony_ci		ret =  -EINVAL;
168562306a36Sopenharmony_ci
168662306a36Sopenharmony_ciexit_set_chap:
168762306a36Sopenharmony_ci	return ret;
168862306a36Sopenharmony_ci}
168962306a36Sopenharmony_ci
169062306a36Sopenharmony_ci
169162306a36Sopenharmony_ciint qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username,
169262306a36Sopenharmony_ci				  char *password, uint16_t chap_index)
169362306a36Sopenharmony_ci{
169462306a36Sopenharmony_ci	int rval = QLA_ERROR;
169562306a36Sopenharmony_ci	struct ql4_chap_table *chap_table = NULL;
169662306a36Sopenharmony_ci	int max_chap_entries;
169762306a36Sopenharmony_ci
169862306a36Sopenharmony_ci	if (!ha->chap_list) {
169962306a36Sopenharmony_ci		ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");
170062306a36Sopenharmony_ci		rval = QLA_ERROR;
170162306a36Sopenharmony_ci		goto exit_uni_chap;
170262306a36Sopenharmony_ci	}
170362306a36Sopenharmony_ci
170462306a36Sopenharmony_ci	if (!username || !password) {
170562306a36Sopenharmony_ci		ql4_printk(KERN_ERR, ha, "No memory for username & secret\n");
170662306a36Sopenharmony_ci		rval = QLA_ERROR;
170762306a36Sopenharmony_ci		goto exit_uni_chap;
170862306a36Sopenharmony_ci	}
170962306a36Sopenharmony_ci
171062306a36Sopenharmony_ci	if (is_qla80XX(ha))
171162306a36Sopenharmony_ci		max_chap_entries = (ha->hw.flt_chap_size / 2) /
171262306a36Sopenharmony_ci				   sizeof(struct ql4_chap_table);
171362306a36Sopenharmony_ci	else
171462306a36Sopenharmony_ci		max_chap_entries = MAX_CHAP_ENTRIES_40XX;
171562306a36Sopenharmony_ci
171662306a36Sopenharmony_ci	if (chap_index > max_chap_entries) {
171762306a36Sopenharmony_ci		ql4_printk(KERN_ERR, ha, "Invalid Chap index\n");
171862306a36Sopenharmony_ci		rval = QLA_ERROR;
171962306a36Sopenharmony_ci		goto exit_uni_chap;
172062306a36Sopenharmony_ci	}
172162306a36Sopenharmony_ci
172262306a36Sopenharmony_ci	mutex_lock(&ha->chap_sem);
172362306a36Sopenharmony_ci	chap_table = (struct ql4_chap_table *)ha->chap_list + chap_index;
172462306a36Sopenharmony_ci	if (chap_table->cookie != cpu_to_le16(CHAP_VALID_COOKIE)) {
172562306a36Sopenharmony_ci		rval = QLA_ERROR;
172662306a36Sopenharmony_ci		goto exit_unlock_uni_chap;
172762306a36Sopenharmony_ci	}
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci	if (!(chap_table->flags & BIT_7)) {
173062306a36Sopenharmony_ci		ql4_printk(KERN_ERR, ha, "Unidirectional entry not set\n");
173162306a36Sopenharmony_ci		rval = QLA_ERROR;
173262306a36Sopenharmony_ci		goto exit_unlock_uni_chap;
173362306a36Sopenharmony_ci	}
173462306a36Sopenharmony_ci
173562306a36Sopenharmony_ci	strscpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN);
173662306a36Sopenharmony_ci	strscpy(username, chap_table->name, MAX_CHAP_NAME_LEN);
173762306a36Sopenharmony_ci
173862306a36Sopenharmony_ci	rval = QLA_SUCCESS;
173962306a36Sopenharmony_ci
174062306a36Sopenharmony_ciexit_unlock_uni_chap:
174162306a36Sopenharmony_ci	mutex_unlock(&ha->chap_sem);
174262306a36Sopenharmony_ciexit_uni_chap:
174362306a36Sopenharmony_ci	return rval;
174462306a36Sopenharmony_ci}
174562306a36Sopenharmony_ci
174662306a36Sopenharmony_ci/**
174762306a36Sopenharmony_ci * qla4xxx_get_chap_index - Get chap index given username and secret
174862306a36Sopenharmony_ci * @ha: pointer to adapter structure
174962306a36Sopenharmony_ci * @username: CHAP username to be searched
175062306a36Sopenharmony_ci * @password: CHAP password to be searched
175162306a36Sopenharmony_ci * @bidi: Is this a BIDI CHAP
175262306a36Sopenharmony_ci * @chap_index: CHAP index to be returned
175362306a36Sopenharmony_ci *
175462306a36Sopenharmony_ci * Match the username and password in the chap_list, return the index if a
175562306a36Sopenharmony_ci * match is found. If a match is not found then add the entry in FLASH and
175662306a36Sopenharmony_ci * return the index at which entry is written in the FLASH.
175762306a36Sopenharmony_ci **/
175862306a36Sopenharmony_ciint qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username,
175962306a36Sopenharmony_ci			   char *password, int bidi, uint16_t *chap_index)
176062306a36Sopenharmony_ci{
176162306a36Sopenharmony_ci	int i, rval;
176262306a36Sopenharmony_ci	int free_index = -1;
176362306a36Sopenharmony_ci	int found_index = 0;
176462306a36Sopenharmony_ci	int max_chap_entries = 0;
176562306a36Sopenharmony_ci	struct ql4_chap_table *chap_table;
176662306a36Sopenharmony_ci
176762306a36Sopenharmony_ci	if (is_qla80XX(ha))
176862306a36Sopenharmony_ci		max_chap_entries = (ha->hw.flt_chap_size / 2) /
176962306a36Sopenharmony_ci						sizeof(struct ql4_chap_table);
177062306a36Sopenharmony_ci	else
177162306a36Sopenharmony_ci		max_chap_entries = MAX_CHAP_ENTRIES_40XX;
177262306a36Sopenharmony_ci
177362306a36Sopenharmony_ci	if (!ha->chap_list) {
177462306a36Sopenharmony_ci		ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");
177562306a36Sopenharmony_ci		return QLA_ERROR;
177662306a36Sopenharmony_ci	}
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci	if (!username || !password) {
177962306a36Sopenharmony_ci		ql4_printk(KERN_ERR, ha, "Do not have username and psw\n");
178062306a36Sopenharmony_ci		return QLA_ERROR;
178162306a36Sopenharmony_ci	}
178262306a36Sopenharmony_ci
178362306a36Sopenharmony_ci	mutex_lock(&ha->chap_sem);
178462306a36Sopenharmony_ci	for (i = 0; i < max_chap_entries; i++) {
178562306a36Sopenharmony_ci		chap_table = (struct ql4_chap_table *)ha->chap_list + i;
178662306a36Sopenharmony_ci		if (chap_table->cookie !=
178762306a36Sopenharmony_ci		    cpu_to_le16(CHAP_VALID_COOKIE)) {
178862306a36Sopenharmony_ci			if (i > MAX_RESRV_CHAP_IDX && free_index == -1)
178962306a36Sopenharmony_ci				free_index = i;
179062306a36Sopenharmony_ci			continue;
179162306a36Sopenharmony_ci		}
179262306a36Sopenharmony_ci		if (bidi) {
179362306a36Sopenharmony_ci			if (chap_table->flags & BIT_7)
179462306a36Sopenharmony_ci				continue;
179562306a36Sopenharmony_ci		} else {
179662306a36Sopenharmony_ci			if (chap_table->flags & BIT_6)
179762306a36Sopenharmony_ci				continue;
179862306a36Sopenharmony_ci		}
179962306a36Sopenharmony_ci		if (!strncmp(chap_table->secret, password,
180062306a36Sopenharmony_ci			     MAX_CHAP_SECRET_LEN) &&
180162306a36Sopenharmony_ci		    !strncmp(chap_table->name, username,
180262306a36Sopenharmony_ci			     MAX_CHAP_NAME_LEN)) {
180362306a36Sopenharmony_ci			*chap_index = i;
180462306a36Sopenharmony_ci			found_index = 1;
180562306a36Sopenharmony_ci			break;
180662306a36Sopenharmony_ci		}
180762306a36Sopenharmony_ci	}
180862306a36Sopenharmony_ci
180962306a36Sopenharmony_ci	/* If chap entry is not present and a free index is available then
181062306a36Sopenharmony_ci	 * write the entry in flash
181162306a36Sopenharmony_ci	 */
181262306a36Sopenharmony_ci	if (!found_index && free_index != -1) {
181362306a36Sopenharmony_ci		rval = qla4xxx_set_chap(ha, username, password,
181462306a36Sopenharmony_ci					free_index, bidi);
181562306a36Sopenharmony_ci		if (!rval) {
181662306a36Sopenharmony_ci			*chap_index = free_index;
181762306a36Sopenharmony_ci			found_index = 1;
181862306a36Sopenharmony_ci		}
181962306a36Sopenharmony_ci	}
182062306a36Sopenharmony_ci
182162306a36Sopenharmony_ci	mutex_unlock(&ha->chap_sem);
182262306a36Sopenharmony_ci
182362306a36Sopenharmony_ci	if (found_index)
182462306a36Sopenharmony_ci		return QLA_SUCCESS;
182562306a36Sopenharmony_ci	return QLA_ERROR;
182662306a36Sopenharmony_ci}
182762306a36Sopenharmony_ci
182862306a36Sopenharmony_ciint qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha,
182962306a36Sopenharmony_ci				   uint16_t fw_ddb_index,
183062306a36Sopenharmony_ci				   uint16_t connection_id,
183162306a36Sopenharmony_ci				   uint16_t option)
183262306a36Sopenharmony_ci{
183362306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
183462306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
183562306a36Sopenharmony_ci	int status = QLA_SUCCESS;
183662306a36Sopenharmony_ci
183762306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
183862306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
183962306a36Sopenharmony_ci
184062306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
184162306a36Sopenharmony_ci	mbox_cmd[1] = fw_ddb_index;
184262306a36Sopenharmony_ci	mbox_cmd[2] = connection_id;
184362306a36Sopenharmony_ci	mbox_cmd[3] = option;
184462306a36Sopenharmony_ci
184562306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]);
184662306a36Sopenharmony_ci	if (status != QLA_SUCCESS) {
184762306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_CONN_CLOSE "
184862306a36Sopenharmony_ci				  "option %04x failed w/ status %04X %04X\n",
184962306a36Sopenharmony_ci				  __func__, option, mbox_sts[0], mbox_sts[1]));
185062306a36Sopenharmony_ci	}
185162306a36Sopenharmony_ci	return status;
185262306a36Sopenharmony_ci}
185362306a36Sopenharmony_ci
185462306a36Sopenharmony_ci/**
185562306a36Sopenharmony_ci * qla4_84xx_extend_idc_tmo - Extend IDC Timeout.
185662306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
185762306a36Sopenharmony_ci * @ext_tmo: idc timeout value
185862306a36Sopenharmony_ci *
185962306a36Sopenharmony_ci * Requests firmware to extend the idc timeout value.
186062306a36Sopenharmony_ci **/
186162306a36Sopenharmony_cistatic int qla4_84xx_extend_idc_tmo(struct scsi_qla_host *ha, uint32_t ext_tmo)
186262306a36Sopenharmony_ci{
186362306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
186462306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
186562306a36Sopenharmony_ci	int status;
186662306a36Sopenharmony_ci
186762306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
186862306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
186962306a36Sopenharmony_ci	ext_tmo &= 0xf;
187062306a36Sopenharmony_ci
187162306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_IDC_TIME_EXTEND;
187262306a36Sopenharmony_ci	mbox_cmd[1] = ((ha->idc_info.request_desc & 0xfffff0ff) |
187362306a36Sopenharmony_ci		       (ext_tmo << 8));		/* new timeout */
187462306a36Sopenharmony_ci	mbox_cmd[2] = ha->idc_info.info1;
187562306a36Sopenharmony_ci	mbox_cmd[3] = ha->idc_info.info2;
187662306a36Sopenharmony_ci	mbox_cmd[4] = ha->idc_info.info3;
187762306a36Sopenharmony_ci
187862306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT,
187962306a36Sopenharmony_ci					 mbox_cmd, mbox_sts);
188062306a36Sopenharmony_ci	if (status != QLA_SUCCESS) {
188162306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_INFO, ha,
188262306a36Sopenharmony_ci				  "scsi%ld: %s: failed status %04X\n",
188362306a36Sopenharmony_ci				  ha->host_no, __func__, mbox_sts[0]));
188462306a36Sopenharmony_ci		return QLA_ERROR;
188562306a36Sopenharmony_ci	} else {
188662306a36Sopenharmony_ci		ql4_printk(KERN_INFO, ha, "%s: IDC timeout extended by %d secs\n",
188762306a36Sopenharmony_ci			   __func__, ext_tmo);
188862306a36Sopenharmony_ci	}
188962306a36Sopenharmony_ci
189062306a36Sopenharmony_ci	return QLA_SUCCESS;
189162306a36Sopenharmony_ci}
189262306a36Sopenharmony_ci
189362306a36Sopenharmony_ciint qla4xxx_disable_acb(struct scsi_qla_host *ha)
189462306a36Sopenharmony_ci{
189562306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
189662306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
189762306a36Sopenharmony_ci	int status = QLA_SUCCESS;
189862306a36Sopenharmony_ci
189962306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
190062306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
190162306a36Sopenharmony_ci
190262306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_DISABLE_ACB;
190362306a36Sopenharmony_ci
190462306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, 8, 5, &mbox_cmd[0], &mbox_sts[0]);
190562306a36Sopenharmony_ci	if (status != QLA_SUCCESS) {
190662306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_DISABLE_ACB "
190762306a36Sopenharmony_ci				  "failed w/ status %04X %04X %04X", __func__,
190862306a36Sopenharmony_ci				  mbox_sts[0], mbox_sts[1], mbox_sts[2]));
190962306a36Sopenharmony_ci	} else {
191062306a36Sopenharmony_ci		if (is_qla8042(ha) &&
191162306a36Sopenharmony_ci		    test_bit(DPC_POST_IDC_ACK, &ha->dpc_flags) &&
191262306a36Sopenharmony_ci		    (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE)) {
191362306a36Sopenharmony_ci			/*
191462306a36Sopenharmony_ci			 * Disable ACB mailbox command takes time to complete
191562306a36Sopenharmony_ci			 * based on the total number of targets connected.
191662306a36Sopenharmony_ci			 * For 512 targets, it took approximately 5 secs to
191762306a36Sopenharmony_ci			 * complete. Setting the timeout value to 8, with the 3
191862306a36Sopenharmony_ci			 * secs buffer.
191962306a36Sopenharmony_ci			 */
192062306a36Sopenharmony_ci			qla4_84xx_extend_idc_tmo(ha, IDC_EXTEND_TOV);
192162306a36Sopenharmony_ci			if (!wait_for_completion_timeout(&ha->disable_acb_comp,
192262306a36Sopenharmony_ci							 IDC_EXTEND_TOV * HZ)) {
192362306a36Sopenharmony_ci				ql4_printk(KERN_WARNING, ha, "%s: Disable ACB Completion not received\n",
192462306a36Sopenharmony_ci					   __func__);
192562306a36Sopenharmony_ci			}
192662306a36Sopenharmony_ci		}
192762306a36Sopenharmony_ci	}
192862306a36Sopenharmony_ci	return status;
192962306a36Sopenharmony_ci}
193062306a36Sopenharmony_ci
193162306a36Sopenharmony_ciint qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma,
193262306a36Sopenharmony_ci		    uint32_t acb_type, uint32_t len)
193362306a36Sopenharmony_ci{
193462306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
193562306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
193662306a36Sopenharmony_ci	int status = QLA_SUCCESS;
193762306a36Sopenharmony_ci
193862306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
193962306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
194062306a36Sopenharmony_ci
194162306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_GET_ACB;
194262306a36Sopenharmony_ci	mbox_cmd[1] = acb_type;
194362306a36Sopenharmony_ci	mbox_cmd[2] = LSDW(acb_dma);
194462306a36Sopenharmony_ci	mbox_cmd[3] = MSDW(acb_dma);
194562306a36Sopenharmony_ci	mbox_cmd[4] = len;
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);
194862306a36Sopenharmony_ci	if (status != QLA_SUCCESS) {
194962306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_GET_ACB "
195062306a36Sopenharmony_ci				  "failed w/ status %04X\n", __func__,
195162306a36Sopenharmony_ci				  mbox_sts[0]));
195262306a36Sopenharmony_ci	}
195362306a36Sopenharmony_ci	return status;
195462306a36Sopenharmony_ci}
195562306a36Sopenharmony_ci
195662306a36Sopenharmony_ciint qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
195762306a36Sopenharmony_ci		    uint32_t *mbox_sts, dma_addr_t acb_dma)
195862306a36Sopenharmony_ci{
195962306a36Sopenharmony_ci	int status = QLA_SUCCESS;
196062306a36Sopenharmony_ci
196162306a36Sopenharmony_ci	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
196262306a36Sopenharmony_ci	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
196362306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_SET_ACB;
196462306a36Sopenharmony_ci	mbox_cmd[1] = 0; /* Primary ACB */
196562306a36Sopenharmony_ci	mbox_cmd[2] = LSDW(acb_dma);
196662306a36Sopenharmony_ci	mbox_cmd[3] = MSDW(acb_dma);
196762306a36Sopenharmony_ci	mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
196862306a36Sopenharmony_ci
196962306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);
197062306a36Sopenharmony_ci	if (status != QLA_SUCCESS) {
197162306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_WARNING, ha,  "%s: MBOX_CMD_SET_ACB "
197262306a36Sopenharmony_ci				  "failed w/ status %04X\n", __func__,
197362306a36Sopenharmony_ci				  mbox_sts[0]));
197462306a36Sopenharmony_ci	}
197562306a36Sopenharmony_ci	return status;
197662306a36Sopenharmony_ci}
197762306a36Sopenharmony_ci
197862306a36Sopenharmony_ciint qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
197962306a36Sopenharmony_ci			       struct ddb_entry *ddb_entry,
198062306a36Sopenharmony_ci			       struct iscsi_cls_conn *cls_conn,
198162306a36Sopenharmony_ci			       uint32_t *mbx_sts)
198262306a36Sopenharmony_ci{
198362306a36Sopenharmony_ci	struct dev_db_entry *fw_ddb_entry;
198462306a36Sopenharmony_ci	struct iscsi_conn *conn;
198562306a36Sopenharmony_ci	struct iscsi_session *sess;
198662306a36Sopenharmony_ci	struct qla_conn *qla_conn;
198762306a36Sopenharmony_ci	struct sockaddr *dst_addr;
198862306a36Sopenharmony_ci	dma_addr_t fw_ddb_entry_dma;
198962306a36Sopenharmony_ci	int status = QLA_SUCCESS;
199062306a36Sopenharmony_ci	int rval = 0;
199162306a36Sopenharmony_ci	struct sockaddr_in *addr;
199262306a36Sopenharmony_ci	struct sockaddr_in6 *addr6;
199362306a36Sopenharmony_ci	char *ip;
199462306a36Sopenharmony_ci	uint16_t iscsi_opts = 0;
199562306a36Sopenharmony_ci	uint32_t options = 0;
199662306a36Sopenharmony_ci	uint16_t idx, *ptid;
199762306a36Sopenharmony_ci
199862306a36Sopenharmony_ci	fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
199962306a36Sopenharmony_ci					  &fw_ddb_entry_dma, GFP_KERNEL);
200062306a36Sopenharmony_ci	if (!fw_ddb_entry) {
200162306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_ERR, ha,
200262306a36Sopenharmony_ci				  "%s: Unable to allocate dma buffer.\n",
200362306a36Sopenharmony_ci				  __func__));
200462306a36Sopenharmony_ci		rval = -ENOMEM;
200562306a36Sopenharmony_ci		goto exit_set_param_no_free;
200662306a36Sopenharmony_ci	}
200762306a36Sopenharmony_ci
200862306a36Sopenharmony_ci	conn = cls_conn->dd_data;
200962306a36Sopenharmony_ci	qla_conn = conn->dd_data;
201062306a36Sopenharmony_ci	sess = conn->session;
201162306a36Sopenharmony_ci	dst_addr = (struct sockaddr *)&qla_conn->qla_ep->dst_addr;
201262306a36Sopenharmony_ci
201362306a36Sopenharmony_ci	if (dst_addr->sa_family == AF_INET6)
201462306a36Sopenharmony_ci		options |= IPV6_DEFAULT_DDB_ENTRY;
201562306a36Sopenharmony_ci
201662306a36Sopenharmony_ci	status = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma);
201762306a36Sopenharmony_ci	if (status == QLA_ERROR) {
201862306a36Sopenharmony_ci		rval = -EINVAL;
201962306a36Sopenharmony_ci		goto exit_set_param;
202062306a36Sopenharmony_ci	}
202162306a36Sopenharmony_ci
202262306a36Sopenharmony_ci	ptid = (uint16_t *)&fw_ddb_entry->isid[1];
202362306a36Sopenharmony_ci	*ptid = cpu_to_le16((uint16_t)ddb_entry->sess->target_id);
202462306a36Sopenharmony_ci
202562306a36Sopenharmony_ci	DEBUG2(ql4_printk(KERN_INFO, ha, "ISID [%pmR]\n", fw_ddb_entry->isid));
202662306a36Sopenharmony_ci
202762306a36Sopenharmony_ci	iscsi_opts = le16_to_cpu(fw_ddb_entry->iscsi_options);
202862306a36Sopenharmony_ci	memset(fw_ddb_entry->iscsi_alias, 0, sizeof(fw_ddb_entry->iscsi_alias));
202962306a36Sopenharmony_ci
203062306a36Sopenharmony_ci	memset(fw_ddb_entry->iscsi_name, 0, sizeof(fw_ddb_entry->iscsi_name));
203162306a36Sopenharmony_ci
203262306a36Sopenharmony_ci	if (sess->targetname != NULL) {
203362306a36Sopenharmony_ci		memcpy(fw_ddb_entry->iscsi_name, sess->targetname,
203462306a36Sopenharmony_ci		       min(strlen(sess->targetname),
203562306a36Sopenharmony_ci		       sizeof(fw_ddb_entry->iscsi_name)));
203662306a36Sopenharmony_ci	}
203762306a36Sopenharmony_ci
203862306a36Sopenharmony_ci	memset(fw_ddb_entry->ip_addr, 0, sizeof(fw_ddb_entry->ip_addr));
203962306a36Sopenharmony_ci	memset(fw_ddb_entry->tgt_addr, 0, sizeof(fw_ddb_entry->tgt_addr));
204062306a36Sopenharmony_ci
204162306a36Sopenharmony_ci	fw_ddb_entry->options =  DDB_OPT_TARGET | DDB_OPT_AUTO_SENDTGTS_DISABLE;
204262306a36Sopenharmony_ci
204362306a36Sopenharmony_ci	if (dst_addr->sa_family == AF_INET) {
204462306a36Sopenharmony_ci		addr = (struct sockaddr_in *)dst_addr;
204562306a36Sopenharmony_ci		ip = (char *)&addr->sin_addr;
204662306a36Sopenharmony_ci		memcpy(fw_ddb_entry->ip_addr, ip, IP_ADDR_LEN);
204762306a36Sopenharmony_ci		fw_ddb_entry->port = cpu_to_le16(ntohs(addr->sin_port));
204862306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_INFO, ha,
204962306a36Sopenharmony_ci				  "%s: Destination Address [%pI4]: index [%d]\n",
205062306a36Sopenharmony_ci				   __func__, fw_ddb_entry->ip_addr,
205162306a36Sopenharmony_ci				  ddb_entry->fw_ddb_index));
205262306a36Sopenharmony_ci	} else if (dst_addr->sa_family == AF_INET6) {
205362306a36Sopenharmony_ci		addr6 = (struct sockaddr_in6 *)dst_addr;
205462306a36Sopenharmony_ci		ip = (char *)&addr6->sin6_addr;
205562306a36Sopenharmony_ci		memcpy(fw_ddb_entry->ip_addr, ip, IPv6_ADDR_LEN);
205662306a36Sopenharmony_ci		fw_ddb_entry->port = cpu_to_le16(ntohs(addr6->sin6_port));
205762306a36Sopenharmony_ci		fw_ddb_entry->options |= DDB_OPT_IPV6_DEVICE;
205862306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_INFO, ha,
205962306a36Sopenharmony_ci				  "%s: Destination Address [%pI6]: index [%d]\n",
206062306a36Sopenharmony_ci				   __func__, fw_ddb_entry->ip_addr,
206162306a36Sopenharmony_ci				  ddb_entry->fw_ddb_index));
206262306a36Sopenharmony_ci	} else {
206362306a36Sopenharmony_ci		ql4_printk(KERN_ERR, ha,
206462306a36Sopenharmony_ci			   "%s: Failed to get IP Address\n",
206562306a36Sopenharmony_ci			   __func__);
206662306a36Sopenharmony_ci		rval = -EINVAL;
206762306a36Sopenharmony_ci		goto exit_set_param;
206862306a36Sopenharmony_ci	}
206962306a36Sopenharmony_ci
207062306a36Sopenharmony_ci	/* CHAP */
207162306a36Sopenharmony_ci	if (sess->username != NULL && sess->password != NULL) {
207262306a36Sopenharmony_ci		if (strlen(sess->username) && strlen(sess->password)) {
207362306a36Sopenharmony_ci			iscsi_opts |= BIT_7;
207462306a36Sopenharmony_ci
207562306a36Sopenharmony_ci			rval = qla4xxx_get_chap_index(ha, sess->username,
207662306a36Sopenharmony_ci						sess->password,
207762306a36Sopenharmony_ci						LOCAL_CHAP, &idx);
207862306a36Sopenharmony_ci			if (rval)
207962306a36Sopenharmony_ci				goto exit_set_param;
208062306a36Sopenharmony_ci
208162306a36Sopenharmony_ci			fw_ddb_entry->chap_tbl_idx = cpu_to_le16(idx);
208262306a36Sopenharmony_ci		}
208362306a36Sopenharmony_ci	}
208462306a36Sopenharmony_ci
208562306a36Sopenharmony_ci	if (sess->username_in != NULL && sess->password_in != NULL) {
208662306a36Sopenharmony_ci		/* Check if BIDI CHAP */
208762306a36Sopenharmony_ci		if (strlen(sess->username_in) && strlen(sess->password_in)) {
208862306a36Sopenharmony_ci			iscsi_opts |= BIT_4;
208962306a36Sopenharmony_ci
209062306a36Sopenharmony_ci			rval = qla4xxx_get_chap_index(ha, sess->username_in,
209162306a36Sopenharmony_ci						      sess->password_in,
209262306a36Sopenharmony_ci						      BIDI_CHAP, &idx);
209362306a36Sopenharmony_ci			if (rval)
209462306a36Sopenharmony_ci				goto exit_set_param;
209562306a36Sopenharmony_ci		}
209662306a36Sopenharmony_ci	}
209762306a36Sopenharmony_ci
209862306a36Sopenharmony_ci	if (sess->initial_r2t_en)
209962306a36Sopenharmony_ci		iscsi_opts |= BIT_10;
210062306a36Sopenharmony_ci
210162306a36Sopenharmony_ci	if (sess->imm_data_en)
210262306a36Sopenharmony_ci		iscsi_opts |= BIT_11;
210362306a36Sopenharmony_ci
210462306a36Sopenharmony_ci	fw_ddb_entry->iscsi_options = cpu_to_le16(iscsi_opts);
210562306a36Sopenharmony_ci
210662306a36Sopenharmony_ci	if (conn->max_recv_dlength)
210762306a36Sopenharmony_ci		fw_ddb_entry->iscsi_max_rcv_data_seg_len =
210862306a36Sopenharmony_ci		  cpu_to_le16((conn->max_recv_dlength / BYTE_UNITS));
210962306a36Sopenharmony_ci
211062306a36Sopenharmony_ci	if (sess->max_r2t)
211162306a36Sopenharmony_ci		fw_ddb_entry->iscsi_max_outsnd_r2t = cpu_to_le16(sess->max_r2t);
211262306a36Sopenharmony_ci
211362306a36Sopenharmony_ci	if (sess->first_burst)
211462306a36Sopenharmony_ci		fw_ddb_entry->iscsi_first_burst_len =
211562306a36Sopenharmony_ci		       cpu_to_le16((sess->first_burst / BYTE_UNITS));
211662306a36Sopenharmony_ci
211762306a36Sopenharmony_ci	if (sess->max_burst)
211862306a36Sopenharmony_ci		fw_ddb_entry->iscsi_max_burst_len =
211962306a36Sopenharmony_ci			cpu_to_le16((sess->max_burst / BYTE_UNITS));
212062306a36Sopenharmony_ci
212162306a36Sopenharmony_ci	if (sess->time2wait)
212262306a36Sopenharmony_ci		fw_ddb_entry->iscsi_def_time2wait =
212362306a36Sopenharmony_ci			cpu_to_le16(sess->time2wait);
212462306a36Sopenharmony_ci
212562306a36Sopenharmony_ci	if (sess->time2retain)
212662306a36Sopenharmony_ci		fw_ddb_entry->iscsi_def_time2retain =
212762306a36Sopenharmony_ci			cpu_to_le16(sess->time2retain);
212862306a36Sopenharmony_ci
212962306a36Sopenharmony_ci	status = qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index,
213062306a36Sopenharmony_ci				       fw_ddb_entry_dma, mbx_sts);
213162306a36Sopenharmony_ci
213262306a36Sopenharmony_ci	if (status != QLA_SUCCESS)
213362306a36Sopenharmony_ci		rval = -EINVAL;
213462306a36Sopenharmony_ciexit_set_param:
213562306a36Sopenharmony_ci	dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
213662306a36Sopenharmony_ci			  fw_ddb_entry, fw_ddb_entry_dma);
213762306a36Sopenharmony_ciexit_set_param_no_free:
213862306a36Sopenharmony_ci	return rval;
213962306a36Sopenharmony_ci}
214062306a36Sopenharmony_ci
214162306a36Sopenharmony_ciint qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index,
214262306a36Sopenharmony_ci			  uint16_t stats_size, dma_addr_t stats_dma)
214362306a36Sopenharmony_ci{
214462306a36Sopenharmony_ci	int status = QLA_SUCCESS;
214562306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
214662306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
214762306a36Sopenharmony_ci
214862306a36Sopenharmony_ci	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
214962306a36Sopenharmony_ci	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
215062306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_GET_MANAGEMENT_DATA;
215162306a36Sopenharmony_ci	mbox_cmd[1] = fw_ddb_index;
215262306a36Sopenharmony_ci	mbox_cmd[2] = LSDW(stats_dma);
215362306a36Sopenharmony_ci	mbox_cmd[3] = MSDW(stats_dma);
215462306a36Sopenharmony_ci	mbox_cmd[4] = stats_size;
215562306a36Sopenharmony_ci
215662306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, 5, 1, &mbox_cmd[0], &mbox_sts[0]);
215762306a36Sopenharmony_ci	if (status != QLA_SUCCESS) {
215862306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_WARNING, ha,
215962306a36Sopenharmony_ci				  "%s: MBOX_CMD_GET_MANAGEMENT_DATA "
216062306a36Sopenharmony_ci				  "failed w/ status %04X\n", __func__,
216162306a36Sopenharmony_ci				  mbox_sts[0]));
216262306a36Sopenharmony_ci	}
216362306a36Sopenharmony_ci	return status;
216462306a36Sopenharmony_ci}
216562306a36Sopenharmony_ci
216662306a36Sopenharmony_ciint qla4xxx_get_ip_state(struct scsi_qla_host *ha, uint32_t acb_idx,
216762306a36Sopenharmony_ci			 uint32_t ip_idx, uint32_t *sts)
216862306a36Sopenharmony_ci{
216962306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
217062306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
217162306a36Sopenharmony_ci	int status = QLA_SUCCESS;
217262306a36Sopenharmony_ci
217362306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
217462306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
217562306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_GET_IP_ADDR_STATE;
217662306a36Sopenharmony_ci	mbox_cmd[1] = acb_idx;
217762306a36Sopenharmony_ci	mbox_cmd[2] = ip_idx;
217862306a36Sopenharmony_ci
217962306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, 3, 8, &mbox_cmd[0], &mbox_sts[0]);
218062306a36Sopenharmony_ci	if (status != QLA_SUCCESS) {
218162306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_WARNING, ha,  "%s: "
218262306a36Sopenharmony_ci				  "MBOX_CMD_GET_IP_ADDR_STATE failed w/ "
218362306a36Sopenharmony_ci				  "status %04X\n", __func__, mbox_sts[0]));
218462306a36Sopenharmony_ci	}
218562306a36Sopenharmony_ci	memcpy(sts, mbox_sts, sizeof(mbox_sts));
218662306a36Sopenharmony_ci	return status;
218762306a36Sopenharmony_ci}
218862306a36Sopenharmony_ci
218962306a36Sopenharmony_ciint qla4xxx_get_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,
219062306a36Sopenharmony_ci		      uint32_t offset, uint32_t size)
219162306a36Sopenharmony_ci{
219262306a36Sopenharmony_ci	int status = QLA_SUCCESS;
219362306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
219462306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
219562306a36Sopenharmony_ci
219662306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
219762306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
219862306a36Sopenharmony_ci
219962306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_GET_NVRAM;
220062306a36Sopenharmony_ci	mbox_cmd[1] = LSDW(nvram_dma);
220162306a36Sopenharmony_ci	mbox_cmd[2] = MSDW(nvram_dma);
220262306a36Sopenharmony_ci	mbox_cmd[3] = offset;
220362306a36Sopenharmony_ci	mbox_cmd[4] = size;
220462306a36Sopenharmony_ci
220562306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
220662306a36Sopenharmony_ci					 &mbox_sts[0]);
220762306a36Sopenharmony_ci	if (status != QLA_SUCCESS) {
220862306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
220962306a36Sopenharmony_ci				  "status %04X\n", ha->host_no, __func__,
221062306a36Sopenharmony_ci				  mbox_sts[0]));
221162306a36Sopenharmony_ci	}
221262306a36Sopenharmony_ci	return status;
221362306a36Sopenharmony_ci}
221462306a36Sopenharmony_ci
221562306a36Sopenharmony_ciint qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,
221662306a36Sopenharmony_ci		      uint32_t offset, uint32_t size)
221762306a36Sopenharmony_ci{
221862306a36Sopenharmony_ci	int status = QLA_SUCCESS;
221962306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
222062306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
222162306a36Sopenharmony_ci
222262306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
222362306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
222462306a36Sopenharmony_ci
222562306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_SET_NVRAM;
222662306a36Sopenharmony_ci	mbox_cmd[1] = LSDW(nvram_dma);
222762306a36Sopenharmony_ci	mbox_cmd[2] = MSDW(nvram_dma);
222862306a36Sopenharmony_ci	mbox_cmd[3] = offset;
222962306a36Sopenharmony_ci	mbox_cmd[4] = size;
223062306a36Sopenharmony_ci
223162306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
223262306a36Sopenharmony_ci					 &mbox_sts[0]);
223362306a36Sopenharmony_ci	if (status != QLA_SUCCESS) {
223462306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
223562306a36Sopenharmony_ci				  "status %04X\n", ha->host_no, __func__,
223662306a36Sopenharmony_ci				  mbox_sts[0]));
223762306a36Sopenharmony_ci	}
223862306a36Sopenharmony_ci	return status;
223962306a36Sopenharmony_ci}
224062306a36Sopenharmony_ci
224162306a36Sopenharmony_ciint qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha,
224262306a36Sopenharmony_ci				     uint32_t region, uint32_t field0,
224362306a36Sopenharmony_ci				     uint32_t field1)
224462306a36Sopenharmony_ci{
224562306a36Sopenharmony_ci	int status = QLA_SUCCESS;
224662306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
224762306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
224862306a36Sopenharmony_ci
224962306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
225062306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
225162306a36Sopenharmony_ci
225262306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_RESTORE_FACTORY_DEFAULTS;
225362306a36Sopenharmony_ci	mbox_cmd[3] = region;
225462306a36Sopenharmony_ci	mbox_cmd[4] = field0;
225562306a36Sopenharmony_ci	mbox_cmd[5] = field1;
225662306a36Sopenharmony_ci
225762306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0],
225862306a36Sopenharmony_ci					 &mbox_sts[0]);
225962306a36Sopenharmony_ci	if (status != QLA_SUCCESS) {
226062306a36Sopenharmony_ci		DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
226162306a36Sopenharmony_ci				  "status %04X\n", ha->host_no, __func__,
226262306a36Sopenharmony_ci				  mbox_sts[0]));
226362306a36Sopenharmony_ci	}
226462306a36Sopenharmony_ci	return status;
226562306a36Sopenharmony_ci}
226662306a36Sopenharmony_ci
226762306a36Sopenharmony_ci/**
226862306a36Sopenharmony_ci * qla4_8xxx_set_param - set driver version in firmware.
226962306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
227062306a36Sopenharmony_ci * @param: Parameter to set i.e driver version
227162306a36Sopenharmony_ci **/
227262306a36Sopenharmony_ciint qla4_8xxx_set_param(struct scsi_qla_host *ha, int param)
227362306a36Sopenharmony_ci{
227462306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
227562306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
227662306a36Sopenharmony_ci	uint32_t status;
227762306a36Sopenharmony_ci
227862306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
227962306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
228062306a36Sopenharmony_ci
228162306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_SET_PARAM;
228262306a36Sopenharmony_ci	if (param == SET_DRVR_VERSION) {
228362306a36Sopenharmony_ci		mbox_cmd[1] = SET_DRVR_VERSION;
228462306a36Sopenharmony_ci		strncpy((char *)&mbox_cmd[2], QLA4XXX_DRIVER_VERSION,
228562306a36Sopenharmony_ci			MAX_DRVR_VER_LEN - 1);
228662306a36Sopenharmony_ci	} else {
228762306a36Sopenharmony_ci		ql4_printk(KERN_ERR, ha, "%s: invalid parameter 0x%x\n",
228862306a36Sopenharmony_ci			   __func__, param);
228962306a36Sopenharmony_ci		status = QLA_ERROR;
229062306a36Sopenharmony_ci		goto exit_set_param;
229162306a36Sopenharmony_ci	}
229262306a36Sopenharmony_ci
229362306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, mbox_cmd,
229462306a36Sopenharmony_ci					 mbox_sts);
229562306a36Sopenharmony_ci	if (status == QLA_ERROR)
229662306a36Sopenharmony_ci		ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",
229762306a36Sopenharmony_ci			   __func__, mbox_sts[0]);
229862306a36Sopenharmony_ci
229962306a36Sopenharmony_ciexit_set_param:
230062306a36Sopenharmony_ci	return status;
230162306a36Sopenharmony_ci}
230262306a36Sopenharmony_ci
230362306a36Sopenharmony_ci/**
230462306a36Sopenharmony_ci * qla4_83xx_post_idc_ack - post IDC ACK
230562306a36Sopenharmony_ci * @ha: Pointer to host adapter structure.
230662306a36Sopenharmony_ci *
230762306a36Sopenharmony_ci * Posts IDC ACK for IDC Request Notification AEN.
230862306a36Sopenharmony_ci **/
230962306a36Sopenharmony_ciint qla4_83xx_post_idc_ack(struct scsi_qla_host *ha)
231062306a36Sopenharmony_ci{
231162306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
231262306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
231362306a36Sopenharmony_ci	int status;
231462306a36Sopenharmony_ci
231562306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
231662306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
231762306a36Sopenharmony_ci
231862306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_IDC_ACK;
231962306a36Sopenharmony_ci	mbox_cmd[1] = ha->idc_info.request_desc;
232062306a36Sopenharmony_ci	mbox_cmd[2] = ha->idc_info.info1;
232162306a36Sopenharmony_ci	mbox_cmd[3] = ha->idc_info.info2;
232262306a36Sopenharmony_ci	mbox_cmd[4] = ha->idc_info.info3;
232362306a36Sopenharmony_ci
232462306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT,
232562306a36Sopenharmony_ci					 mbox_cmd, mbox_sts);
232662306a36Sopenharmony_ci	if (status == QLA_ERROR)
232762306a36Sopenharmony_ci		ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__,
232862306a36Sopenharmony_ci			   mbox_sts[0]);
232962306a36Sopenharmony_ci	else
233062306a36Sopenharmony_ci	       ql4_printk(KERN_INFO, ha, "%s: IDC ACK posted\n", __func__);
233162306a36Sopenharmony_ci
233262306a36Sopenharmony_ci	return status;
233362306a36Sopenharmony_ci}
233462306a36Sopenharmony_ci
233562306a36Sopenharmony_ciint qla4_84xx_config_acb(struct scsi_qla_host *ha, int acb_config)
233662306a36Sopenharmony_ci{
233762306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
233862306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
233962306a36Sopenharmony_ci	struct addr_ctrl_blk *acb = NULL;
234062306a36Sopenharmony_ci	uint32_t acb_len = sizeof(struct addr_ctrl_blk);
234162306a36Sopenharmony_ci	int rval = QLA_SUCCESS;
234262306a36Sopenharmony_ci	dma_addr_t acb_dma;
234362306a36Sopenharmony_ci
234462306a36Sopenharmony_ci	acb = dma_alloc_coherent(&ha->pdev->dev,
234562306a36Sopenharmony_ci				 sizeof(struct addr_ctrl_blk),
234662306a36Sopenharmony_ci				 &acb_dma, GFP_KERNEL);
234762306a36Sopenharmony_ci	if (!acb) {
234862306a36Sopenharmony_ci		ql4_printk(KERN_ERR, ha, "%s: Unable to alloc acb\n", __func__);
234962306a36Sopenharmony_ci		rval = QLA_ERROR;
235062306a36Sopenharmony_ci		goto exit_config_acb;
235162306a36Sopenharmony_ci	}
235262306a36Sopenharmony_ci	memset(acb, 0, acb_len);
235362306a36Sopenharmony_ci
235462306a36Sopenharmony_ci	switch (acb_config) {
235562306a36Sopenharmony_ci	case ACB_CONFIG_DISABLE:
235662306a36Sopenharmony_ci		rval = qla4xxx_get_acb(ha, acb_dma, 0, acb_len);
235762306a36Sopenharmony_ci		if (rval != QLA_SUCCESS)
235862306a36Sopenharmony_ci			goto exit_free_acb;
235962306a36Sopenharmony_ci
236062306a36Sopenharmony_ci		rval = qla4xxx_disable_acb(ha);
236162306a36Sopenharmony_ci		if (rval != QLA_SUCCESS)
236262306a36Sopenharmony_ci			goto exit_free_acb;
236362306a36Sopenharmony_ci
236462306a36Sopenharmony_ci		if (!ha->saved_acb)
236562306a36Sopenharmony_ci			ha->saved_acb = kzalloc(acb_len, GFP_KERNEL);
236662306a36Sopenharmony_ci
236762306a36Sopenharmony_ci		if (!ha->saved_acb) {
236862306a36Sopenharmony_ci			ql4_printk(KERN_ERR, ha, "%s: Unable to alloc acb\n",
236962306a36Sopenharmony_ci				   __func__);
237062306a36Sopenharmony_ci			rval = QLA_ERROR;
237162306a36Sopenharmony_ci			goto exit_free_acb;
237262306a36Sopenharmony_ci		}
237362306a36Sopenharmony_ci		memcpy(ha->saved_acb, acb, acb_len);
237462306a36Sopenharmony_ci		break;
237562306a36Sopenharmony_ci	case ACB_CONFIG_SET:
237662306a36Sopenharmony_ci
237762306a36Sopenharmony_ci		if (!ha->saved_acb) {
237862306a36Sopenharmony_ci			ql4_printk(KERN_ERR, ha, "%s: Can't set ACB, Saved ACB not available\n",
237962306a36Sopenharmony_ci				   __func__);
238062306a36Sopenharmony_ci			rval = QLA_ERROR;
238162306a36Sopenharmony_ci			goto exit_free_acb;
238262306a36Sopenharmony_ci		}
238362306a36Sopenharmony_ci
238462306a36Sopenharmony_ci		memcpy(acb, ha->saved_acb, acb_len);
238562306a36Sopenharmony_ci
238662306a36Sopenharmony_ci		rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], acb_dma);
238762306a36Sopenharmony_ci		if (rval != QLA_SUCCESS)
238862306a36Sopenharmony_ci			goto exit_free_acb;
238962306a36Sopenharmony_ci
239062306a36Sopenharmony_ci		break;
239162306a36Sopenharmony_ci	default:
239262306a36Sopenharmony_ci		ql4_printk(KERN_ERR, ha, "%s: Invalid ACB Configuration\n",
239362306a36Sopenharmony_ci			   __func__);
239462306a36Sopenharmony_ci	}
239562306a36Sopenharmony_ci
239662306a36Sopenharmony_ciexit_free_acb:
239762306a36Sopenharmony_ci	dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk), acb,
239862306a36Sopenharmony_ci			  acb_dma);
239962306a36Sopenharmony_ciexit_config_acb:
240062306a36Sopenharmony_ci	if ((acb_config == ACB_CONFIG_SET) && ha->saved_acb) {
240162306a36Sopenharmony_ci		kfree(ha->saved_acb);
240262306a36Sopenharmony_ci		ha->saved_acb = NULL;
240362306a36Sopenharmony_ci	}
240462306a36Sopenharmony_ci	DEBUG2(ql4_printk(KERN_INFO, ha,
240562306a36Sopenharmony_ci			  "%s %s\n", __func__,
240662306a36Sopenharmony_ci			  rval == QLA_SUCCESS ? "SUCCEEDED" : "FAILED"));
240762306a36Sopenharmony_ci	return rval;
240862306a36Sopenharmony_ci}
240962306a36Sopenharmony_ci
241062306a36Sopenharmony_ciint qla4_83xx_get_port_config(struct scsi_qla_host *ha, uint32_t *config)
241162306a36Sopenharmony_ci{
241262306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
241362306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
241462306a36Sopenharmony_ci	int status;
241562306a36Sopenharmony_ci
241662306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
241762306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
241862306a36Sopenharmony_ci
241962306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_GET_PORT_CONFIG;
242062306a36Sopenharmony_ci
242162306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT,
242262306a36Sopenharmony_ci					 mbox_cmd, mbox_sts);
242362306a36Sopenharmony_ci	if (status == QLA_SUCCESS)
242462306a36Sopenharmony_ci		*config = mbox_sts[1];
242562306a36Sopenharmony_ci	else
242662306a36Sopenharmony_ci		ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__,
242762306a36Sopenharmony_ci			   mbox_sts[0]);
242862306a36Sopenharmony_ci
242962306a36Sopenharmony_ci	return status;
243062306a36Sopenharmony_ci}
243162306a36Sopenharmony_ci
243262306a36Sopenharmony_ciint qla4_83xx_set_port_config(struct scsi_qla_host *ha, uint32_t *config)
243362306a36Sopenharmony_ci{
243462306a36Sopenharmony_ci	uint32_t mbox_cmd[MBOX_REG_COUNT];
243562306a36Sopenharmony_ci	uint32_t mbox_sts[MBOX_REG_COUNT];
243662306a36Sopenharmony_ci	int status;
243762306a36Sopenharmony_ci
243862306a36Sopenharmony_ci	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
243962306a36Sopenharmony_ci	memset(&mbox_sts, 0, sizeof(mbox_sts));
244062306a36Sopenharmony_ci
244162306a36Sopenharmony_ci	mbox_cmd[0] = MBOX_CMD_SET_PORT_CONFIG;
244262306a36Sopenharmony_ci	mbox_cmd[1] = *config;
244362306a36Sopenharmony_ci
244462306a36Sopenharmony_ci	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT,
244562306a36Sopenharmony_ci				mbox_cmd, mbox_sts);
244662306a36Sopenharmony_ci	if (status != QLA_SUCCESS)
244762306a36Sopenharmony_ci		ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__,
244862306a36Sopenharmony_ci			   mbox_sts[0]);
244962306a36Sopenharmony_ci
245062306a36Sopenharmony_ci	return status;
245162306a36Sopenharmony_ci}
2452