xref: /linux/drivers/scsi/qla4xxx/ql4_mbx.c (revision cfb27874ca278fbb157f82a1d0ca9faff49aecfe)
1afaf5a2dSDavid Somayajulu /*
2afaf5a2dSDavid Somayajulu  * QLogic iSCSI HBA Driver
3c68cdbf0SVikas Chaudhary  * Copyright (c)  2003-2012 QLogic Corporation
4afaf5a2dSDavid Somayajulu  *
5afaf5a2dSDavid Somayajulu  * See LICENSE.qla4xxx for copyright and licensing details.
6afaf5a2dSDavid Somayajulu  */
7afaf5a2dSDavid Somayajulu 
8afaf5a2dSDavid Somayajulu #include "ql4_def.h"
9c0e344c9SDavid C Somayajulu #include "ql4_glbl.h"
10c0e344c9SDavid C Somayajulu #include "ql4_dbg.h"
11c0e344c9SDavid C Somayajulu #include "ql4_inline.h"
12*cfb27874SManish Dusane #include "ql4_version.h"
13afaf5a2dSDavid Somayajulu 
1433693c7aSVikas Chaudhary void qla4xxx_queue_mbox_cmd(struct scsi_qla_host *ha, uint32_t *mbx_cmd,
1533693c7aSVikas Chaudhary 			    int in_count)
1633693c7aSVikas Chaudhary {
1733693c7aSVikas Chaudhary 	int i;
1833693c7aSVikas Chaudhary 
1933693c7aSVikas Chaudhary 	/* Load all mailbox registers, except mailbox 0. */
2033693c7aSVikas Chaudhary 	for (i = 1; i < in_count; i++)
2133693c7aSVikas Chaudhary 		writel(mbx_cmd[i], &ha->reg->mailbox[i]);
2233693c7aSVikas Chaudhary 
2333693c7aSVikas Chaudhary 	/* Wakeup firmware  */
2433693c7aSVikas Chaudhary 	writel(mbx_cmd[0], &ha->reg->mailbox[0]);
2533693c7aSVikas Chaudhary 	readl(&ha->reg->mailbox[0]);
2633693c7aSVikas Chaudhary 	writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status);
2733693c7aSVikas Chaudhary 	readl(&ha->reg->ctrl_status);
2833693c7aSVikas Chaudhary }
2933693c7aSVikas Chaudhary 
3033693c7aSVikas Chaudhary void qla4xxx_process_mbox_intr(struct scsi_qla_host *ha, int out_count)
3133693c7aSVikas Chaudhary {
3233693c7aSVikas Chaudhary 	int intr_status;
3333693c7aSVikas Chaudhary 
3433693c7aSVikas Chaudhary 	intr_status = readl(&ha->reg->ctrl_status);
3533693c7aSVikas Chaudhary 	if (intr_status & INTR_PENDING) {
3633693c7aSVikas Chaudhary 		/*
3733693c7aSVikas Chaudhary 		 * Service the interrupt.
3833693c7aSVikas Chaudhary 		 * The ISR will save the mailbox status registers
3933693c7aSVikas Chaudhary 		 * to a temporary storage location in the adapter structure.
4033693c7aSVikas Chaudhary 		 */
4133693c7aSVikas Chaudhary 		ha->mbox_status_count = out_count;
4233693c7aSVikas Chaudhary 		ha->isp_ops->interrupt_service_routine(ha, intr_status);
4333693c7aSVikas Chaudhary 	}
4433693c7aSVikas Chaudhary }
45afaf5a2dSDavid Somayajulu 
46afaf5a2dSDavid Somayajulu /**
47afaf5a2dSDavid Somayajulu  * qla4xxx_mailbox_command - issues mailbox commands
48afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
49afaf5a2dSDavid Somayajulu  * @inCount: number of mailbox registers to load.
50afaf5a2dSDavid Somayajulu  * @outCount: number of mailbox registers to return.
51afaf5a2dSDavid Somayajulu  * @mbx_cmd: data pointer for mailbox in registers.
52afaf5a2dSDavid Somayajulu  * @mbx_sts: data pointer for mailbox out registers.
53afaf5a2dSDavid Somayajulu  *
5470f23fd6SJustin P. Mattock  * This routine issue mailbox commands and waits for completion.
55afaf5a2dSDavid Somayajulu  * If outCount is 0, this routine completes successfully WITHOUT waiting
56afaf5a2dSDavid Somayajulu  * for the mailbox command to complete.
57afaf5a2dSDavid Somayajulu  **/
58f4f5df23SVikas Chaudhary int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
59afaf5a2dSDavid Somayajulu 			    uint8_t outCount, uint32_t *mbx_cmd,
60afaf5a2dSDavid Somayajulu 			    uint32_t *mbx_sts)
61afaf5a2dSDavid Somayajulu {
62afaf5a2dSDavid Somayajulu 	int status = QLA_ERROR;
63afaf5a2dSDavid Somayajulu 	uint8_t i;
64afaf5a2dSDavid Somayajulu 	u_long wait_count;
65afaf5a2dSDavid Somayajulu 	unsigned long flags = 0;
6699b53bf5SPrasanna Mumbai 	uint32_t dev_state;
67afaf5a2dSDavid Somayajulu 
68afaf5a2dSDavid Somayajulu 	/* Make sure that pointers are valid */
69afaf5a2dSDavid Somayajulu 	if (!mbx_cmd || !mbx_sts) {
70afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts "
71afaf5a2dSDavid Somayajulu 			      "pointer\n", ha->host_no, __func__));
72477ffb9dSDavid C Somayajulu 		return status;
73477ffb9dSDavid C Somayajulu 	}
7421033639SNilesh Javali 
7513483730SMike Christie 	if (is_qla40XX(ha)) {
7613483730SMike Christie 		if (test_bit(AF_HA_REMOVAL, &ha->flags)) {
7713483730SMike Christie 			DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: "
7813483730SMike Christie 					  "prematurely completing mbx cmd as "
7913483730SMike Christie 					  "adapter removal detected\n",
8013483730SMike Christie 					  ha->host_no, __func__));
8113483730SMike Christie 			return status;
8213483730SMike Christie 		}
8313483730SMike Christie 	}
8413483730SMike Christie 
852232be0dSLalit Chandivade 	if ((is_aer_supported(ha)) &&
862232be0dSLalit Chandivade 	    (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) {
872232be0dSLalit Chandivade 		DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, "
882232be0dSLalit Chandivade 		    "timeout MBX Exiting.\n", ha->host_no, __func__));
892232be0dSLalit Chandivade 		return status;
902232be0dSLalit Chandivade 	}
912232be0dSLalit Chandivade 
92477ffb9dSDavid C Somayajulu 	/* Mailbox code active */
93477ffb9dSDavid C Somayajulu 	wait_count = MBOX_TOV * 100;
94477ffb9dSDavid C Somayajulu 
95477ffb9dSDavid C Somayajulu 	while (wait_count--) {
96477ffb9dSDavid C Somayajulu 		mutex_lock(&ha->mbox_sem);
97477ffb9dSDavid C Somayajulu 		if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) {
98477ffb9dSDavid C Somayajulu 			set_bit(AF_MBOX_COMMAND, &ha->flags);
99477ffb9dSDavid C Somayajulu 			mutex_unlock(&ha->mbox_sem);
100477ffb9dSDavid C Somayajulu 			break;
101477ffb9dSDavid C Somayajulu 		}
102477ffb9dSDavid C Somayajulu 		mutex_unlock(&ha->mbox_sem);
103477ffb9dSDavid C Somayajulu 		if (!wait_count) {
104477ffb9dSDavid C Somayajulu 			DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n",
105477ffb9dSDavid C Somayajulu 				ha->host_no, __func__));
106477ffb9dSDavid C Somayajulu 			return status;
107477ffb9dSDavid C Somayajulu 		}
108477ffb9dSDavid C Somayajulu 		msleep(10);
109afaf5a2dSDavid Somayajulu 	}
110afaf5a2dSDavid Somayajulu 
1116e7b4292SVikas Chaudhary 	if (is_qla80XX(ha)) {
1125f50aa3aSLalit Chandivade 		if (test_bit(AF_FW_RECOVERY, &ha->flags)) {
1135f50aa3aSLalit Chandivade 			DEBUG2(ql4_printk(KERN_WARNING, ha,
1145f50aa3aSLalit Chandivade 					  "scsi%ld: %s: prematurely completing mbx cmd as firmware recovery detected\n",
1155f50aa3aSLalit Chandivade 					  ha->host_no, __func__));
1165f50aa3aSLalit Chandivade 			goto mbox_exit;
1175f50aa3aSLalit Chandivade 		}
1185f50aa3aSLalit Chandivade 		/* Do not send any mbx cmd if h/w is in failed state*/
11933693c7aSVikas Chaudhary 		ha->isp_ops->idc_lock(ha);
12033693c7aSVikas Chaudhary 		dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE);
12133693c7aSVikas Chaudhary 		ha->isp_ops->idc_unlock(ha);
122de8c72daSVikas Chaudhary 		if (dev_state == QLA8XXX_DEV_FAILED) {
1235f50aa3aSLalit Chandivade 			ql4_printk(KERN_WARNING, ha,
1245f50aa3aSLalit Chandivade 				   "scsi%ld: %s: H/W is in failed state, do not send any mailbox commands\n",
1255f50aa3aSLalit Chandivade 				   ha->host_no, __func__);
1265f50aa3aSLalit Chandivade 			goto mbox_exit;
1275f50aa3aSLalit Chandivade 		}
1285f50aa3aSLalit Chandivade 	}
1295f50aa3aSLalit Chandivade 
130afaf5a2dSDavid Somayajulu 	spin_lock_irqsave(&ha->hardware_lock, flags);
131f4f5df23SVikas Chaudhary 
132afaf5a2dSDavid Somayajulu 	ha->mbox_status_count = outCount;
133afaf5a2dSDavid Somayajulu 	for (i = 0; i < outCount; i++)
134afaf5a2dSDavid Somayajulu 		ha->mbox_status[i] = 0;
135afaf5a2dSDavid Somayajulu 
13633693c7aSVikas Chaudhary 	/* Queue the mailbox command to the firmware */
13733693c7aSVikas Chaudhary 	ha->isp_ops->queue_mailbox_command(ha, mbx_cmd, inCount);
138f4f5df23SVikas Chaudhary 
139afaf5a2dSDavid Somayajulu 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
140afaf5a2dSDavid Somayajulu 
141afaf5a2dSDavid Somayajulu 	/* Wait for completion */
142afaf5a2dSDavid Somayajulu 
143afaf5a2dSDavid Somayajulu 	/*
144afaf5a2dSDavid Somayajulu 	 * If we don't want status, don't wait for the mailbox command to
145afaf5a2dSDavid Somayajulu 	 * complete.  For example, MBOX_CMD_RESET_FW doesn't return status,
146afaf5a2dSDavid Somayajulu 	 * you must poll the inbound Interrupt Mask for completion.
147afaf5a2dSDavid Somayajulu 	 */
148afaf5a2dSDavid Somayajulu 	if (outCount == 0) {
149afaf5a2dSDavid Somayajulu 		status = QLA_SUCCESS;
150afaf5a2dSDavid Somayajulu 		goto mbox_exit;
151afaf5a2dSDavid Somayajulu 	}
152f4f5df23SVikas Chaudhary 
153f4f5df23SVikas Chaudhary 	/*
154f4f5df23SVikas Chaudhary 	 * Wait for completion: Poll or completion queue
155f4f5df23SVikas Chaudhary 	 */
156f4f5df23SVikas Chaudhary 	if (test_bit(AF_IRQ_ATTACHED, &ha->flags) &&
157f4f5df23SVikas Chaudhary 	    test_bit(AF_INTERRUPTS_ON, &ha->flags) &&
158f4f5df23SVikas Chaudhary 	    test_bit(AF_ONLINE, &ha->flags) &&
1597eece5a0SKaren Higgins 	    !test_bit(AF_HA_REMOVAL, &ha->flags)) {
160f4f5df23SVikas Chaudhary 		/* Do not poll for completion. Use completion queue */
161f4f5df23SVikas Chaudhary 		set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
162f4f5df23SVikas Chaudhary 		wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ);
163f4f5df23SVikas Chaudhary 		clear_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
164f4f5df23SVikas Chaudhary 	} else {
165f4f5df23SVikas Chaudhary 		/* Poll for command to complete */
166afaf5a2dSDavid Somayajulu 		wait_count = jiffies + MBOX_TOV * HZ;
167afaf5a2dSDavid Somayajulu 		while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) {
168afaf5a2dSDavid Somayajulu 			if (time_after_eq(jiffies, wait_count))
169afaf5a2dSDavid Somayajulu 				break;
1702232be0dSLalit Chandivade 
171afaf5a2dSDavid Somayajulu 			/*
172afaf5a2dSDavid Somayajulu 			 * Service the interrupt.
173afaf5a2dSDavid Somayajulu 			 * The ISR will save the mailbox status registers
174afaf5a2dSDavid Somayajulu 			 * to a temporary storage location in the adapter
175afaf5a2dSDavid Somayajulu 			 * structure.
176afaf5a2dSDavid Somayajulu 			 */
177f4f5df23SVikas Chaudhary 
178f4f5df23SVikas Chaudhary 			spin_lock_irqsave(&ha->hardware_lock, flags);
17933693c7aSVikas Chaudhary 			ha->isp_ops->process_mailbox_interrupt(ha, outCount);
180afaf5a2dSDavid Somayajulu 			spin_unlock_irqrestore(&ha->hardware_lock, flags);
181afaf5a2dSDavid Somayajulu 			msleep(10);
182afaf5a2dSDavid Somayajulu 		}
183f4f5df23SVikas Chaudhary 	}
184afaf5a2dSDavid Somayajulu 
185afaf5a2dSDavid Somayajulu 	/* Check for mailbox timeout. */
186afaf5a2dSDavid Somayajulu 	if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) {
1876e7b4292SVikas Chaudhary 		if (is_qla80XX(ha) &&
18821033639SNilesh Javali 		    test_bit(AF_FW_RECOVERY, &ha->flags)) {
18921033639SNilesh Javali 			DEBUG2(ql4_printk(KERN_INFO, ha,
19021033639SNilesh Javali 			    "scsi%ld: %s: prematurely completing mbx cmd as "
19121033639SNilesh Javali 			    "firmware recovery detected\n",
19221033639SNilesh Javali 			    ha->host_no, __func__));
19321033639SNilesh Javali 			goto mbox_exit;
19421033639SNilesh Javali 		}
195afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: Mailbox Cmd 0x%08X timed out ...,"
196afaf5a2dSDavid Somayajulu 			      " Scheduling Adapter Reset\n", ha->host_no,
197afaf5a2dSDavid Somayajulu 			      mbx_cmd[0]));
198afaf5a2dSDavid Somayajulu 		ha->mailbox_timeout_count++;
199afaf5a2dSDavid Somayajulu 		mbx_sts[0] = (-1);
200afaf5a2dSDavid Somayajulu 		set_bit(DPC_RESET_HA, &ha->dpc_flags);
201e6bd0ebdSGiridhar Malavali 		if (is_qla8022(ha)) {
202e6bd0ebdSGiridhar Malavali 			ql4_printk(KERN_INFO, ha,
203e6bd0ebdSGiridhar Malavali 				   "disabling pause transmit on port 0 & 1.\n");
204f8086f4fSVikas Chaudhary 			qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
205e6bd0ebdSGiridhar Malavali 					CRB_NIU_XG_PAUSE_CTL_P0 |
206e6bd0ebdSGiridhar Malavali 					CRB_NIU_XG_PAUSE_CTL_P1);
207e6bd0ebdSGiridhar Malavali 		}
208afaf5a2dSDavid Somayajulu 		goto mbox_exit;
209afaf5a2dSDavid Somayajulu 	}
210afaf5a2dSDavid Somayajulu 
211afaf5a2dSDavid Somayajulu 	/*
212afaf5a2dSDavid Somayajulu 	 * Copy the mailbox out registers to the caller's mailbox in/out
213afaf5a2dSDavid Somayajulu 	 * structure.
214afaf5a2dSDavid Somayajulu 	 */
215afaf5a2dSDavid Somayajulu 	spin_lock_irqsave(&ha->hardware_lock, flags);
216afaf5a2dSDavid Somayajulu 	for (i = 0; i < outCount; i++)
217afaf5a2dSDavid Somayajulu 		mbx_sts[i] = ha->mbox_status[i];
218afaf5a2dSDavid Somayajulu 
219afaf5a2dSDavid Somayajulu 	/* Set return status and error flags (if applicable). */
220afaf5a2dSDavid Somayajulu 	switch (ha->mbox_status[0]) {
221afaf5a2dSDavid Somayajulu 	case MBOX_STS_COMMAND_COMPLETE:
222afaf5a2dSDavid Somayajulu 		status = QLA_SUCCESS;
223afaf5a2dSDavid Somayajulu 		break;
224afaf5a2dSDavid Somayajulu 
225afaf5a2dSDavid Somayajulu 	case MBOX_STS_INTERMEDIATE_COMPLETION:
226afaf5a2dSDavid Somayajulu 		status = QLA_SUCCESS;
227afaf5a2dSDavid Somayajulu 		break;
228afaf5a2dSDavid Somayajulu 
229afaf5a2dSDavid Somayajulu 	case MBOX_STS_BUSY:
230afaf5a2dSDavid Somayajulu 		DEBUG2( printk("scsi%ld: %s: Cmd = %08X, ISP BUSY\n",
231afaf5a2dSDavid Somayajulu 			       ha->host_no, __func__, mbx_cmd[0]));
232afaf5a2dSDavid Somayajulu 		ha->mailbox_timeout_count++;
233afaf5a2dSDavid Somayajulu 		break;
234afaf5a2dSDavid Somayajulu 
235afaf5a2dSDavid Somayajulu 	default:
236afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: **** FAILED, cmd = %08X, "
237afaf5a2dSDavid Somayajulu 			      "sts = %08X ****\n", ha->host_no, __func__,
238afaf5a2dSDavid Somayajulu 			      mbx_cmd[0], mbx_sts[0]));
239afaf5a2dSDavid Somayajulu 		break;
240afaf5a2dSDavid Somayajulu 	}
241afaf5a2dSDavid Somayajulu 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
242afaf5a2dSDavid Somayajulu 
243afaf5a2dSDavid Somayajulu mbox_exit:
244477ffb9dSDavid C Somayajulu 	mutex_lock(&ha->mbox_sem);
245afaf5a2dSDavid Somayajulu 	clear_bit(AF_MBOX_COMMAND, &ha->flags);
246afaf5a2dSDavid Somayajulu 	mutex_unlock(&ha->mbox_sem);
247477ffb9dSDavid C Somayajulu 	clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
248afaf5a2dSDavid Somayajulu 
249afaf5a2dSDavid Somayajulu 	return status;
250afaf5a2dSDavid Somayajulu }
251afaf5a2dSDavid Somayajulu 
252068237c8STej Parkash /**
253068237c8STej Parkash  * qla4xxx_get_minidump_template - Get the firmware template
254068237c8STej Parkash  * @ha: Pointer to host adapter structure.
255068237c8STej Parkash  * @phys_addr: dma address for template
256068237c8STej Parkash  *
257068237c8STej Parkash  * Obtain the minidump template from firmware during initialization
258068237c8STej Parkash  * as it may not be available when minidump is desired.
259068237c8STej Parkash  **/
260068237c8STej Parkash int qla4xxx_get_minidump_template(struct scsi_qla_host *ha,
261068237c8STej Parkash 				  dma_addr_t phys_addr)
262068237c8STej Parkash {
263068237c8STej Parkash 	uint32_t mbox_cmd[MBOX_REG_COUNT];
264068237c8STej Parkash 	uint32_t mbox_sts[MBOX_REG_COUNT];
265068237c8STej Parkash 	int status;
266068237c8STej Parkash 
267068237c8STej Parkash 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
268068237c8STej Parkash 	memset(&mbox_sts, 0, sizeof(mbox_sts));
269068237c8STej Parkash 
270068237c8STej Parkash 	mbox_cmd[0] = MBOX_CMD_MINIDUMP;
271068237c8STej Parkash 	mbox_cmd[1] = MINIDUMP_GET_TMPLT_SUBCOMMAND;
272068237c8STej Parkash 	mbox_cmd[2] = LSDW(phys_addr);
273068237c8STej Parkash 	mbox_cmd[3] = MSDW(phys_addr);
274068237c8STej Parkash 	mbox_cmd[4] = ha->fw_dump_tmplt_size;
275068237c8STej Parkash 	mbox_cmd[5] = 0;
276068237c8STej Parkash 
277068237c8STej Parkash 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
278068237c8STej Parkash 					 &mbox_sts[0]);
279068237c8STej Parkash 	if (status != QLA_SUCCESS) {
280068237c8STej Parkash 		DEBUG2(ql4_printk(KERN_INFO, ha,
281068237c8STej Parkash 				  "scsi%ld: %s: Cmd = %08X, mbx[0] = 0x%04x, mbx[1] = 0x%04x\n",
282068237c8STej Parkash 				  ha->host_no, __func__, mbox_cmd[0],
283068237c8STej Parkash 				  mbox_sts[0], mbox_sts[1]));
284068237c8STej Parkash 	}
285068237c8STej Parkash 	return status;
286068237c8STej Parkash }
287068237c8STej Parkash 
288068237c8STej Parkash /**
289068237c8STej Parkash  * qla4xxx_req_template_size - Get minidump template size from firmware.
290068237c8STej Parkash  * @ha: Pointer to host adapter structure.
291068237c8STej Parkash  **/
292068237c8STej Parkash int qla4xxx_req_template_size(struct scsi_qla_host *ha)
293068237c8STej Parkash {
294068237c8STej Parkash 	uint32_t mbox_cmd[MBOX_REG_COUNT];
295068237c8STej Parkash 	uint32_t mbox_sts[MBOX_REG_COUNT];
296068237c8STej Parkash 	int status;
297068237c8STej Parkash 
298068237c8STej Parkash 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
299068237c8STej Parkash 	memset(&mbox_sts, 0, sizeof(mbox_sts));
300068237c8STej Parkash 
301068237c8STej Parkash 	mbox_cmd[0] = MBOX_CMD_MINIDUMP;
302068237c8STej Parkash 	mbox_cmd[1] = MINIDUMP_GET_SIZE_SUBCOMMAND;
303068237c8STej Parkash 
304068237c8STej Parkash 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0],
305068237c8STej Parkash 					 &mbox_sts[0]);
306068237c8STej Parkash 	if (status == QLA_SUCCESS) {
307068237c8STej Parkash 		ha->fw_dump_tmplt_size = mbox_sts[1];
308068237c8STej Parkash 		DEBUG2(ql4_printk(KERN_INFO, ha,
309068237c8STej Parkash 				  "%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",
310068237c8STej Parkash 				  __func__, mbox_sts[0], mbox_sts[1],
311068237c8STej Parkash 				  mbox_sts[2], mbox_sts[3], mbox_sts[4],
312068237c8STej Parkash 				  mbox_sts[5], mbox_sts[6], mbox_sts[7]));
313068237c8STej Parkash 		if (ha->fw_dump_tmplt_size == 0)
314068237c8STej Parkash 			status = QLA_ERROR;
315068237c8STej Parkash 	} else {
316068237c8STej Parkash 		ql4_printk(KERN_WARNING, ha,
317068237c8STej Parkash 			   "%s: Error sts[0]=0x%04x, mbx[1]=0x%04x\n",
318068237c8STej Parkash 			   __func__, mbox_sts[0], mbox_sts[1]);
319068237c8STej Parkash 		status = QLA_ERROR;
320068237c8STej Parkash 	}
321068237c8STej Parkash 
322068237c8STej Parkash 	return status;
323068237c8STej Parkash }
324068237c8STej Parkash 
32521033639SNilesh Javali void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha)
32621033639SNilesh Javali {
32721033639SNilesh Javali 	set_bit(AF_FW_RECOVERY, &ha->flags);
32821033639SNilesh Javali 	ql4_printk(KERN_INFO, ha, "scsi%ld: %s: set FW RECOVERY!\n",
32921033639SNilesh Javali 	    ha->host_no, __func__);
33021033639SNilesh Javali 
33121033639SNilesh Javali 	if (test_bit(AF_MBOX_COMMAND, &ha->flags)) {
33221033639SNilesh Javali 		if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags)) {
33321033639SNilesh Javali 			complete(&ha->mbx_intr_comp);
33421033639SNilesh Javali 			ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw "
33521033639SNilesh Javali 			    "recovery, doing premature completion of "
33621033639SNilesh Javali 			    "mbx cmd\n", ha->host_no, __func__);
33721033639SNilesh Javali 
33821033639SNilesh Javali 		} else {
33921033639SNilesh Javali 			set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
34021033639SNilesh Javali 			ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw "
34121033639SNilesh Javali 			    "recovery, doing premature completion of "
34221033639SNilesh Javali 			    "polling mbx cmd\n", ha->host_no, __func__);
34321033639SNilesh Javali 		}
34421033639SNilesh Javali 	}
34521033639SNilesh Javali }
34621033639SNilesh Javali 
347f4f5df23SVikas Chaudhary static uint8_t
3482a49a78eSVikas Chaudhary qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
3492a49a78eSVikas Chaudhary 		 uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)
3502a49a78eSVikas Chaudhary {
3512a49a78eSVikas Chaudhary 	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
3522a49a78eSVikas Chaudhary 	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
3532657c800SShyam Sundar 
3542657c800SShyam Sundar 	if (is_qla8022(ha))
355f8086f4fSVikas Chaudhary 		qla4_82xx_wr_32(ha, ha->nx_db_wr_ptr, 0);
3562657c800SShyam Sundar 
3572a49a78eSVikas Chaudhary 	mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE;
3582a49a78eSVikas Chaudhary 	mbox_cmd[1] = 0;
3592a49a78eSVikas Chaudhary 	mbox_cmd[2] = LSDW(init_fw_cb_dma);
3602a49a78eSVikas Chaudhary 	mbox_cmd[3] = MSDW(init_fw_cb_dma);
3612a49a78eSVikas Chaudhary 	mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
3622a49a78eSVikas Chaudhary 	mbox_cmd[5] = (IFCB_VER_MAX << 8) | IFCB_VER_MIN;
3632a49a78eSVikas Chaudhary 
3642a49a78eSVikas Chaudhary 	if (qla4xxx_mailbox_command(ha, 6, 6, mbox_cmd, mbox_sts) !=
3652a49a78eSVikas Chaudhary 	    QLA_SUCCESS) {
3662a49a78eSVikas Chaudhary 		DEBUG2(printk(KERN_WARNING "scsi%ld: %s: "
3672a49a78eSVikas Chaudhary 			      "MBOX_CMD_INITIALIZE_FIRMWARE"
3682a49a78eSVikas Chaudhary 			      " failed w/ status %04X\n",
3692a49a78eSVikas Chaudhary 			      ha->host_no, __func__, mbox_sts[0]));
3702a49a78eSVikas Chaudhary 		return QLA_ERROR;
3712a49a78eSVikas Chaudhary 	}
3722a49a78eSVikas Chaudhary 	return QLA_SUCCESS;
3732a49a78eSVikas Chaudhary }
3742a49a78eSVikas Chaudhary 
375d00efe3fSMike Christie uint8_t
3762a49a78eSVikas Chaudhary qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
3772a49a78eSVikas Chaudhary 		 uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)
3782a49a78eSVikas Chaudhary {
3792a49a78eSVikas Chaudhary 	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
3802a49a78eSVikas Chaudhary 	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
3812a49a78eSVikas Chaudhary 	mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
3822a49a78eSVikas Chaudhary 	mbox_cmd[2] = LSDW(init_fw_cb_dma);
3832a49a78eSVikas Chaudhary 	mbox_cmd[3] = MSDW(init_fw_cb_dma);
3842a49a78eSVikas Chaudhary 	mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
3852a49a78eSVikas Chaudhary 
3862a49a78eSVikas Chaudhary 	if (qla4xxx_mailbox_command(ha, 5, 5, mbox_cmd, mbox_sts) !=
3872a49a78eSVikas Chaudhary 	    QLA_SUCCESS) {
3882a49a78eSVikas Chaudhary 		DEBUG2(printk(KERN_WARNING "scsi%ld: %s: "
3892a49a78eSVikas Chaudhary 			      "MBOX_CMD_GET_INIT_FW_CTRL_BLOCK"
3902a49a78eSVikas Chaudhary 			      " failed w/ status %04X\n",
3912a49a78eSVikas Chaudhary 			      ha->host_no, __func__, mbox_sts[0]));
3922a49a78eSVikas Chaudhary 		return QLA_ERROR;
3932a49a78eSVikas Chaudhary 	}
3942a49a78eSVikas Chaudhary 	return QLA_SUCCESS;
3952a49a78eSVikas Chaudhary }
3962a49a78eSVikas Chaudhary 
397f4f5df23SVikas Chaudhary static void
3982a49a78eSVikas Chaudhary qla4xxx_update_local_ip(struct scsi_qla_host *ha,
3992a49a78eSVikas Chaudhary 			struct addr_ctrl_blk *init_fw_cb)
4002a49a78eSVikas Chaudhary {
4012bab08fcSVikas Chaudhary 	ha->ip_config.tcp_options = le16_to_cpu(init_fw_cb->ipv4_tcp_opts);
4022bab08fcSVikas Chaudhary 	ha->ip_config.ipv4_options = le16_to_cpu(init_fw_cb->ipv4_ip_opts);
4032bab08fcSVikas Chaudhary 	ha->ip_config.ipv4_addr_state =
4042bab08fcSVikas Chaudhary 				le16_to_cpu(init_fw_cb->ipv4_addr_state);
405943c157bSVikas Chaudhary 	ha->ip_config.eth_mtu_size =
406943c157bSVikas Chaudhary 				le16_to_cpu(init_fw_cb->eth_mtu_size);
4072ada7fc5SVikas Chaudhary 	ha->ip_config.ipv4_port = le16_to_cpu(init_fw_cb->ipv4_port);
4082bab08fcSVikas Chaudhary 
4092bab08fcSVikas Chaudhary 	if (ha->acb_version == ACB_SUPPORTED) {
4102bab08fcSVikas Chaudhary 		ha->ip_config.ipv6_options = le16_to_cpu(init_fw_cb->ipv6_opts);
4112bab08fcSVikas Chaudhary 		ha->ip_config.ipv6_addl_options =
4122bab08fcSVikas Chaudhary 				le16_to_cpu(init_fw_cb->ipv6_addtl_opts);
4132bab08fcSVikas Chaudhary 	}
4142bab08fcSVikas Chaudhary 
4152a49a78eSVikas Chaudhary 	/* Save IPv4 Address Info */
4162bab08fcSVikas Chaudhary 	memcpy(ha->ip_config.ip_address, init_fw_cb->ipv4_addr,
4172bab08fcSVikas Chaudhary 	       min(sizeof(ha->ip_config.ip_address),
4182bab08fcSVikas Chaudhary 		   sizeof(init_fw_cb->ipv4_addr)));
4192bab08fcSVikas Chaudhary 	memcpy(ha->ip_config.subnet_mask, init_fw_cb->ipv4_subnet,
4202bab08fcSVikas Chaudhary 	       min(sizeof(ha->ip_config.subnet_mask),
4212bab08fcSVikas Chaudhary 		   sizeof(init_fw_cb->ipv4_subnet)));
4222bab08fcSVikas Chaudhary 	memcpy(ha->ip_config.gateway, init_fw_cb->ipv4_gw_addr,
4232bab08fcSVikas Chaudhary 	       min(sizeof(ha->ip_config.gateway),
4242bab08fcSVikas Chaudhary 		   sizeof(init_fw_cb->ipv4_gw_addr)));
4252a49a78eSVikas Chaudhary 
4266ac73e8cSVikas Chaudhary 	ha->ip_config.ipv4_vlan_tag = be16_to_cpu(init_fw_cb->ipv4_vlan_tag);
4276ac73e8cSVikas Chaudhary 
4282a49a78eSVikas Chaudhary 	if (is_ipv6_enabled(ha)) {
4292a49a78eSVikas Chaudhary 		/* Save IPv6 Address */
4302bab08fcSVikas Chaudhary 		ha->ip_config.ipv6_link_local_state =
4312bab08fcSVikas Chaudhary 			le16_to_cpu(init_fw_cb->ipv6_lnk_lcl_addr_state);
4322bab08fcSVikas Chaudhary 		ha->ip_config.ipv6_addr0_state =
4332bab08fcSVikas Chaudhary 				le16_to_cpu(init_fw_cb->ipv6_addr0_state);
4342bab08fcSVikas Chaudhary 		ha->ip_config.ipv6_addr1_state =
4352bab08fcSVikas Chaudhary 				le16_to_cpu(init_fw_cb->ipv6_addr1_state);
4362bab08fcSVikas Chaudhary 		ha->ip_config.ipv6_default_router_state =
4372bab08fcSVikas Chaudhary 				le16_to_cpu(init_fw_cb->ipv6_dflt_rtr_state);
4382bab08fcSVikas Chaudhary 		ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[0] = 0xFE;
4392bab08fcSVikas Chaudhary 		ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[1] = 0x80;
4402a49a78eSVikas Chaudhary 
4412bab08fcSVikas Chaudhary 		memcpy(&ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[8],
4422a49a78eSVikas Chaudhary 		       init_fw_cb->ipv6_if_id,
4432bab08fcSVikas Chaudhary 		       min(sizeof(ha->ip_config.ipv6_link_local_addr)/2,
4442a49a78eSVikas Chaudhary 			   sizeof(init_fw_cb->ipv6_if_id)));
4452bab08fcSVikas Chaudhary 		memcpy(&ha->ip_config.ipv6_addr0, init_fw_cb->ipv6_addr0,
4462bab08fcSVikas Chaudhary 		       min(sizeof(ha->ip_config.ipv6_addr0),
4472a49a78eSVikas Chaudhary 			   sizeof(init_fw_cb->ipv6_addr0)));
4482bab08fcSVikas Chaudhary 		memcpy(&ha->ip_config.ipv6_addr1, init_fw_cb->ipv6_addr1,
4492bab08fcSVikas Chaudhary 		       min(sizeof(ha->ip_config.ipv6_addr1),
4502a49a78eSVikas Chaudhary 			   sizeof(init_fw_cb->ipv6_addr1)));
4512bab08fcSVikas Chaudhary 		memcpy(&ha->ip_config.ipv6_default_router_addr,
4522a49a78eSVikas Chaudhary 		       init_fw_cb->ipv6_dflt_rtr_addr,
4532bab08fcSVikas Chaudhary 		       min(sizeof(ha->ip_config.ipv6_default_router_addr),
4542a49a78eSVikas Chaudhary 			   sizeof(init_fw_cb->ipv6_dflt_rtr_addr)));
4556ac73e8cSVikas Chaudhary 		ha->ip_config.ipv6_vlan_tag =
4566ac73e8cSVikas Chaudhary 				be16_to_cpu(init_fw_cb->ipv6_vlan_tag);
4572ada7fc5SVikas Chaudhary 		ha->ip_config.ipv6_port = le16_to_cpu(init_fw_cb->ipv6_port);
4582a49a78eSVikas Chaudhary 	}
4592a49a78eSVikas Chaudhary }
4602a49a78eSVikas Chaudhary 
461d00efe3fSMike Christie uint8_t
4622a49a78eSVikas Chaudhary qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
4632a49a78eSVikas Chaudhary 			  uint32_t *mbox_cmd,
4642a49a78eSVikas Chaudhary 			  uint32_t *mbox_sts,
4652a49a78eSVikas Chaudhary 			  struct addr_ctrl_blk  *init_fw_cb,
4662a49a78eSVikas Chaudhary 			  dma_addr_t init_fw_cb_dma)
4672a49a78eSVikas Chaudhary {
4682a49a78eSVikas Chaudhary 	if (qla4xxx_get_ifcb(ha, mbox_cmd, mbox_sts, init_fw_cb_dma)
4692a49a78eSVikas Chaudhary 	    != QLA_SUCCESS) {
4702a49a78eSVikas Chaudhary 		DEBUG2(printk(KERN_WARNING
4712a49a78eSVikas Chaudhary 			      "scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",
4722a49a78eSVikas Chaudhary 			      ha->host_no, __func__));
4732a49a78eSVikas Chaudhary 		return QLA_ERROR;
4742a49a78eSVikas Chaudhary 	}
4752a49a78eSVikas Chaudhary 
4762a49a78eSVikas Chaudhary 	DEBUG2(qla4xxx_dump_buffer(init_fw_cb, sizeof(struct addr_ctrl_blk)));
4772a49a78eSVikas Chaudhary 
4782a49a78eSVikas Chaudhary 	/* Save some info in adapter structure. */
4792a49a78eSVikas Chaudhary 	ha->acb_version = init_fw_cb->acb_version;
4802a49a78eSVikas Chaudhary 	ha->firmware_options = le16_to_cpu(init_fw_cb->fw_options);
4812a49a78eSVikas Chaudhary 	ha->heartbeat_interval = init_fw_cb->hb_interval;
4822a49a78eSVikas Chaudhary 	memcpy(ha->name_string, init_fw_cb->iscsi_name,
4832a49a78eSVikas Chaudhary 		min(sizeof(ha->name_string),
4842a49a78eSVikas Chaudhary 		sizeof(init_fw_cb->iscsi_name)));
48513483730SMike Christie 	ha->def_timeout = le16_to_cpu(init_fw_cb->def_timeout);
4862a49a78eSVikas Chaudhary 	/*memcpy(ha->alias, init_fw_cb->Alias,
4872a49a78eSVikas Chaudhary 	       min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/
4882a49a78eSVikas Chaudhary 
4892a49a78eSVikas Chaudhary 	qla4xxx_update_local_ip(ha, init_fw_cb);
4902a49a78eSVikas Chaudhary 
4912a49a78eSVikas Chaudhary 	return QLA_SUCCESS;
4922a49a78eSVikas Chaudhary }
4932a49a78eSVikas Chaudhary 
494afaf5a2dSDavid Somayajulu /**
495afaf5a2dSDavid Somayajulu  * qla4xxx_initialize_fw_cb - initializes firmware control block.
496afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
497afaf5a2dSDavid Somayajulu  **/
498afaf5a2dSDavid Somayajulu int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
499afaf5a2dSDavid Somayajulu {
5002a49a78eSVikas Chaudhary 	struct addr_ctrl_blk *init_fw_cb;
501afaf5a2dSDavid Somayajulu 	dma_addr_t init_fw_cb_dma;
502afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
503afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
504afaf5a2dSDavid Somayajulu 	int status = QLA_ERROR;
505afaf5a2dSDavid Somayajulu 
506afaf5a2dSDavid Somayajulu 	init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
5072a49a78eSVikas Chaudhary 					sizeof(struct addr_ctrl_blk),
508afaf5a2dSDavid Somayajulu 					&init_fw_cb_dma, GFP_KERNEL);
509afaf5a2dSDavid Somayajulu 	if (init_fw_cb == NULL) {
510afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n",
511afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__));
512beabe7c1SPrasanna Mumbai 		goto exit_init_fw_cb_no_free;
513afaf5a2dSDavid Somayajulu 	}
5142a49a78eSVikas Chaudhary 	memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
515afaf5a2dSDavid Somayajulu 
516afaf5a2dSDavid Somayajulu 	/* Get Initialize Firmware Control Block. */
517afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
518afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
519c0e344c9SDavid C Somayajulu 
5202a49a78eSVikas Chaudhary 	if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) !=
521afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
522afaf5a2dSDavid Somayajulu 		dma_free_coherent(&ha->pdev->dev,
5232a49a78eSVikas Chaudhary 				  sizeof(struct addr_ctrl_blk),
524afaf5a2dSDavid Somayajulu 				  init_fw_cb, init_fw_cb_dma);
5252a49a78eSVikas Chaudhary 		goto exit_init_fw_cb;
526afaf5a2dSDavid Somayajulu 	}
527afaf5a2dSDavid Somayajulu 
528afaf5a2dSDavid Somayajulu 	/* Initialize request and response queues. */
529afaf5a2dSDavid Somayajulu 	qla4xxx_init_rings(ha);
530afaf5a2dSDavid Somayajulu 
531afaf5a2dSDavid Somayajulu 	/* Fill in the request and response queue information. */
5322a49a78eSVikas Chaudhary 	init_fw_cb->rqq_consumer_idx = cpu_to_le16(ha->request_out);
5332a49a78eSVikas Chaudhary 	init_fw_cb->compq_producer_idx = cpu_to_le16(ha->response_in);
5342a49a78eSVikas Chaudhary 	init_fw_cb->rqq_len = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH);
5352a49a78eSVikas Chaudhary 	init_fw_cb->compq_len = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH);
5362a49a78eSVikas Chaudhary 	init_fw_cb->rqq_addr_lo = cpu_to_le32(LSDW(ha->request_dma));
5372a49a78eSVikas Chaudhary 	init_fw_cb->rqq_addr_hi = cpu_to_le32(MSDW(ha->request_dma));
5382a49a78eSVikas Chaudhary 	init_fw_cb->compq_addr_lo = cpu_to_le32(LSDW(ha->response_dma));
5392a49a78eSVikas Chaudhary 	init_fw_cb->compq_addr_hi = cpu_to_le32(MSDW(ha->response_dma));
5402a49a78eSVikas Chaudhary 	init_fw_cb->shdwreg_addr_lo = cpu_to_le32(LSDW(ha->shadow_regs_dma));
5412a49a78eSVikas Chaudhary 	init_fw_cb->shdwreg_addr_hi = cpu_to_le32(MSDW(ha->shadow_regs_dma));
542afaf5a2dSDavid Somayajulu 
543afaf5a2dSDavid Somayajulu 	/* Set up required options. */
5442a49a78eSVikas Chaudhary 	init_fw_cb->fw_options |=
545afaf5a2dSDavid Somayajulu 		__constant_cpu_to_le16(FWOPT_SESSION_MODE |
546afaf5a2dSDavid Somayajulu 				       FWOPT_INITIATOR_MODE);
5472657c800SShyam Sundar 
5486e7b4292SVikas Chaudhary 	if (is_qla80XX(ha))
5492657c800SShyam Sundar 		init_fw_cb->fw_options |=
5502657c800SShyam Sundar 		    __constant_cpu_to_le16(FWOPT_ENABLE_CRBDB);
5512657c800SShyam Sundar 
5522a49a78eSVikas Chaudhary 	init_fw_cb->fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
553afaf5a2dSDavid Somayajulu 
554d32cee3cSPrasanna Mumbai 	init_fw_cb->add_fw_options = 0;
555d32cee3cSPrasanna Mumbai 	init_fw_cb->add_fw_options |=
556b3a271a9SManish Rangankar 			__constant_cpu_to_le16(ADFWOPT_SERIALIZE_TASK_MGMT);
557b3a271a9SManish Rangankar 	init_fw_cb->add_fw_options |=
558b3a271a9SManish Rangankar 			__constant_cpu_to_le16(ADFWOPT_AUTOCONN_DISABLE);
559d32cee3cSPrasanna Mumbai 
5602a49a78eSVikas Chaudhary 	if (qla4xxx_set_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)
5612a49a78eSVikas Chaudhary 		!= QLA_SUCCESS) {
5622a49a78eSVikas Chaudhary 		DEBUG2(printk(KERN_WARNING
5632a49a78eSVikas Chaudhary 			      "scsi%ld: %s: Failed to set init_fw_ctrl_blk\n",
5642a49a78eSVikas Chaudhary 			      ha->host_no, __func__));
5652a49a78eSVikas Chaudhary 		goto exit_init_fw_cb;
566afaf5a2dSDavid Somayajulu 	}
5672a49a78eSVikas Chaudhary 
5682a49a78eSVikas Chaudhary 	if (qla4xxx_update_local_ifcb(ha, &mbox_cmd[0], &mbox_sts[0],
5692a49a78eSVikas Chaudhary 		init_fw_cb, init_fw_cb_dma) != QLA_SUCCESS) {
5702a49a78eSVikas Chaudhary 		DEBUG2(printk("scsi%ld: %s: Failed to update local ifcb\n",
5712a49a78eSVikas Chaudhary 				ha->host_no, __func__));
5722a49a78eSVikas Chaudhary 		goto exit_init_fw_cb;
5732a49a78eSVikas Chaudhary 	}
5742a49a78eSVikas Chaudhary 	status = QLA_SUCCESS;
5752a49a78eSVikas Chaudhary 
5762a49a78eSVikas Chaudhary exit_init_fw_cb:
5772a49a78eSVikas Chaudhary 	dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
578afaf5a2dSDavid Somayajulu 				init_fw_cb, init_fw_cb_dma);
579beabe7c1SPrasanna Mumbai exit_init_fw_cb_no_free:
580afaf5a2dSDavid Somayajulu 	return status;
581afaf5a2dSDavid Somayajulu }
582afaf5a2dSDavid Somayajulu 
583afaf5a2dSDavid Somayajulu /**
584afaf5a2dSDavid Somayajulu  * qla4xxx_get_dhcp_ip_address - gets HBA ip address via DHCP
585afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
586afaf5a2dSDavid Somayajulu  **/
587afaf5a2dSDavid Somayajulu int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha)
588afaf5a2dSDavid Somayajulu {
5892a49a78eSVikas Chaudhary 	struct addr_ctrl_blk *init_fw_cb;
590afaf5a2dSDavid Somayajulu 	dma_addr_t init_fw_cb_dma;
591afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
592afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
593afaf5a2dSDavid Somayajulu 
594afaf5a2dSDavid Somayajulu 	init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
5952a49a78eSVikas Chaudhary 					sizeof(struct addr_ctrl_blk),
596afaf5a2dSDavid Somayajulu 					&init_fw_cb_dma, GFP_KERNEL);
597afaf5a2dSDavid Somayajulu 	if (init_fw_cb == NULL) {
598afaf5a2dSDavid Somayajulu 		printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no,
599afaf5a2dSDavid Somayajulu 		       __func__);
600beabe7c1SPrasanna Mumbai 		return QLA_ERROR;
601afaf5a2dSDavid Somayajulu 	}
602afaf5a2dSDavid Somayajulu 
603afaf5a2dSDavid Somayajulu 	/* Get Initialize Firmware Control Block. */
6042a49a78eSVikas Chaudhary 	memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
6052a49a78eSVikas Chaudhary 	if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) !=
606afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
607afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",
608afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__));
609afaf5a2dSDavid Somayajulu 		dma_free_coherent(&ha->pdev->dev,
6102a49a78eSVikas Chaudhary 				  sizeof(struct addr_ctrl_blk),
611afaf5a2dSDavid Somayajulu 				  init_fw_cb, init_fw_cb_dma);
612afaf5a2dSDavid Somayajulu 		return QLA_ERROR;
613afaf5a2dSDavid Somayajulu 	}
614afaf5a2dSDavid Somayajulu 
615afaf5a2dSDavid Somayajulu 	/* Save IP Address. */
6162a49a78eSVikas Chaudhary 	qla4xxx_update_local_ip(ha, init_fw_cb);
6172a49a78eSVikas Chaudhary 	dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
618afaf5a2dSDavid Somayajulu 				init_fw_cb, init_fw_cb_dma);
619afaf5a2dSDavid Somayajulu 
620afaf5a2dSDavid Somayajulu 	return QLA_SUCCESS;
621afaf5a2dSDavid Somayajulu }
622afaf5a2dSDavid Somayajulu 
623afaf5a2dSDavid Somayajulu /**
624afaf5a2dSDavid Somayajulu  * qla4xxx_get_firmware_state - gets firmware state of HBA
625afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
626afaf5a2dSDavid Somayajulu  **/
627afaf5a2dSDavid Somayajulu int qla4xxx_get_firmware_state(struct scsi_qla_host * ha)
628afaf5a2dSDavid Somayajulu {
629afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
630afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
631afaf5a2dSDavid Somayajulu 
632afaf5a2dSDavid Somayajulu 	/* Get firmware version */
633afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
634afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
635c0e344c9SDavid C Somayajulu 
636afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_FW_STATE;
637c0e344c9SDavid C Somayajulu 
638c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 4, &mbox_cmd[0], &mbox_sts[0]) !=
639afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
640afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ "
641afaf5a2dSDavid Somayajulu 			      "status %04X\n", ha->host_no, __func__,
642afaf5a2dSDavid Somayajulu 			      mbox_sts[0]));
643afaf5a2dSDavid Somayajulu 		return QLA_ERROR;
644afaf5a2dSDavid Somayajulu 	}
645afaf5a2dSDavid Somayajulu 	ha->firmware_state = mbox_sts[1];
646afaf5a2dSDavid Somayajulu 	ha->board_id = mbox_sts[2];
647afaf5a2dSDavid Somayajulu 	ha->addl_fw_state = mbox_sts[3];
648afaf5a2dSDavid Somayajulu 	DEBUG2(printk("scsi%ld: %s firmware_state=0x%x\n",
649afaf5a2dSDavid Somayajulu 		      ha->host_no, __func__, ha->firmware_state);)
650afaf5a2dSDavid Somayajulu 
651afaf5a2dSDavid Somayajulu 	return QLA_SUCCESS;
652afaf5a2dSDavid Somayajulu }
653afaf5a2dSDavid Somayajulu 
654afaf5a2dSDavid Somayajulu /**
655afaf5a2dSDavid Somayajulu  * qla4xxx_get_firmware_status - retrieves firmware status
656afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
657afaf5a2dSDavid Somayajulu  **/
658afaf5a2dSDavid Somayajulu int qla4xxx_get_firmware_status(struct scsi_qla_host * ha)
659afaf5a2dSDavid Somayajulu {
660afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
661afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
662afaf5a2dSDavid Somayajulu 
663afaf5a2dSDavid Somayajulu 	/* Get firmware version */
664afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
665afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
666c0e344c9SDavid C Somayajulu 
667afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS;
668c0e344c9SDavid C Somayajulu 
669c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) !=
670afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
671afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ "
672afaf5a2dSDavid Somayajulu 			      "status %04X\n", ha->host_no, __func__,
673afaf5a2dSDavid Somayajulu 			      mbox_sts[0]));
674afaf5a2dSDavid Somayajulu 		return QLA_ERROR;
675afaf5a2dSDavid Somayajulu 	}
676f4f5df23SVikas Chaudhary 
6773573bfb2SVikas Chaudhary 	ql4_printk(KERN_INFO, ha, "%ld firmware IOCBs available (%d).\n",
678f581a3f7SVikas Chaudhary 	    ha->host_no, mbox_sts[2]);
679f4f5df23SVikas Chaudhary 
680afaf5a2dSDavid Somayajulu 	return QLA_SUCCESS;
681afaf5a2dSDavid Somayajulu }
682afaf5a2dSDavid Somayajulu 
683afaf5a2dSDavid Somayajulu /**
684afaf5a2dSDavid Somayajulu  * qla4xxx_get_fwddb_entry - retrieves firmware ddb entry
685afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
686afaf5a2dSDavid Somayajulu  * @fw_ddb_index: Firmware's device database index
687afaf5a2dSDavid Somayajulu  * @fw_ddb_entry: Pointer to firmware's device database entry structure
688afaf5a2dSDavid Somayajulu  * @num_valid_ddb_entries: Pointer to number of valid ddb entries
689afaf5a2dSDavid Somayajulu  * @next_ddb_index: Pointer to next valid device database index
690afaf5a2dSDavid Somayajulu  * @fw_ddb_device_state: Pointer to device state
691afaf5a2dSDavid Somayajulu  **/
692afaf5a2dSDavid Somayajulu int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
693afaf5a2dSDavid Somayajulu 			    uint16_t fw_ddb_index,
694afaf5a2dSDavid Somayajulu 			    struct dev_db_entry *fw_ddb_entry,
695afaf5a2dSDavid Somayajulu 			    dma_addr_t fw_ddb_entry_dma,
696afaf5a2dSDavid Somayajulu 			    uint32_t *num_valid_ddb_entries,
697afaf5a2dSDavid Somayajulu 			    uint32_t *next_ddb_index,
698afaf5a2dSDavid Somayajulu 			    uint32_t *fw_ddb_device_state,
699afaf5a2dSDavid Somayajulu 			    uint32_t *conn_err_detail,
700afaf5a2dSDavid Somayajulu 			    uint16_t *tcp_source_port_num,
701afaf5a2dSDavid Somayajulu 			    uint16_t *connection_id)
702afaf5a2dSDavid Somayajulu {
703afaf5a2dSDavid Somayajulu 	int status = QLA_ERROR;
7042a49a78eSVikas Chaudhary 	uint16_t options;
705afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
706afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
707afaf5a2dSDavid Somayajulu 
708afaf5a2dSDavid Somayajulu 	/* Make sure the device index is valid */
709afaf5a2dSDavid Somayajulu 	if (fw_ddb_index >= MAX_DDB_ENTRIES) {
710f4f5df23SVikas Chaudhary 		DEBUG2(printk("scsi%ld: %s: ddb [%d] out of range.\n",
711afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__, fw_ddb_index));
712afaf5a2dSDavid Somayajulu 		goto exit_get_fwddb;
713afaf5a2dSDavid Somayajulu 	}
714afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
715afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
716981c982cSLalit Chandivade 	if (fw_ddb_entry)
717981c982cSLalit Chandivade 		memset(fw_ddb_entry, 0, sizeof(struct dev_db_entry));
718c0e344c9SDavid C Somayajulu 
719afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY;
720afaf5a2dSDavid Somayajulu 	mbox_cmd[1] = (uint32_t) fw_ddb_index;
721afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
722afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
723c0e344c9SDavid C Somayajulu 	mbox_cmd[4] = sizeof(struct dev_db_entry);
724c0e344c9SDavid C Somayajulu 
725c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 7, &mbox_cmd[0], &mbox_sts[0]) ==
726afaf5a2dSDavid Somayajulu 	    QLA_ERROR) {
727afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed"
728afaf5a2dSDavid Somayajulu 			      " with status 0x%04X\n", ha->host_no, __func__,
729afaf5a2dSDavid Somayajulu 			      mbox_sts[0]));
730afaf5a2dSDavid Somayajulu 		goto exit_get_fwddb;
731afaf5a2dSDavid Somayajulu 	}
732afaf5a2dSDavid Somayajulu 	if (fw_ddb_index != mbox_sts[1]) {
733f4f5df23SVikas Chaudhary 		DEBUG2(printk("scsi%ld: %s: ddb mismatch [%d] != [%d].\n",
734afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__, fw_ddb_index,
735afaf5a2dSDavid Somayajulu 			      mbox_sts[1]));
736afaf5a2dSDavid Somayajulu 		goto exit_get_fwddb;
737afaf5a2dSDavid Somayajulu 	}
738afaf5a2dSDavid Somayajulu 	if (fw_ddb_entry) {
7392a49a78eSVikas Chaudhary 		options = le16_to_cpu(fw_ddb_entry->options);
7402a49a78eSVikas Chaudhary 		if (options & DDB_OPT_IPV6_DEVICE) {
741c2660df3SVikas Chaudhary 			ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d "
7422a49a78eSVikas Chaudhary 				"Next %d State %04x ConnErr %08x %pI6 "
7432a49a78eSVikas Chaudhary 				":%04d \"%s\"\n", __func__, fw_ddb_index,
7442a49a78eSVikas Chaudhary 				mbox_sts[0], mbox_sts[2], mbox_sts[3],
7452a49a78eSVikas Chaudhary 				mbox_sts[4], mbox_sts[5],
7462a49a78eSVikas Chaudhary 				fw_ddb_entry->ip_addr,
747c0e344c9SDavid C Somayajulu 				le16_to_cpu(fw_ddb_entry->port),
748c0e344c9SDavid C Somayajulu 				fw_ddb_entry->iscsi_name);
7492a49a78eSVikas Chaudhary 		} else {
750c2660df3SVikas Chaudhary 			ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d "
7512a49a78eSVikas Chaudhary 				"Next %d State %04x ConnErr %08x %pI4 "
7522a49a78eSVikas Chaudhary 				":%04d \"%s\"\n", __func__, fw_ddb_index,
7532a49a78eSVikas Chaudhary 				mbox_sts[0], mbox_sts[2], mbox_sts[3],
7542a49a78eSVikas Chaudhary 				mbox_sts[4], mbox_sts[5],
7552a49a78eSVikas Chaudhary 				fw_ddb_entry->ip_addr,
7562a49a78eSVikas Chaudhary 				le16_to_cpu(fw_ddb_entry->port),
7572a49a78eSVikas Chaudhary 				fw_ddb_entry->iscsi_name);
7582a49a78eSVikas Chaudhary 		}
759afaf5a2dSDavid Somayajulu 	}
760afaf5a2dSDavid Somayajulu 	if (num_valid_ddb_entries)
761afaf5a2dSDavid Somayajulu 		*num_valid_ddb_entries = mbox_sts[2];
762afaf5a2dSDavid Somayajulu 	if (next_ddb_index)
763afaf5a2dSDavid Somayajulu 		*next_ddb_index = mbox_sts[3];
764afaf5a2dSDavid Somayajulu 	if (fw_ddb_device_state)
765afaf5a2dSDavid Somayajulu 		*fw_ddb_device_state = mbox_sts[4];
766afaf5a2dSDavid Somayajulu 
767afaf5a2dSDavid Somayajulu 	/*
768afaf5a2dSDavid Somayajulu 	 * RA: This mailbox has been changed to pass connection error and
769afaf5a2dSDavid Somayajulu 	 * details.  Its true for ISP4010 as per Version E - Not sure when it
770afaf5a2dSDavid Somayajulu 	 * was changed.	 Get the time2wait from the fw_dd_entry field :
771afaf5a2dSDavid Somayajulu 	 * default_time2wait which we call it as minTime2Wait DEV_DB_ENTRY
772afaf5a2dSDavid Somayajulu 	 * struct.
773afaf5a2dSDavid Somayajulu 	 */
774afaf5a2dSDavid Somayajulu 	if (conn_err_detail)
775afaf5a2dSDavid Somayajulu 		*conn_err_detail = mbox_sts[5];
776afaf5a2dSDavid Somayajulu 	if (tcp_source_port_num)
7771482338fSRandy Dunlap 		*tcp_source_port_num = (uint16_t) (mbox_sts[6] >> 16);
778afaf5a2dSDavid Somayajulu 	if (connection_id)
779afaf5a2dSDavid Somayajulu 		*connection_id = (uint16_t) mbox_sts[6] & 0x00FF;
780afaf5a2dSDavid Somayajulu 	status = QLA_SUCCESS;
781afaf5a2dSDavid Somayajulu 
782afaf5a2dSDavid Somayajulu exit_get_fwddb:
783afaf5a2dSDavid Somayajulu 	return status;
784afaf5a2dSDavid Somayajulu }
785afaf5a2dSDavid Somayajulu 
786b3a271a9SManish Rangankar int qla4xxx_conn_open(struct scsi_qla_host *ha, uint16_t fw_ddb_index)
787b3a271a9SManish Rangankar {
788b3a271a9SManish Rangankar 	uint32_t mbox_cmd[MBOX_REG_COUNT];
789b3a271a9SManish Rangankar 	uint32_t mbox_sts[MBOX_REG_COUNT];
790b3a271a9SManish Rangankar 	int status;
791b3a271a9SManish Rangankar 
792b3a271a9SManish Rangankar 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
793b3a271a9SManish Rangankar 	memset(&mbox_sts, 0, sizeof(mbox_sts));
794b3a271a9SManish Rangankar 
795b3a271a9SManish Rangankar 	mbox_cmd[0] = MBOX_CMD_CONN_OPEN;
796b3a271a9SManish Rangankar 	mbox_cmd[1] = fw_ddb_index;
797b3a271a9SManish Rangankar 
798b3a271a9SManish Rangankar 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
799b3a271a9SManish Rangankar 					 &mbox_sts[0]);
800b3a271a9SManish Rangankar 	DEBUG2(ql4_printk(KERN_INFO, ha,
801b3a271a9SManish Rangankar 			  "%s: status = %d mbx0 = 0x%x mbx1 = 0x%x\n",
802b3a271a9SManish Rangankar 			  __func__, status, mbox_sts[0], mbox_sts[1]));
803b3a271a9SManish Rangankar 	return status;
804b3a271a9SManish Rangankar }
805b3a271a9SManish Rangankar 
806afaf5a2dSDavid Somayajulu /**
807afaf5a2dSDavid Somayajulu  * qla4xxx_set_fwddb_entry - sets a ddb entry.
808afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
809afaf5a2dSDavid Somayajulu  * @fw_ddb_index: Firmware's device database index
810b3a271a9SManish Rangankar  * @fw_ddb_entry_dma: dma address of ddb entry
811b3a271a9SManish Rangankar  * @mbx_sts: mailbox 0 to be returned or NULL
812afaf5a2dSDavid Somayajulu  *
813afaf5a2dSDavid Somayajulu  * This routine initializes or updates the adapter's device database
814b3a271a9SManish Rangankar  * entry for the specified device.
815afaf5a2dSDavid Somayajulu  **/
816afaf5a2dSDavid Somayajulu int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
817b3a271a9SManish Rangankar 			  dma_addr_t fw_ddb_entry_dma, uint32_t *mbx_sts)
818afaf5a2dSDavid Somayajulu {
819afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
820afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
821f4f5df23SVikas Chaudhary 	int status;
822afaf5a2dSDavid Somayajulu 
823afaf5a2dSDavid Somayajulu 	/* Do not wait for completion. The firmware will send us an
824afaf5a2dSDavid Somayajulu 	 * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status.
825afaf5a2dSDavid Somayajulu 	 */
826afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
827afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
828afaf5a2dSDavid Somayajulu 
829afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_SET_DATABASE_ENTRY;
830afaf5a2dSDavid Somayajulu 	mbox_cmd[1] = (uint32_t) fw_ddb_index;
831afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
832afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
833c0e344c9SDavid C Somayajulu 	mbox_cmd[4] = sizeof(struct dev_db_entry);
834c0e344c9SDavid C Somayajulu 
835f4f5df23SVikas Chaudhary 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0],
836f4f5df23SVikas Chaudhary 					 &mbox_sts[0]);
837b3a271a9SManish Rangankar 	if (mbx_sts)
838b3a271a9SManish Rangankar 		*mbx_sts = mbox_sts[0];
839f4f5df23SVikas Chaudhary 	DEBUG2(printk("scsi%ld: %s: status=%d mbx0=0x%x mbx4=0x%x\n",
840f4f5df23SVikas Chaudhary 	    ha->host_no, __func__, status, mbox_sts[0], mbox_sts[4]);)
841f4f5df23SVikas Chaudhary 
842f4f5df23SVikas Chaudhary 	return status;
843afaf5a2dSDavid Somayajulu }
844afaf5a2dSDavid Somayajulu 
845b3a271a9SManish Rangankar int qla4xxx_session_logout_ddb(struct scsi_qla_host *ha,
846b3a271a9SManish Rangankar 			       struct ddb_entry *ddb_entry, int options)
847b3a271a9SManish Rangankar {
848b3a271a9SManish Rangankar 	int status;
849b3a271a9SManish Rangankar 	uint32_t mbox_cmd[MBOX_REG_COUNT];
850b3a271a9SManish Rangankar 	uint32_t mbox_sts[MBOX_REG_COUNT];
851b3a271a9SManish Rangankar 
852b3a271a9SManish Rangankar 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
853b3a271a9SManish Rangankar 	memset(&mbox_sts, 0, sizeof(mbox_sts));
854b3a271a9SManish Rangankar 
855b3a271a9SManish Rangankar 	mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
856b3a271a9SManish Rangankar 	mbox_cmd[1] = ddb_entry->fw_ddb_index;
857b3a271a9SManish Rangankar 	mbox_cmd[3] = options;
858b3a271a9SManish Rangankar 
859b3a271a9SManish Rangankar 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
860b3a271a9SManish Rangankar 					 &mbox_sts[0]);
861b3a271a9SManish Rangankar 	if (status != QLA_SUCCESS) {
862b3a271a9SManish Rangankar 		DEBUG2(ql4_printk(KERN_INFO, ha,
863b3a271a9SManish Rangankar 				  "%s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
864b3a271a9SManish Rangankar 				  "failed sts %04X %04X", __func__,
865b3a271a9SManish Rangankar 				  mbox_sts[0], mbox_sts[1]));
866b3a271a9SManish Rangankar 	}
867b3a271a9SManish Rangankar 
868b3a271a9SManish Rangankar 	return status;
869b3a271a9SManish Rangankar }
870b3a271a9SManish Rangankar 
871afaf5a2dSDavid Somayajulu /**
872afaf5a2dSDavid Somayajulu  * qla4xxx_get_crash_record - retrieves crash record.
873afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
874afaf5a2dSDavid Somayajulu  *
875afaf5a2dSDavid Somayajulu  * This routine retrieves a crash record from the QLA4010 after an 8002h aen.
876afaf5a2dSDavid Somayajulu  **/
877afaf5a2dSDavid Somayajulu void qla4xxx_get_crash_record(struct scsi_qla_host * ha)
878afaf5a2dSDavid Somayajulu {
879afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
880afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
881afaf5a2dSDavid Somayajulu 	struct crash_record *crash_record = NULL;
882afaf5a2dSDavid Somayajulu 	dma_addr_t crash_record_dma = 0;
883afaf5a2dSDavid Somayajulu 	uint32_t crash_record_size = 0;
884c0e344c9SDavid C Somayajulu 
885afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
886afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_cmd));
887afaf5a2dSDavid Somayajulu 
888afaf5a2dSDavid Somayajulu 	/* Get size of crash record. */
889afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
890c0e344c9SDavid C Somayajulu 
891c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
892afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
893afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n",
894afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__));
895afaf5a2dSDavid Somayajulu 		goto exit_get_crash_record;
896afaf5a2dSDavid Somayajulu 	}
897afaf5a2dSDavid Somayajulu 	crash_record_size = mbox_sts[4];
898afaf5a2dSDavid Somayajulu 	if (crash_record_size == 0) {
899afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: ERROR: Crash record size is 0!\n",
900afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__));
901afaf5a2dSDavid Somayajulu 		goto exit_get_crash_record;
902afaf5a2dSDavid Somayajulu 	}
903afaf5a2dSDavid Somayajulu 
904afaf5a2dSDavid Somayajulu 	/* Alloc Memory for Crash Record. */
905afaf5a2dSDavid Somayajulu 	crash_record = dma_alloc_coherent(&ha->pdev->dev, crash_record_size,
906afaf5a2dSDavid Somayajulu 					  &crash_record_dma, GFP_KERNEL);
907afaf5a2dSDavid Somayajulu 	if (crash_record == NULL)
908afaf5a2dSDavid Somayajulu 		goto exit_get_crash_record;
909afaf5a2dSDavid Somayajulu 
910afaf5a2dSDavid Somayajulu 	/* Get Crash Record. */
911c0e344c9SDavid C Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
912c0e344c9SDavid C Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_cmd));
913c0e344c9SDavid C Somayajulu 
914afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
915afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = LSDW(crash_record_dma);
916afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = MSDW(crash_record_dma);
917afaf5a2dSDavid Somayajulu 	mbox_cmd[4] = crash_record_size;
918c0e344c9SDavid C Somayajulu 
919c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
920afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS)
921afaf5a2dSDavid Somayajulu 		goto exit_get_crash_record;
922afaf5a2dSDavid Somayajulu 
923afaf5a2dSDavid Somayajulu 	/* Dump Crash Record. */
924afaf5a2dSDavid Somayajulu 
925afaf5a2dSDavid Somayajulu exit_get_crash_record:
926afaf5a2dSDavid Somayajulu 	if (crash_record)
927afaf5a2dSDavid Somayajulu 		dma_free_coherent(&ha->pdev->dev, crash_record_size,
928afaf5a2dSDavid Somayajulu 				  crash_record, crash_record_dma);
929afaf5a2dSDavid Somayajulu }
930afaf5a2dSDavid Somayajulu 
931afaf5a2dSDavid Somayajulu /**
932afaf5a2dSDavid Somayajulu  * qla4xxx_get_conn_event_log - retrieves connection event log
933afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
934afaf5a2dSDavid Somayajulu  **/
935afaf5a2dSDavid Somayajulu void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha)
936afaf5a2dSDavid Somayajulu {
937afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
938afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
939afaf5a2dSDavid Somayajulu 	struct conn_event_log_entry *event_log = NULL;
940afaf5a2dSDavid Somayajulu 	dma_addr_t event_log_dma = 0;
941afaf5a2dSDavid Somayajulu 	uint32_t event_log_size = 0;
942afaf5a2dSDavid Somayajulu 	uint32_t num_valid_entries;
943afaf5a2dSDavid Somayajulu 	uint32_t      oldest_entry = 0;
944afaf5a2dSDavid Somayajulu 	uint32_t	max_event_log_entries;
945afaf5a2dSDavid Somayajulu 	uint8_t		i;
946afaf5a2dSDavid Somayajulu 
947afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
948afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_cmd));
949afaf5a2dSDavid Somayajulu 
950afaf5a2dSDavid Somayajulu 	/* Get size of crash record. */
951afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
952c0e344c9SDavid C Somayajulu 
953c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
954afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS)
955afaf5a2dSDavid Somayajulu 		goto exit_get_event_log;
956afaf5a2dSDavid Somayajulu 
957afaf5a2dSDavid Somayajulu 	event_log_size = mbox_sts[4];
958afaf5a2dSDavid Somayajulu 	if (event_log_size == 0)
959afaf5a2dSDavid Somayajulu 		goto exit_get_event_log;
960afaf5a2dSDavid Somayajulu 
961afaf5a2dSDavid Somayajulu 	/* Alloc Memory for Crash Record. */
962afaf5a2dSDavid Somayajulu 	event_log = dma_alloc_coherent(&ha->pdev->dev, event_log_size,
963afaf5a2dSDavid Somayajulu 				       &event_log_dma, GFP_KERNEL);
964afaf5a2dSDavid Somayajulu 	if (event_log == NULL)
965afaf5a2dSDavid Somayajulu 		goto exit_get_event_log;
966afaf5a2dSDavid Somayajulu 
967afaf5a2dSDavid Somayajulu 	/* Get Crash Record. */
968c0e344c9SDavid C Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
969c0e344c9SDavid C Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_cmd));
970c0e344c9SDavid C Somayajulu 
971afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
972afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = LSDW(event_log_dma);
973afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = MSDW(event_log_dma);
974c0e344c9SDavid C Somayajulu 
975c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
976afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
977afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event "
978afaf5a2dSDavid Somayajulu 			      "log!\n", ha->host_no, __func__));
979afaf5a2dSDavid Somayajulu 		goto exit_get_event_log;
980afaf5a2dSDavid Somayajulu 	}
981afaf5a2dSDavid Somayajulu 
982afaf5a2dSDavid Somayajulu 	/* Dump Event Log. */
983afaf5a2dSDavid Somayajulu 	num_valid_entries = mbox_sts[1];
984afaf5a2dSDavid Somayajulu 
985afaf5a2dSDavid Somayajulu 	max_event_log_entries = event_log_size /
986afaf5a2dSDavid Somayajulu 		sizeof(struct conn_event_log_entry);
987afaf5a2dSDavid Somayajulu 
988afaf5a2dSDavid Somayajulu 	if (num_valid_entries > max_event_log_entries)
989afaf5a2dSDavid Somayajulu 		oldest_entry = num_valid_entries % max_event_log_entries;
990afaf5a2dSDavid Somayajulu 
991afaf5a2dSDavid Somayajulu 	DEBUG3(printk("scsi%ld: Connection Event Log Dump (%d entries):\n",
992afaf5a2dSDavid Somayajulu 		      ha->host_no, num_valid_entries));
993afaf5a2dSDavid Somayajulu 
99411010fecSAndrew Vasquez 	if (ql4xextended_error_logging == 3) {
995afaf5a2dSDavid Somayajulu 		if (oldest_entry == 0) {
996afaf5a2dSDavid Somayajulu 			/* Circular Buffer has not wrapped around */
997afaf5a2dSDavid Somayajulu 			for (i=0; i < num_valid_entries; i++) {
998afaf5a2dSDavid Somayajulu 				qla4xxx_dump_buffer((uint8_t *)event_log+
999afaf5a2dSDavid Somayajulu 						    (i*sizeof(*event_log)),
1000afaf5a2dSDavid Somayajulu 						    sizeof(*event_log));
1001afaf5a2dSDavid Somayajulu 			}
1002afaf5a2dSDavid Somayajulu 		}
1003afaf5a2dSDavid Somayajulu 		else {
1004afaf5a2dSDavid Somayajulu 			/* Circular Buffer has wrapped around -
1005afaf5a2dSDavid Somayajulu 			 * display accordingly*/
1006afaf5a2dSDavid Somayajulu 			for (i=oldest_entry; i < max_event_log_entries; i++) {
1007afaf5a2dSDavid Somayajulu 				qla4xxx_dump_buffer((uint8_t *)event_log+
1008afaf5a2dSDavid Somayajulu 						    (i*sizeof(*event_log)),
1009afaf5a2dSDavid Somayajulu 						    sizeof(*event_log));
1010afaf5a2dSDavid Somayajulu 			}
1011afaf5a2dSDavid Somayajulu 			for (i=0; i < oldest_entry; i++) {
1012afaf5a2dSDavid Somayajulu 				qla4xxx_dump_buffer((uint8_t *)event_log+
1013afaf5a2dSDavid Somayajulu 						    (i*sizeof(*event_log)),
1014afaf5a2dSDavid Somayajulu 						    sizeof(*event_log));
1015afaf5a2dSDavid Somayajulu 			}
1016afaf5a2dSDavid Somayajulu 		}
1017afaf5a2dSDavid Somayajulu 	}
1018afaf5a2dSDavid Somayajulu 
1019afaf5a2dSDavid Somayajulu exit_get_event_log:
1020afaf5a2dSDavid Somayajulu 	if (event_log)
1021afaf5a2dSDavid Somayajulu 		dma_free_coherent(&ha->pdev->dev, event_log_size, event_log,
1022afaf5a2dSDavid Somayajulu 				  event_log_dma);
1023afaf5a2dSDavid Somayajulu }
1024afaf5a2dSDavid Somayajulu 
1025afaf5a2dSDavid Somayajulu /**
102609a0f719SVikas Chaudhary  * qla4xxx_abort_task - issues Abort Task
102709a0f719SVikas Chaudhary  * @ha: Pointer to host adapter structure.
102809a0f719SVikas Chaudhary  * @srb: Pointer to srb entry
102909a0f719SVikas Chaudhary  *
103009a0f719SVikas Chaudhary  * This routine performs a LUN RESET on the specified target/lun.
103109a0f719SVikas Chaudhary  * The caller must ensure that the ddb_entry and lun_entry pointers
103209a0f719SVikas Chaudhary  * are valid before calling this routine.
103309a0f719SVikas Chaudhary  **/
103409a0f719SVikas Chaudhary int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb)
103509a0f719SVikas Chaudhary {
103609a0f719SVikas Chaudhary 	uint32_t mbox_cmd[MBOX_REG_COUNT];
103709a0f719SVikas Chaudhary 	uint32_t mbox_sts[MBOX_REG_COUNT];
103809a0f719SVikas Chaudhary 	struct scsi_cmnd *cmd = srb->cmd;
103909a0f719SVikas Chaudhary 	int status = QLA_SUCCESS;
104009a0f719SVikas Chaudhary 	unsigned long flags = 0;
104109a0f719SVikas Chaudhary 	uint32_t index;
104209a0f719SVikas Chaudhary 
104309a0f719SVikas Chaudhary 	/*
104409a0f719SVikas Chaudhary 	 * Send abort task command to ISP, so that the ISP will return
104509a0f719SVikas Chaudhary 	 * request with ABORT status
104609a0f719SVikas Chaudhary 	 */
104709a0f719SVikas Chaudhary 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
104809a0f719SVikas Chaudhary 	memset(&mbox_sts, 0, sizeof(mbox_sts));
104909a0f719SVikas Chaudhary 
105009a0f719SVikas Chaudhary 	spin_lock_irqsave(&ha->hardware_lock, flags);
105109a0f719SVikas Chaudhary 	index = (unsigned long)(unsigned char *)cmd->host_scribble;
105209a0f719SVikas Chaudhary 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
105309a0f719SVikas Chaudhary 
105409a0f719SVikas Chaudhary 	/* Firmware already posted completion on response queue */
105509a0f719SVikas Chaudhary 	if (index == MAX_SRBS)
105609a0f719SVikas Chaudhary 		return status;
105709a0f719SVikas Chaudhary 
105809a0f719SVikas Chaudhary 	mbox_cmd[0] = MBOX_CMD_ABORT_TASK;
10596790d4feSKaren Higgins 	mbox_cmd[1] = srb->ddb->fw_ddb_index;
106009a0f719SVikas Chaudhary 	mbox_cmd[2] = index;
106109a0f719SVikas Chaudhary 	/* Immediate Command Enable */
106209a0f719SVikas Chaudhary 	mbox_cmd[5] = 0x01;
106309a0f719SVikas Chaudhary 
106409a0f719SVikas Chaudhary 	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0],
106509a0f719SVikas Chaudhary 	    &mbox_sts[0]);
106609a0f719SVikas Chaudhary 	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE) {
106709a0f719SVikas Chaudhary 		status = QLA_ERROR;
106809a0f719SVikas Chaudhary 
106909a0f719SVikas Chaudhary 		DEBUG2(printk(KERN_WARNING "scsi%ld:%d:%d: abort task FAILED: "
107009a0f719SVikas Chaudhary 		    "mbx0=%04X, mb1=%04X, mb2=%04X, mb3=%04X, mb4=%04X\n",
107109a0f719SVikas Chaudhary 		    ha->host_no, cmd->device->id, cmd->device->lun, mbox_sts[0],
107209a0f719SVikas Chaudhary 		    mbox_sts[1], mbox_sts[2], mbox_sts[3], mbox_sts[4]));
107309a0f719SVikas Chaudhary 	}
107409a0f719SVikas Chaudhary 
107509a0f719SVikas Chaudhary 	return status;
107609a0f719SVikas Chaudhary }
107709a0f719SVikas Chaudhary 
107809a0f719SVikas Chaudhary /**
1079afaf5a2dSDavid Somayajulu  * qla4xxx_reset_lun - issues LUN Reset
1080afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
1081f4f5df23SVikas Chaudhary  * @ddb_entry: Pointer to device database entry
1082f4f5df23SVikas Chaudhary  * @lun: lun number
1083afaf5a2dSDavid Somayajulu  *
1084afaf5a2dSDavid Somayajulu  * This routine performs a LUN RESET on the specified target/lun.
1085afaf5a2dSDavid Somayajulu  * The caller must ensure that the ddb_entry and lun_entry pointers
1086afaf5a2dSDavid Somayajulu  * are valid before calling this routine.
1087afaf5a2dSDavid Somayajulu  **/
1088afaf5a2dSDavid Somayajulu int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
1089afaf5a2dSDavid Somayajulu 		      int lun)
1090afaf5a2dSDavid Somayajulu {
1091afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1092afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
1093afaf5a2dSDavid Somayajulu 	int status = QLA_SUCCESS;
1094afaf5a2dSDavid Somayajulu 
1095afaf5a2dSDavid Somayajulu 	DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no,
1096f4f5df23SVikas Chaudhary 		      ddb_entry->fw_ddb_index, lun));
1097afaf5a2dSDavid Somayajulu 
1098afaf5a2dSDavid Somayajulu 	/*
1099afaf5a2dSDavid Somayajulu 	 * Send lun reset command to ISP, so that the ISP will return all
1100afaf5a2dSDavid Somayajulu 	 * outstanding requests with RESET status
1101afaf5a2dSDavid Somayajulu 	 */
1102afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1103afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1104c0e344c9SDavid C Somayajulu 
1105afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_LUN_RESET;
1106afaf5a2dSDavid Somayajulu 	mbox_cmd[1] = ddb_entry->fw_ddb_index;
1107afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = lun << 8;
1108afaf5a2dSDavid Somayajulu 	mbox_cmd[5] = 0x01;	/* Immediate Command Enable */
1109c0e344c9SDavid C Somayajulu 
1110c0e344c9SDavid C Somayajulu 	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]);
1111afaf5a2dSDavid Somayajulu 	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
1112afaf5a2dSDavid Somayajulu 	    mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
1113afaf5a2dSDavid Somayajulu 		status = QLA_ERROR;
1114afaf5a2dSDavid Somayajulu 
1115afaf5a2dSDavid Somayajulu 	return status;
1116afaf5a2dSDavid Somayajulu }
1117afaf5a2dSDavid Somayajulu 
1118ce545039SMike Christie /**
1119ce545039SMike Christie  * qla4xxx_reset_target - issues target Reset
1120ce545039SMike Christie  * @ha: Pointer to host adapter structure.
1121ce545039SMike Christie  * @db_entry: Pointer to device database entry
1122ce545039SMike Christie  * @un_entry: Pointer to lun entry structure
1123ce545039SMike Christie  *
1124ce545039SMike Christie  * This routine performs a TARGET RESET on the specified target.
1125ce545039SMike Christie  * The caller must ensure that the ddb_entry pointers
1126ce545039SMike Christie  * are valid before calling this routine.
1127ce545039SMike Christie  **/
1128ce545039SMike Christie int qla4xxx_reset_target(struct scsi_qla_host *ha,
1129ce545039SMike Christie 			 struct ddb_entry *ddb_entry)
1130ce545039SMike Christie {
1131ce545039SMike Christie 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1132ce545039SMike Christie 	uint32_t mbox_sts[MBOX_REG_COUNT];
1133ce545039SMike Christie 	int status = QLA_SUCCESS;
1134ce545039SMike Christie 
1135ce545039SMike Christie 	DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no,
1136f4f5df23SVikas Chaudhary 		      ddb_entry->fw_ddb_index));
1137ce545039SMike Christie 
1138ce545039SMike Christie 	/*
1139ce545039SMike Christie 	 * Send target reset command to ISP, so that the ISP will return all
1140ce545039SMike Christie 	 * outstanding requests with RESET status
1141ce545039SMike Christie 	 */
1142ce545039SMike Christie 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1143ce545039SMike Christie 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1144ce545039SMike Christie 
1145ce545039SMike Christie 	mbox_cmd[0] = MBOX_CMD_TARGET_WARM_RESET;
1146ce545039SMike Christie 	mbox_cmd[1] = ddb_entry->fw_ddb_index;
1147ce545039SMike Christie 	mbox_cmd[5] = 0x01;	/* Immediate Command Enable */
1148ce545039SMike Christie 
1149ce545039SMike Christie 	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
1150ce545039SMike Christie 				&mbox_sts[0]);
1151ce545039SMike Christie 	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
1152ce545039SMike Christie 	    mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
1153ce545039SMike Christie 		status = QLA_ERROR;
1154ce545039SMike Christie 
1155ce545039SMike Christie 	return status;
1156ce545039SMike Christie }
1157afaf5a2dSDavid Somayajulu 
1158afaf5a2dSDavid Somayajulu int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
1159afaf5a2dSDavid Somayajulu 		      uint32_t offset, uint32_t len)
1160afaf5a2dSDavid Somayajulu {
1161afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1162afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
1163afaf5a2dSDavid Somayajulu 
1164afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1165afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1166c0e344c9SDavid C Somayajulu 
1167afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_READ_FLASH;
1168afaf5a2dSDavid Somayajulu 	mbox_cmd[1] = LSDW(dma_addr);
1169afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = MSDW(dma_addr);
1170afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = offset;
1171afaf5a2dSDavid Somayajulu 	mbox_cmd[4] = len;
1172c0e344c9SDavid C Somayajulu 
1173c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], &mbox_sts[0]) !=
1174afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
1175afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ "
1176afaf5a2dSDavid Somayajulu 		    "status %04X %04X, offset %08x, len %08x\n", ha->host_no,
1177afaf5a2dSDavid Somayajulu 		    __func__, mbox_sts[0], mbox_sts[1], offset, len));
1178afaf5a2dSDavid Somayajulu 		return QLA_ERROR;
1179afaf5a2dSDavid Somayajulu 	}
1180afaf5a2dSDavid Somayajulu 	return QLA_SUCCESS;
1181afaf5a2dSDavid Somayajulu }
1182afaf5a2dSDavid Somayajulu 
1183afaf5a2dSDavid Somayajulu /**
11847ad633c0SHarish Zunjarrao  * qla4xxx_about_firmware - gets FW, iscsi draft and boot loader version
1185afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
1186afaf5a2dSDavid Somayajulu  *
11877ad633c0SHarish Zunjarrao  * Retrieves the FW version, iSCSI draft version & bootloader version of HBA.
11887ad633c0SHarish Zunjarrao  * Mailboxes 2 & 3 may hold an address for data. Make sure that we write 0 to
11897ad633c0SHarish Zunjarrao  * those mailboxes, if unused.
1190afaf5a2dSDavid Somayajulu  **/
11917ad633c0SHarish Zunjarrao int qla4xxx_about_firmware(struct scsi_qla_host *ha)
1192afaf5a2dSDavid Somayajulu {
11937ad633c0SHarish Zunjarrao 	struct about_fw_info *about_fw = NULL;
11947ad633c0SHarish Zunjarrao 	dma_addr_t about_fw_dma;
1195afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1196afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
11977ad633c0SHarish Zunjarrao 	int status = QLA_ERROR;
1198afaf5a2dSDavid Somayajulu 
11997ad633c0SHarish Zunjarrao 	about_fw = dma_alloc_coherent(&ha->pdev->dev,
12007ad633c0SHarish Zunjarrao 				      sizeof(struct about_fw_info),
12017ad633c0SHarish Zunjarrao 				      &about_fw_dma, GFP_KERNEL);
12027ad633c0SHarish Zunjarrao 	if (!about_fw) {
12037ad633c0SHarish Zunjarrao 		DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Unable to alloc memory "
12047ad633c0SHarish Zunjarrao 				  "for about_fw\n", __func__));
12057ad633c0SHarish Zunjarrao 		return status;
12067ad633c0SHarish Zunjarrao 	}
12077ad633c0SHarish Zunjarrao 
12087ad633c0SHarish Zunjarrao 	memset(about_fw, 0, sizeof(struct about_fw_info));
1209afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1210afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1211c0e344c9SDavid C Somayajulu 
1212afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_ABOUT_FW;
12137ad633c0SHarish Zunjarrao 	mbox_cmd[2] = LSDW(about_fw_dma);
12147ad633c0SHarish Zunjarrao 	mbox_cmd[3] = MSDW(about_fw_dma);
12157ad633c0SHarish Zunjarrao 	mbox_cmd[4] = sizeof(struct about_fw_info);
1216c0e344c9SDavid C Somayajulu 
12177ad633c0SHarish Zunjarrao 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT,
12187ad633c0SHarish Zunjarrao 					 &mbox_cmd[0], &mbox_sts[0]);
12197ad633c0SHarish Zunjarrao 	if (status != QLA_SUCCESS) {
12207ad633c0SHarish Zunjarrao 		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_ABOUT_FW "
12217ad633c0SHarish Zunjarrao 				  "failed w/ status %04X\n", __func__,
12227ad633c0SHarish Zunjarrao 				  mbox_sts[0]));
12237ad633c0SHarish Zunjarrao 		goto exit_about_fw;
1224afaf5a2dSDavid Somayajulu 	}
1225afaf5a2dSDavid Somayajulu 
12267ad633c0SHarish Zunjarrao 	/* Save version information. */
12277ad633c0SHarish Zunjarrao 	ha->firmware_version[0] = le16_to_cpu(about_fw->fw_major);
12287ad633c0SHarish Zunjarrao 	ha->firmware_version[1] = le16_to_cpu(about_fw->fw_minor);
12297ad633c0SHarish Zunjarrao 	ha->patch_number = le16_to_cpu(about_fw->fw_patch);
12307ad633c0SHarish Zunjarrao 	ha->build_number = le16_to_cpu(about_fw->fw_build);
12317ad633c0SHarish Zunjarrao 	ha->iscsi_major = le16_to_cpu(about_fw->iscsi_major);
12327ad633c0SHarish Zunjarrao 	ha->iscsi_minor = le16_to_cpu(about_fw->iscsi_minor);
12337ad633c0SHarish Zunjarrao 	ha->bootload_major = le16_to_cpu(about_fw->bootload_major);
12347ad633c0SHarish Zunjarrao 	ha->bootload_minor = le16_to_cpu(about_fw->bootload_minor);
12357ad633c0SHarish Zunjarrao 	ha->bootload_patch = le16_to_cpu(about_fw->bootload_patch);
12367ad633c0SHarish Zunjarrao 	ha->bootload_build = le16_to_cpu(about_fw->bootload_build);
12377ad633c0SHarish Zunjarrao 	status = QLA_SUCCESS;
1238afaf5a2dSDavid Somayajulu 
12397ad633c0SHarish Zunjarrao exit_about_fw:
12407ad633c0SHarish Zunjarrao 	dma_free_coherent(&ha->pdev->dev, sizeof(struct about_fw_info),
12417ad633c0SHarish Zunjarrao 			  about_fw, about_fw_dma);
12427ad633c0SHarish Zunjarrao 	return status;
1243afaf5a2dSDavid Somayajulu }
1244afaf5a2dSDavid Somayajulu 
1245b3a271a9SManish Rangankar static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options,
124647975477SAdrian Bunk 				   dma_addr_t dma_addr)
1247afaf5a2dSDavid Somayajulu {
1248afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1249afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
1250afaf5a2dSDavid Somayajulu 
1251afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1252afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1253afaf5a2dSDavid Somayajulu 
1254afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS;
1255b3a271a9SManish Rangankar 	mbox_cmd[1] = options;
1256afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = LSDW(dma_addr);
1257afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = MSDW(dma_addr);
1258afaf5a2dSDavid Somayajulu 
1259c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=
1260afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
1261afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
1262afaf5a2dSDavid Somayajulu 		     ha->host_no, __func__, mbox_sts[0]));
1263afaf5a2dSDavid Somayajulu 		return QLA_ERROR;
1264afaf5a2dSDavid Somayajulu 	}
1265afaf5a2dSDavid Somayajulu 	return QLA_SUCCESS;
1266afaf5a2dSDavid Somayajulu }
1267afaf5a2dSDavid Somayajulu 
1268b3a271a9SManish Rangankar int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index,
1269b3a271a9SManish Rangankar 			  uint32_t *mbx_sts)
1270afaf5a2dSDavid Somayajulu {
1271b3a271a9SManish Rangankar 	int status;
1272afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1273afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
1274afaf5a2dSDavid Somayajulu 
1275afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1276afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1277afaf5a2dSDavid Somayajulu 
1278afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY;
1279b3a271a9SManish Rangankar 	mbox_cmd[1] = ddb_index;
1280afaf5a2dSDavid Somayajulu 
1281b3a271a9SManish Rangankar 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
1282b3a271a9SManish Rangankar 					 &mbox_sts[0]);
1283b3a271a9SManish Rangankar 	if (status != QLA_SUCCESS) {
1284b3a271a9SManish Rangankar 		DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",
1285b3a271a9SManish Rangankar 				   __func__, mbox_sts[0]));
1286afaf5a2dSDavid Somayajulu 	}
1287afaf5a2dSDavid Somayajulu 
1288b3a271a9SManish Rangankar 	*mbx_sts = mbox_sts[0];
1289b3a271a9SManish Rangankar 	return status;
1290afaf5a2dSDavid Somayajulu }
1291afaf5a2dSDavid Somayajulu 
1292b3a271a9SManish Rangankar int qla4xxx_clear_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index)
1293b3a271a9SManish Rangankar {
1294b3a271a9SManish Rangankar 	int status;
1295b3a271a9SManish Rangankar 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1296b3a271a9SManish Rangankar 	uint32_t mbox_sts[MBOX_REG_COUNT];
1297b3a271a9SManish Rangankar 
1298b3a271a9SManish Rangankar 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1299b3a271a9SManish Rangankar 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1300b3a271a9SManish Rangankar 
1301b3a271a9SManish Rangankar 	mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY;
1302b3a271a9SManish Rangankar 	mbox_cmd[1] = ddb_index;
1303b3a271a9SManish Rangankar 
1304b3a271a9SManish Rangankar 	status = qla4xxx_mailbox_command(ha, 2, 1, &mbox_cmd[0],
1305b3a271a9SManish Rangankar 					 &mbox_sts[0]);
1306b3a271a9SManish Rangankar 	if (status != QLA_SUCCESS) {
1307b3a271a9SManish Rangankar 		DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",
1308b3a271a9SManish Rangankar 				   __func__, mbox_sts[0]));
1309b3a271a9SManish Rangankar 	}
1310b3a271a9SManish Rangankar 
1311b3a271a9SManish Rangankar 	return status;
1312b3a271a9SManish Rangankar }
1313b3a271a9SManish Rangankar 
1314d00efe3fSMike Christie int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
1315d00efe3fSMike Christie 		      uint32_t offset, uint32_t length, uint32_t options)
1316d00efe3fSMike Christie {
1317d00efe3fSMike Christie 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1318d00efe3fSMike Christie 	uint32_t mbox_sts[MBOX_REG_COUNT];
1319d00efe3fSMike Christie 	int status = QLA_SUCCESS;
1320d00efe3fSMike Christie 
1321d00efe3fSMike Christie 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1322d00efe3fSMike Christie 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1323d00efe3fSMike Christie 
1324d00efe3fSMike Christie 	mbox_cmd[0] = MBOX_CMD_WRITE_FLASH;
1325d00efe3fSMike Christie 	mbox_cmd[1] = LSDW(dma_addr);
1326d00efe3fSMike Christie 	mbox_cmd[2] = MSDW(dma_addr);
1327d00efe3fSMike Christie 	mbox_cmd[3] = offset;
1328d00efe3fSMike Christie 	mbox_cmd[4] = length;
1329d00efe3fSMike Christie 	mbox_cmd[5] = options;
1330d00efe3fSMike Christie 
1331d00efe3fSMike Christie 	status = qla4xxx_mailbox_command(ha, 6, 2, &mbox_cmd[0], &mbox_sts[0]);
1332d00efe3fSMike Christie 	if (status != QLA_SUCCESS) {
1333d00efe3fSMike Christie 		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_WRITE_FLASH "
1334d00efe3fSMike Christie 				  "failed w/ status %04X, mbx1 %04X\n",
1335d00efe3fSMike Christie 				  __func__, mbox_sts[0], mbox_sts[1]));
1336d00efe3fSMike Christie 	}
1337d00efe3fSMike Christie 	return status;
1338d00efe3fSMike Christie }
1339d00efe3fSMike Christie 
13402a991c21SManish Rangankar int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha,
13412a991c21SManish Rangankar 			    struct dev_db_entry *fw_ddb_entry,
13422a991c21SManish Rangankar 			    dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index)
13432a991c21SManish Rangankar {
13442a991c21SManish Rangankar 	uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO;
13452a991c21SManish Rangankar 	uint32_t dev_db_end_offset;
13462a991c21SManish Rangankar 	int status = QLA_ERROR;
13472a991c21SManish Rangankar 
13482a991c21SManish Rangankar 	memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry));
13492a991c21SManish Rangankar 
13502a991c21SManish Rangankar 	dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry));
13512a991c21SManish Rangankar 	dev_db_end_offset = FLASH_OFFSET_DB_END;
13522a991c21SManish Rangankar 
13532a991c21SManish Rangankar 	if (dev_db_start_offset > dev_db_end_offset) {
13542a991c21SManish Rangankar 		DEBUG2(ql4_printk(KERN_ERR, ha,
13552a991c21SManish Rangankar 				  "%s:Invalid DDB index %d", __func__,
13562a991c21SManish Rangankar 				  ddb_index));
13572a991c21SManish Rangankar 		goto exit_bootdb_failed;
13582a991c21SManish Rangankar 	}
13592a991c21SManish Rangankar 
13602a991c21SManish Rangankar 	if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset,
13612a991c21SManish Rangankar 			      sizeof(*fw_ddb_entry)) != QLA_SUCCESS) {
13622a991c21SManish Rangankar 		ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash"
13632a991c21SManish Rangankar 			   "failed\n", ha->host_no, __func__);
13642a991c21SManish Rangankar 		goto exit_bootdb_failed;
13652a991c21SManish Rangankar 	}
13662a991c21SManish Rangankar 
13672a991c21SManish Rangankar 	if (fw_ddb_entry->cookie == DDB_VALID_COOKIE)
13682a991c21SManish Rangankar 		status = QLA_SUCCESS;
13692a991c21SManish Rangankar 
13702a991c21SManish Rangankar exit_bootdb_failed:
13712a991c21SManish Rangankar 	return status;
13722a991c21SManish Rangankar }
13732a991c21SManish Rangankar 
13742a991c21SManish Rangankar int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,
13752a991c21SManish Rangankar 		     uint16_t idx)
13762a991c21SManish Rangankar {
13772a991c21SManish Rangankar 	int ret = 0;
13782a991c21SManish Rangankar 	int rval = QLA_ERROR;
13794549415aSLalit Chandivade 	uint32_t offset = 0, chap_size;
13802a991c21SManish Rangankar 	struct ql4_chap_table *chap_table;
13812a991c21SManish Rangankar 	dma_addr_t chap_dma;
13822a991c21SManish Rangankar 
13832a991c21SManish Rangankar 	chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);
13842a991c21SManish Rangankar 	if (chap_table == NULL) {
13852a991c21SManish Rangankar 		ret = -ENOMEM;
13862a991c21SManish Rangankar 		goto exit_get_chap;
13872a991c21SManish Rangankar 	}
13882a991c21SManish Rangankar 
13894549415aSLalit Chandivade 	chap_size = sizeof(struct ql4_chap_table);
13904549415aSLalit Chandivade 	memset(chap_table, 0, chap_size);
13912a991c21SManish Rangankar 
13924549415aSLalit Chandivade 	if (is_qla40XX(ha))
13934549415aSLalit Chandivade 		offset = FLASH_CHAP_OFFSET | (idx * chap_size);
13944549415aSLalit Chandivade 	else {
13954549415aSLalit Chandivade 		offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);
13964549415aSLalit Chandivade 		/* flt_chap_size is CHAP table size for both ports
13974549415aSLalit Chandivade 		 * so divide it by 2 to calculate the offset for second port
13984549415aSLalit Chandivade 		 */
13994549415aSLalit Chandivade 		if (ha->port_num == 1)
14004549415aSLalit Chandivade 			offset += (ha->hw.flt_chap_size / 2);
14014549415aSLalit Chandivade 		offset += (idx * chap_size);
14024549415aSLalit Chandivade 	}
14032a991c21SManish Rangankar 
14044549415aSLalit Chandivade 	rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size);
14052a991c21SManish Rangankar 	if (rval != QLA_SUCCESS) {
14062a991c21SManish Rangankar 		ret = -EINVAL;
14072a991c21SManish Rangankar 		goto exit_get_chap;
14082a991c21SManish Rangankar 	}
14092a991c21SManish Rangankar 
14102a991c21SManish Rangankar 	DEBUG2(ql4_printk(KERN_INFO, ha, "Chap Cookie: x%x\n",
14112a991c21SManish Rangankar 		__le16_to_cpu(chap_table->cookie)));
14122a991c21SManish Rangankar 
14132a991c21SManish Rangankar 	if (__le16_to_cpu(chap_table->cookie) != CHAP_VALID_COOKIE) {
14142a991c21SManish Rangankar 		ql4_printk(KERN_ERR, ha, "No valid chap entry found\n");
14152a991c21SManish Rangankar 		goto exit_get_chap;
14162a991c21SManish Rangankar 	}
14172a991c21SManish Rangankar 
14182a991c21SManish Rangankar 	strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
14192a991c21SManish Rangankar 	strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
14202a991c21SManish Rangankar 	chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE);
14212a991c21SManish Rangankar 
14222a991c21SManish Rangankar exit_get_chap:
14232a991c21SManish Rangankar 	dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
14242a991c21SManish Rangankar 	return ret;
14252a991c21SManish Rangankar }
14262a991c21SManish Rangankar 
1427b3a271a9SManish Rangankar static int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username,
1428b3a271a9SManish Rangankar 			    char *password, uint16_t idx, int bidi)
1429b3a271a9SManish Rangankar {
1430b3a271a9SManish Rangankar 	int ret = 0;
1431b3a271a9SManish Rangankar 	int rval = QLA_ERROR;
1432b3a271a9SManish Rangankar 	uint32_t offset = 0;
1433b3a271a9SManish Rangankar 	struct ql4_chap_table *chap_table;
1434b3a271a9SManish Rangankar 	dma_addr_t chap_dma;
1435b3a271a9SManish Rangankar 
1436b3a271a9SManish Rangankar 	chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);
1437b3a271a9SManish Rangankar 	if (chap_table == NULL) {
1438b3a271a9SManish Rangankar 		ret =  -ENOMEM;
1439b3a271a9SManish Rangankar 		goto exit_set_chap;
1440b3a271a9SManish Rangankar 	}
1441b3a271a9SManish Rangankar 
1442b3a271a9SManish Rangankar 	memset(chap_table, 0, sizeof(struct ql4_chap_table));
1443b3a271a9SManish Rangankar 	if (bidi)
1444b3a271a9SManish Rangankar 		chap_table->flags |= BIT_6; /* peer */
1445b3a271a9SManish Rangankar 	else
1446b3a271a9SManish Rangankar 		chap_table->flags |= BIT_7; /* local */
1447b3a271a9SManish Rangankar 	chap_table->secret_len = strlen(password);
1448b3a271a9SManish Rangankar 	strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN);
1449b3a271a9SManish Rangankar 	strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN);
1450b3a271a9SManish Rangankar 	chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE);
14514549415aSLalit Chandivade 	offset = FLASH_CHAP_OFFSET | (idx * sizeof(struct ql4_chap_table));
1452b3a271a9SManish Rangankar 	rval = qla4xxx_set_flash(ha, chap_dma, offset,
1453b3a271a9SManish Rangankar 				sizeof(struct ql4_chap_table),
1454b3a271a9SManish Rangankar 				FLASH_OPT_RMW_COMMIT);
14554549415aSLalit Chandivade 
14564549415aSLalit Chandivade 	if (rval == QLA_SUCCESS && ha->chap_list) {
14574549415aSLalit Chandivade 		/* Update ha chap_list cache */
14584549415aSLalit Chandivade 		memcpy((struct ql4_chap_table *)ha->chap_list + idx,
14594549415aSLalit Chandivade 		       chap_table, sizeof(struct ql4_chap_table));
14604549415aSLalit Chandivade 	}
1461b3a271a9SManish Rangankar 	dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
1462b3a271a9SManish Rangankar 	if (rval != QLA_SUCCESS)
1463b3a271a9SManish Rangankar 		ret =  -EINVAL;
1464b3a271a9SManish Rangankar 
1465b3a271a9SManish Rangankar exit_set_chap:
1466b3a271a9SManish Rangankar 	return ret;
1467b3a271a9SManish Rangankar }
1468b3a271a9SManish Rangankar 
14694549415aSLalit Chandivade /**
14704549415aSLalit Chandivade  * qla4xxx_get_chap_index - Get chap index given username and secret
14714549415aSLalit Chandivade  * @ha: pointer to adapter structure
14724549415aSLalit Chandivade  * @username: CHAP username to be searched
14734549415aSLalit Chandivade  * @password: CHAP password to be searched
14744549415aSLalit Chandivade  * @bidi: Is this a BIDI CHAP
14754549415aSLalit Chandivade  * @chap_index: CHAP index to be returned
14764549415aSLalit Chandivade  *
14774549415aSLalit Chandivade  * Match the username and password in the chap_list, return the index if a
14784549415aSLalit Chandivade  * match is found. If a match is not found then add the entry in FLASH and
14794549415aSLalit Chandivade  * return the index at which entry is written in the FLASH.
14804549415aSLalit Chandivade  **/
1481fca9f04dSMike Christie int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username,
14824549415aSLalit Chandivade 			   char *password, int bidi, uint16_t *chap_index)
14834549415aSLalit Chandivade {
14844549415aSLalit Chandivade 	int i, rval;
14854549415aSLalit Chandivade 	int free_index = -1;
14864549415aSLalit Chandivade 	int found_index = 0;
14874549415aSLalit Chandivade 	int max_chap_entries = 0;
14884549415aSLalit Chandivade 	struct ql4_chap_table *chap_table;
14894549415aSLalit Chandivade 
14904549415aSLalit Chandivade 	if (is_qla8022(ha))
14914549415aSLalit Chandivade 		max_chap_entries = (ha->hw.flt_chap_size / 2) /
14924549415aSLalit Chandivade 						sizeof(struct ql4_chap_table);
14934549415aSLalit Chandivade 	else
14944549415aSLalit Chandivade 		max_chap_entries = MAX_CHAP_ENTRIES_40XX;
14954549415aSLalit Chandivade 
14964549415aSLalit Chandivade 	if (!ha->chap_list) {
14974549415aSLalit Chandivade 		ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");
14984549415aSLalit Chandivade 		return QLA_ERROR;
14994549415aSLalit Chandivade 	}
15004549415aSLalit Chandivade 
1501fca9f04dSMike Christie 	if (!username || !password) {
1502fca9f04dSMike Christie 		ql4_printk(KERN_ERR, ha, "Do not have username and psw\n");
1503fca9f04dSMike Christie 		return QLA_ERROR;
1504fca9f04dSMike Christie 	}
1505fca9f04dSMike Christie 
15064549415aSLalit Chandivade 	mutex_lock(&ha->chap_sem);
15074549415aSLalit Chandivade 	for (i = 0; i < max_chap_entries; i++) {
15084549415aSLalit Chandivade 		chap_table = (struct ql4_chap_table *)ha->chap_list + i;
15094549415aSLalit Chandivade 		if (chap_table->cookie !=
15104549415aSLalit Chandivade 		    __constant_cpu_to_le16(CHAP_VALID_COOKIE)) {
15114549415aSLalit Chandivade 			if (i > MAX_RESRV_CHAP_IDX && free_index == -1)
15124549415aSLalit Chandivade 				free_index = i;
15134549415aSLalit Chandivade 			continue;
15144549415aSLalit Chandivade 		}
15154549415aSLalit Chandivade 		if (bidi) {
15164549415aSLalit Chandivade 			if (chap_table->flags & BIT_7)
15174549415aSLalit Chandivade 				continue;
15184549415aSLalit Chandivade 		} else {
15194549415aSLalit Chandivade 			if (chap_table->flags & BIT_6)
15204549415aSLalit Chandivade 				continue;
15214549415aSLalit Chandivade 		}
15224549415aSLalit Chandivade 		if (!strncmp(chap_table->secret, password,
15234549415aSLalit Chandivade 			     MAX_CHAP_SECRET_LEN) &&
15244549415aSLalit Chandivade 		    !strncmp(chap_table->name, username,
15254549415aSLalit Chandivade 			     MAX_CHAP_NAME_LEN)) {
15264549415aSLalit Chandivade 			*chap_index = i;
15274549415aSLalit Chandivade 			found_index = 1;
15284549415aSLalit Chandivade 			break;
15294549415aSLalit Chandivade 		}
15304549415aSLalit Chandivade 	}
15314549415aSLalit Chandivade 
15324549415aSLalit Chandivade 	/* If chap entry is not present and a free index is available then
15334549415aSLalit Chandivade 	 * write the entry in flash
15344549415aSLalit Chandivade 	 */
15354549415aSLalit Chandivade 	if (!found_index && free_index != -1) {
15364549415aSLalit Chandivade 		rval = qla4xxx_set_chap(ha, username, password,
15374549415aSLalit Chandivade 					free_index, bidi);
15384549415aSLalit Chandivade 		if (!rval) {
15394549415aSLalit Chandivade 			*chap_index = free_index;
15404549415aSLalit Chandivade 			found_index = 1;
15414549415aSLalit Chandivade 		}
15424549415aSLalit Chandivade 	}
15434549415aSLalit Chandivade 
15444549415aSLalit Chandivade 	mutex_unlock(&ha->chap_sem);
15454549415aSLalit Chandivade 
15464549415aSLalit Chandivade 	if (found_index)
15474549415aSLalit Chandivade 		return QLA_SUCCESS;
15484549415aSLalit Chandivade 	return QLA_ERROR;
15494549415aSLalit Chandivade }
15504549415aSLalit Chandivade 
1551d00efe3fSMike Christie int qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha,
1552d00efe3fSMike Christie 				   uint16_t fw_ddb_index,
1553d00efe3fSMike Christie 				   uint16_t connection_id,
1554d00efe3fSMike Christie 				   uint16_t option)
1555d00efe3fSMike Christie {
1556d00efe3fSMike Christie 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1557d00efe3fSMike Christie 	uint32_t mbox_sts[MBOX_REG_COUNT];
1558d00efe3fSMike Christie 	int status = QLA_SUCCESS;
1559d00efe3fSMike Christie 
1560d00efe3fSMike Christie 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1561d00efe3fSMike Christie 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1562d00efe3fSMike Christie 
1563d00efe3fSMike Christie 	mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
1564d00efe3fSMike Christie 	mbox_cmd[1] = fw_ddb_index;
1565d00efe3fSMike Christie 	mbox_cmd[2] = connection_id;
1566d00efe3fSMike Christie 	mbox_cmd[3] = option;
1567d00efe3fSMike Christie 
1568d00efe3fSMike Christie 	status = qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]);
1569d00efe3fSMike Christie 	if (status != QLA_SUCCESS) {
1570d00efe3fSMike Christie 		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_CONN_CLOSE "
1571d00efe3fSMike Christie 				  "option %04x failed w/ status %04X %04X\n",
1572d00efe3fSMike Christie 				  __func__, option, mbox_sts[0], mbox_sts[1]));
1573d00efe3fSMike Christie 	}
1574d00efe3fSMike Christie 	return status;
1575d00efe3fSMike Christie }
1576d00efe3fSMike Christie 
1577d00efe3fSMike Christie int qla4xxx_disable_acb(struct scsi_qla_host *ha)
1578d00efe3fSMike Christie {
1579d00efe3fSMike Christie 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1580d00efe3fSMike Christie 	uint32_t mbox_sts[MBOX_REG_COUNT];
1581d00efe3fSMike Christie 	int status = QLA_SUCCESS;
1582d00efe3fSMike Christie 
1583d00efe3fSMike Christie 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1584d00efe3fSMike Christie 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1585d00efe3fSMike Christie 
1586d00efe3fSMike Christie 	mbox_cmd[0] = MBOX_CMD_DISABLE_ACB;
1587d00efe3fSMike Christie 
1588d00efe3fSMike Christie 	status = qla4xxx_mailbox_command(ha, 8, 5, &mbox_cmd[0], &mbox_sts[0]);
1589d00efe3fSMike Christie 	if (status != QLA_SUCCESS) {
1590d00efe3fSMike Christie 		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_DISABLE_ACB "
1591d00efe3fSMike Christie 				  "failed w/ status %04X %04X %04X", __func__,
1592d00efe3fSMike Christie 				  mbox_sts[0], mbox_sts[1], mbox_sts[2]));
1593d00efe3fSMike Christie 	}
1594d00efe3fSMike Christie 	return status;
1595d00efe3fSMike Christie }
1596d00efe3fSMike Christie 
15976085491cSHarish Zunjarrao int qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma,
15986085491cSHarish Zunjarrao 		    uint32_t acb_type, uint32_t len)
1599d00efe3fSMike Christie {
16006085491cSHarish Zunjarrao 	uint32_t mbox_cmd[MBOX_REG_COUNT];
16016085491cSHarish Zunjarrao 	uint32_t mbox_sts[MBOX_REG_COUNT];
1602d00efe3fSMike Christie 	int status = QLA_SUCCESS;
1603d00efe3fSMike Christie 
16046085491cSHarish Zunjarrao 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
16056085491cSHarish Zunjarrao 	memset(&mbox_sts, 0, sizeof(mbox_sts));
16066085491cSHarish Zunjarrao 
1607d00efe3fSMike Christie 	mbox_cmd[0] = MBOX_CMD_GET_ACB;
16086085491cSHarish Zunjarrao 	mbox_cmd[1] = acb_type;
1609d00efe3fSMike Christie 	mbox_cmd[2] = LSDW(acb_dma);
1610d00efe3fSMike Christie 	mbox_cmd[3] = MSDW(acb_dma);
16116085491cSHarish Zunjarrao 	mbox_cmd[4] = len;
1612d00efe3fSMike Christie 
1613d00efe3fSMike Christie 	status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);
1614d00efe3fSMike Christie 	if (status != QLA_SUCCESS) {
1615d00efe3fSMike Christie 		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_GET_ACB "
1616d00efe3fSMike Christie 				  "failed w/ status %04X\n", __func__,
1617d00efe3fSMike Christie 				  mbox_sts[0]));
1618d00efe3fSMike Christie 	}
1619d00efe3fSMike Christie 	return status;
1620d00efe3fSMike Christie }
1621d00efe3fSMike Christie 
1622d00efe3fSMike Christie int qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
1623d00efe3fSMike Christie 		    uint32_t *mbox_sts, dma_addr_t acb_dma)
1624d00efe3fSMike Christie {
1625d00efe3fSMike Christie 	int status = QLA_SUCCESS;
1626d00efe3fSMike Christie 
1627d00efe3fSMike Christie 	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
1628d00efe3fSMike Christie 	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
1629d00efe3fSMike Christie 	mbox_cmd[0] = MBOX_CMD_SET_ACB;
1630d00efe3fSMike Christie 	mbox_cmd[1] = 0; /* Primary ACB */
1631d00efe3fSMike Christie 	mbox_cmd[2] = LSDW(acb_dma);
1632d00efe3fSMike Christie 	mbox_cmd[3] = MSDW(acb_dma);
1633d00efe3fSMike Christie 	mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
1634d00efe3fSMike Christie 
1635d00efe3fSMike Christie 	status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);
1636d00efe3fSMike Christie 	if (status != QLA_SUCCESS) {
1637d00efe3fSMike Christie 		DEBUG2(ql4_printk(KERN_WARNING, ha,  "%s: MBOX_CMD_SET_ACB "
1638d00efe3fSMike Christie 				  "failed w/ status %04X\n", __func__,
1639d00efe3fSMike Christie 				  mbox_sts[0]));
1640d00efe3fSMike Christie 	}
1641d00efe3fSMike Christie 	return status;
1642d00efe3fSMike Christie }
1643b3a271a9SManish Rangankar 
1644b3a271a9SManish Rangankar int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
1645b3a271a9SManish Rangankar 			       struct ddb_entry *ddb_entry,
1646b3a271a9SManish Rangankar 			       struct iscsi_cls_conn *cls_conn,
1647b3a271a9SManish Rangankar 			       uint32_t *mbx_sts)
1648b3a271a9SManish Rangankar {
1649b3a271a9SManish Rangankar 	struct dev_db_entry *fw_ddb_entry;
1650b3a271a9SManish Rangankar 	struct iscsi_conn *conn;
1651b3a271a9SManish Rangankar 	struct iscsi_session *sess;
1652b3a271a9SManish Rangankar 	struct qla_conn *qla_conn;
1653b3a271a9SManish Rangankar 	struct sockaddr *dst_addr;
1654b3a271a9SManish Rangankar 	dma_addr_t fw_ddb_entry_dma;
1655b3a271a9SManish Rangankar 	int status = QLA_SUCCESS;
1656b3a271a9SManish Rangankar 	int rval = 0;
1657b3a271a9SManish Rangankar 	struct sockaddr_in *addr;
1658b3a271a9SManish Rangankar 	struct sockaddr_in6 *addr6;
1659b3a271a9SManish Rangankar 	char *ip;
1660b3a271a9SManish Rangankar 	uint16_t iscsi_opts = 0;
1661b3a271a9SManish Rangankar 	uint32_t options = 0;
1662173269efSManish Rangankar 	uint16_t idx, *ptid;
1663b3a271a9SManish Rangankar 
1664b3a271a9SManish Rangankar 	fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
1665b3a271a9SManish Rangankar 					  &fw_ddb_entry_dma, GFP_KERNEL);
1666b3a271a9SManish Rangankar 	if (!fw_ddb_entry) {
1667b3a271a9SManish Rangankar 		DEBUG2(ql4_printk(KERN_ERR, ha,
1668b3a271a9SManish Rangankar 				  "%s: Unable to allocate dma buffer.\n",
1669b3a271a9SManish Rangankar 				  __func__));
1670b3a271a9SManish Rangankar 		rval = -ENOMEM;
1671b3a271a9SManish Rangankar 		goto exit_set_param_no_free;
1672b3a271a9SManish Rangankar 	}
1673b3a271a9SManish Rangankar 
1674b3a271a9SManish Rangankar 	conn = cls_conn->dd_data;
1675b3a271a9SManish Rangankar 	qla_conn = conn->dd_data;
1676b3a271a9SManish Rangankar 	sess = conn->session;
1677d46bdeb1SManish Rangankar 	dst_addr = (struct sockaddr *)&qla_conn->qla_ep->dst_addr;
1678b3a271a9SManish Rangankar 
1679b3a271a9SManish Rangankar 	if (dst_addr->sa_family == AF_INET6)
1680b3a271a9SManish Rangankar 		options |= IPV6_DEFAULT_DDB_ENTRY;
1681b3a271a9SManish Rangankar 
1682b3a271a9SManish Rangankar 	status = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma);
1683b3a271a9SManish Rangankar 	if (status == QLA_ERROR) {
1684b3a271a9SManish Rangankar 		rval = -EINVAL;
1685b3a271a9SManish Rangankar 		goto exit_set_param;
1686b3a271a9SManish Rangankar 	}
1687b3a271a9SManish Rangankar 
1688173269efSManish Rangankar 	ptid = (uint16_t *)&fw_ddb_entry->isid[1];
1689173269efSManish Rangankar 	*ptid = cpu_to_le16((uint16_t)ddb_entry->sess->target_id);
1690173269efSManish Rangankar 
1691173269efSManish Rangankar 	DEBUG2(ql4_printk(KERN_INFO, ha, "ISID [%02x%02x%02x%02x%02x%02x]\n",
1692173269efSManish Rangankar 			  fw_ddb_entry->isid[5], fw_ddb_entry->isid[4],
1693173269efSManish Rangankar 			  fw_ddb_entry->isid[3], fw_ddb_entry->isid[2],
1694173269efSManish Rangankar 			  fw_ddb_entry->isid[1], fw_ddb_entry->isid[0]));
1695173269efSManish Rangankar 
1696b3a271a9SManish Rangankar 	iscsi_opts = le16_to_cpu(fw_ddb_entry->iscsi_options);
1697b3a271a9SManish Rangankar 	memset(fw_ddb_entry->iscsi_alias, 0, sizeof(fw_ddb_entry->iscsi_alias));
1698b3a271a9SManish Rangankar 
1699b3a271a9SManish Rangankar 	memset(fw_ddb_entry->iscsi_name, 0, sizeof(fw_ddb_entry->iscsi_name));
1700b3a271a9SManish Rangankar 
1701b3a271a9SManish Rangankar 	if (sess->targetname != NULL) {
1702b3a271a9SManish Rangankar 		memcpy(fw_ddb_entry->iscsi_name, sess->targetname,
1703b3a271a9SManish Rangankar 		       min(strlen(sess->targetname),
1704b3a271a9SManish Rangankar 		       sizeof(fw_ddb_entry->iscsi_name)));
1705b3a271a9SManish Rangankar 	}
1706b3a271a9SManish Rangankar 
1707b3a271a9SManish Rangankar 	memset(fw_ddb_entry->ip_addr, 0, sizeof(fw_ddb_entry->ip_addr));
1708b3a271a9SManish Rangankar 	memset(fw_ddb_entry->tgt_addr, 0, sizeof(fw_ddb_entry->tgt_addr));
1709b3a271a9SManish Rangankar 
1710b3a271a9SManish Rangankar 	fw_ddb_entry->options =  DDB_OPT_TARGET | DDB_OPT_AUTO_SENDTGTS_DISABLE;
1711b3a271a9SManish Rangankar 
1712b3a271a9SManish Rangankar 	if (dst_addr->sa_family == AF_INET) {
1713b3a271a9SManish Rangankar 		addr = (struct sockaddr_in *)dst_addr;
1714b3a271a9SManish Rangankar 		ip = (char *)&addr->sin_addr;
1715b3a271a9SManish Rangankar 		memcpy(fw_ddb_entry->ip_addr, ip, IP_ADDR_LEN);
1716b3a271a9SManish Rangankar 		fw_ddb_entry->port = cpu_to_le16(ntohs(addr->sin_port));
1717b3a271a9SManish Rangankar 		DEBUG2(ql4_printk(KERN_INFO, ha,
1718b3a271a9SManish Rangankar 				  "%s: Destination Address [%pI4]: index [%d]\n",
1719b3a271a9SManish Rangankar 				   __func__, fw_ddb_entry->ip_addr,
1720b3a271a9SManish Rangankar 				  ddb_entry->fw_ddb_index));
1721b3a271a9SManish Rangankar 	} else if (dst_addr->sa_family == AF_INET6) {
1722b3a271a9SManish Rangankar 		addr6 = (struct sockaddr_in6 *)dst_addr;
1723b3a271a9SManish Rangankar 		ip = (char *)&addr6->sin6_addr;
1724b3a271a9SManish Rangankar 		memcpy(fw_ddb_entry->ip_addr, ip, IPv6_ADDR_LEN);
1725b3a271a9SManish Rangankar 		fw_ddb_entry->port = cpu_to_le16(ntohs(addr6->sin6_port));
1726b3a271a9SManish Rangankar 		fw_ddb_entry->options |= DDB_OPT_IPV6_DEVICE;
1727b3a271a9SManish Rangankar 		DEBUG2(ql4_printk(KERN_INFO, ha,
1728b3a271a9SManish Rangankar 				  "%s: Destination Address [%pI6]: index [%d]\n",
1729b3a271a9SManish Rangankar 				   __func__, fw_ddb_entry->ip_addr,
1730b3a271a9SManish Rangankar 				  ddb_entry->fw_ddb_index));
1731b3a271a9SManish Rangankar 	} else {
1732b3a271a9SManish Rangankar 		ql4_printk(KERN_ERR, ha,
1733b3a271a9SManish Rangankar 			   "%s: Failed to get IP Address\n",
1734b3a271a9SManish Rangankar 			   __func__);
1735b3a271a9SManish Rangankar 		rval = -EINVAL;
1736b3a271a9SManish Rangankar 		goto exit_set_param;
1737b3a271a9SManish Rangankar 	}
1738b3a271a9SManish Rangankar 
1739b3a271a9SManish Rangankar 	/* CHAP */
1740b3a271a9SManish Rangankar 	if (sess->username != NULL && sess->password != NULL) {
1741b3a271a9SManish Rangankar 		if (strlen(sess->username) && strlen(sess->password)) {
1742b3a271a9SManish Rangankar 			iscsi_opts |= BIT_7;
1743b3a271a9SManish Rangankar 
17444549415aSLalit Chandivade 			rval = qla4xxx_get_chap_index(ha, sess->username,
17454549415aSLalit Chandivade 						sess->password,
17464549415aSLalit Chandivade 						LOCAL_CHAP, &idx);
1747b3a271a9SManish Rangankar 			if (rval)
1748b3a271a9SManish Rangankar 				goto exit_set_param;
1749b3a271a9SManish Rangankar 
1750b3a271a9SManish Rangankar 			fw_ddb_entry->chap_tbl_idx = cpu_to_le16(idx);
1751b3a271a9SManish Rangankar 		}
1752b3a271a9SManish Rangankar 	}
1753b3a271a9SManish Rangankar 
1754b3a271a9SManish Rangankar 	if (sess->username_in != NULL && sess->password_in != NULL) {
1755b3a271a9SManish Rangankar 		/* Check if BIDI CHAP */
1756b3a271a9SManish Rangankar 		if (strlen(sess->username_in) && strlen(sess->password_in)) {
1757b3a271a9SManish Rangankar 			iscsi_opts |= BIT_4;
17584549415aSLalit Chandivade 
17594549415aSLalit Chandivade 			rval = qla4xxx_get_chap_index(ha, sess->username_in,
17604549415aSLalit Chandivade 						      sess->password_in,
17614549415aSLalit Chandivade 						      BIDI_CHAP, &idx);
1762b3a271a9SManish Rangankar 			if (rval)
1763b3a271a9SManish Rangankar 				goto exit_set_param;
1764b3a271a9SManish Rangankar 		}
1765b3a271a9SManish Rangankar 	}
1766b3a271a9SManish Rangankar 
1767b3a271a9SManish Rangankar 	if (sess->initial_r2t_en)
1768b3a271a9SManish Rangankar 		iscsi_opts |= BIT_10;
1769b3a271a9SManish Rangankar 
1770b3a271a9SManish Rangankar 	if (sess->imm_data_en)
1771b3a271a9SManish Rangankar 		iscsi_opts |= BIT_11;
1772b3a271a9SManish Rangankar 
1773b3a271a9SManish Rangankar 	fw_ddb_entry->iscsi_options = cpu_to_le16(iscsi_opts);
1774b3a271a9SManish Rangankar 
1775b3a271a9SManish Rangankar 	if (conn->max_recv_dlength)
1776b3a271a9SManish Rangankar 		fw_ddb_entry->iscsi_max_rcv_data_seg_len =
1777b3a271a9SManish Rangankar 		  __constant_cpu_to_le16((conn->max_recv_dlength / BYTE_UNITS));
1778b3a271a9SManish Rangankar 
1779b3a271a9SManish Rangankar 	if (sess->max_r2t)
1780b3a271a9SManish Rangankar 		fw_ddb_entry->iscsi_max_outsnd_r2t = cpu_to_le16(sess->max_r2t);
1781b3a271a9SManish Rangankar 
1782b3a271a9SManish Rangankar 	if (sess->first_burst)
1783b3a271a9SManish Rangankar 		fw_ddb_entry->iscsi_first_burst_len =
1784b3a271a9SManish Rangankar 		       __constant_cpu_to_le16((sess->first_burst / BYTE_UNITS));
1785b3a271a9SManish Rangankar 
1786b3a271a9SManish Rangankar 	if (sess->max_burst)
1787b3a271a9SManish Rangankar 		fw_ddb_entry->iscsi_max_burst_len =
1788b3a271a9SManish Rangankar 			__constant_cpu_to_le16((sess->max_burst / BYTE_UNITS));
1789b3a271a9SManish Rangankar 
1790b3a271a9SManish Rangankar 	if (sess->time2wait)
1791b3a271a9SManish Rangankar 		fw_ddb_entry->iscsi_def_time2wait =
1792b3a271a9SManish Rangankar 			cpu_to_le16(sess->time2wait);
1793b3a271a9SManish Rangankar 
1794b3a271a9SManish Rangankar 	if (sess->time2retain)
1795b3a271a9SManish Rangankar 		fw_ddb_entry->iscsi_def_time2retain =
1796b3a271a9SManish Rangankar 			cpu_to_le16(sess->time2retain);
1797b3a271a9SManish Rangankar 
1798b3a271a9SManish Rangankar 	status = qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index,
1799b3a271a9SManish Rangankar 				       fw_ddb_entry_dma, mbx_sts);
1800b3a271a9SManish Rangankar 
1801b3a271a9SManish Rangankar 	if (status != QLA_SUCCESS)
1802b3a271a9SManish Rangankar 		rval = -EINVAL;
1803b3a271a9SManish Rangankar exit_set_param:
1804b3a271a9SManish Rangankar 	dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
1805b3a271a9SManish Rangankar 			  fw_ddb_entry, fw_ddb_entry_dma);
1806b3a271a9SManish Rangankar exit_set_param_no_free:
1807b3a271a9SManish Rangankar 	return rval;
1808b3a271a9SManish Rangankar }
1809b3a271a9SManish Rangankar 
1810b3a271a9SManish Rangankar int qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index,
1811b3a271a9SManish Rangankar 			  uint16_t stats_size, dma_addr_t stats_dma)
1812b3a271a9SManish Rangankar {
1813b3a271a9SManish Rangankar 	int status = QLA_SUCCESS;
1814b3a271a9SManish Rangankar 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1815b3a271a9SManish Rangankar 	uint32_t mbox_sts[MBOX_REG_COUNT];
1816b3a271a9SManish Rangankar 
1817b3a271a9SManish Rangankar 	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
1818b3a271a9SManish Rangankar 	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
1819b3a271a9SManish Rangankar 	mbox_cmd[0] = MBOX_CMD_GET_MANAGEMENT_DATA;
1820b3a271a9SManish Rangankar 	mbox_cmd[1] = fw_ddb_index;
1821b3a271a9SManish Rangankar 	mbox_cmd[2] = LSDW(stats_dma);
1822b3a271a9SManish Rangankar 	mbox_cmd[3] = MSDW(stats_dma);
1823b3a271a9SManish Rangankar 	mbox_cmd[4] = stats_size;
1824b3a271a9SManish Rangankar 
1825b3a271a9SManish Rangankar 	status = qla4xxx_mailbox_command(ha, 5, 1, &mbox_cmd[0], &mbox_sts[0]);
1826b3a271a9SManish Rangankar 	if (status != QLA_SUCCESS) {
1827b3a271a9SManish Rangankar 		DEBUG2(ql4_printk(KERN_WARNING, ha,
1828b3a271a9SManish Rangankar 				  "%s: MBOX_CMD_GET_MANAGEMENT_DATA "
1829b3a271a9SManish Rangankar 				  "failed w/ status %04X\n", __func__,
1830b3a271a9SManish Rangankar 				  mbox_sts[0]));
1831b3a271a9SManish Rangankar 	}
1832b3a271a9SManish Rangankar 	return status;
1833b3a271a9SManish Rangankar }
18348b0402e1SHarish Zunjarrao 
18358b0402e1SHarish Zunjarrao int qla4xxx_get_ip_state(struct scsi_qla_host *ha, uint32_t acb_idx,
18368b0402e1SHarish Zunjarrao 			 uint32_t ip_idx, uint32_t *sts)
18378b0402e1SHarish Zunjarrao {
18388b0402e1SHarish Zunjarrao 	uint32_t mbox_cmd[MBOX_REG_COUNT];
18398b0402e1SHarish Zunjarrao 	uint32_t mbox_sts[MBOX_REG_COUNT];
18408b0402e1SHarish Zunjarrao 	int status = QLA_SUCCESS;
18418b0402e1SHarish Zunjarrao 
18428b0402e1SHarish Zunjarrao 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
18438b0402e1SHarish Zunjarrao 	memset(&mbox_sts, 0, sizeof(mbox_sts));
18448b0402e1SHarish Zunjarrao 	mbox_cmd[0] = MBOX_CMD_GET_IP_ADDR_STATE;
18458b0402e1SHarish Zunjarrao 	mbox_cmd[1] = acb_idx;
18468b0402e1SHarish Zunjarrao 	mbox_cmd[2] = ip_idx;
18478b0402e1SHarish Zunjarrao 
18488b0402e1SHarish Zunjarrao 	status = qla4xxx_mailbox_command(ha, 3, 8, &mbox_cmd[0], &mbox_sts[0]);
18498b0402e1SHarish Zunjarrao 	if (status != QLA_SUCCESS) {
18508b0402e1SHarish Zunjarrao 		DEBUG2(ql4_printk(KERN_WARNING, ha,  "%s: "
18518b0402e1SHarish Zunjarrao 				  "MBOX_CMD_GET_IP_ADDR_STATE failed w/ "
18528b0402e1SHarish Zunjarrao 				  "status %04X\n", __func__, mbox_sts[0]));
18538b0402e1SHarish Zunjarrao 	}
18548b0402e1SHarish Zunjarrao 	memcpy(sts, mbox_sts, sizeof(mbox_sts));
18558b0402e1SHarish Zunjarrao 	return status;
18568b0402e1SHarish Zunjarrao }
18577c07d139SHarish Zunjarrao 
18587c07d139SHarish Zunjarrao int qla4xxx_get_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,
18597c07d139SHarish Zunjarrao 		      uint32_t offset, uint32_t size)
18607c07d139SHarish Zunjarrao {
18617c07d139SHarish Zunjarrao 	int status = QLA_SUCCESS;
18627c07d139SHarish Zunjarrao 	uint32_t mbox_cmd[MBOX_REG_COUNT];
18637c07d139SHarish Zunjarrao 	uint32_t mbox_sts[MBOX_REG_COUNT];
18647c07d139SHarish Zunjarrao 
18657c07d139SHarish Zunjarrao 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
18667c07d139SHarish Zunjarrao 	memset(&mbox_sts, 0, sizeof(mbox_sts));
18677c07d139SHarish Zunjarrao 
18687c07d139SHarish Zunjarrao 	mbox_cmd[0] = MBOX_CMD_GET_NVRAM;
18697c07d139SHarish Zunjarrao 	mbox_cmd[1] = LSDW(nvram_dma);
18707c07d139SHarish Zunjarrao 	mbox_cmd[2] = MSDW(nvram_dma);
18717c07d139SHarish Zunjarrao 	mbox_cmd[3] = offset;
18727c07d139SHarish Zunjarrao 	mbox_cmd[4] = size;
18737c07d139SHarish Zunjarrao 
18747c07d139SHarish Zunjarrao 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
18757c07d139SHarish Zunjarrao 					 &mbox_sts[0]);
18767c07d139SHarish Zunjarrao 	if (status != QLA_SUCCESS) {
18777c07d139SHarish Zunjarrao 		DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
18787c07d139SHarish Zunjarrao 				  "status %04X\n", ha->host_no, __func__,
18797c07d139SHarish Zunjarrao 				  mbox_sts[0]));
18807c07d139SHarish Zunjarrao 	}
18817c07d139SHarish Zunjarrao 	return status;
18827c07d139SHarish Zunjarrao }
18837c07d139SHarish Zunjarrao 
18847c07d139SHarish Zunjarrao int qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,
18857c07d139SHarish Zunjarrao 		      uint32_t offset, uint32_t size)
18867c07d139SHarish Zunjarrao {
18877c07d139SHarish Zunjarrao 	int status = QLA_SUCCESS;
18887c07d139SHarish Zunjarrao 	uint32_t mbox_cmd[MBOX_REG_COUNT];
18897c07d139SHarish Zunjarrao 	uint32_t mbox_sts[MBOX_REG_COUNT];
18907c07d139SHarish Zunjarrao 
18917c07d139SHarish Zunjarrao 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
18927c07d139SHarish Zunjarrao 	memset(&mbox_sts, 0, sizeof(mbox_sts));
18937c07d139SHarish Zunjarrao 
18947c07d139SHarish Zunjarrao 	mbox_cmd[0] = MBOX_CMD_SET_NVRAM;
18957c07d139SHarish Zunjarrao 	mbox_cmd[1] = LSDW(nvram_dma);
18967c07d139SHarish Zunjarrao 	mbox_cmd[2] = MSDW(nvram_dma);
18977c07d139SHarish Zunjarrao 	mbox_cmd[3] = offset;
18987c07d139SHarish Zunjarrao 	mbox_cmd[4] = size;
18997c07d139SHarish Zunjarrao 
19007c07d139SHarish Zunjarrao 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
19017c07d139SHarish Zunjarrao 					 &mbox_sts[0]);
19027c07d139SHarish Zunjarrao 	if (status != QLA_SUCCESS) {
19037c07d139SHarish Zunjarrao 		DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
19047c07d139SHarish Zunjarrao 				  "status %04X\n", ha->host_no, __func__,
19057c07d139SHarish Zunjarrao 				  mbox_sts[0]));
19067c07d139SHarish Zunjarrao 	}
19077c07d139SHarish Zunjarrao 	return status;
19087c07d139SHarish Zunjarrao }
19095232f801SHarish Zunjarrao 
19105232f801SHarish Zunjarrao int qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha,
19115232f801SHarish Zunjarrao 				     uint32_t region, uint32_t field0,
19125232f801SHarish Zunjarrao 				     uint32_t field1)
19135232f801SHarish Zunjarrao {
19145232f801SHarish Zunjarrao 	int status = QLA_SUCCESS;
19155232f801SHarish Zunjarrao 	uint32_t mbox_cmd[MBOX_REG_COUNT];
19165232f801SHarish Zunjarrao 	uint32_t mbox_sts[MBOX_REG_COUNT];
19175232f801SHarish Zunjarrao 
19185232f801SHarish Zunjarrao 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
19195232f801SHarish Zunjarrao 	memset(&mbox_sts, 0, sizeof(mbox_sts));
19205232f801SHarish Zunjarrao 
19215232f801SHarish Zunjarrao 	mbox_cmd[0] = MBOX_CMD_RESTORE_FACTORY_DEFAULTS;
19225232f801SHarish Zunjarrao 	mbox_cmd[3] = region;
19235232f801SHarish Zunjarrao 	mbox_cmd[4] = field0;
19245232f801SHarish Zunjarrao 	mbox_cmd[5] = field1;
19255232f801SHarish Zunjarrao 
19265232f801SHarish Zunjarrao 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0],
19275232f801SHarish Zunjarrao 					 &mbox_sts[0]);
19285232f801SHarish Zunjarrao 	if (status != QLA_SUCCESS) {
19295232f801SHarish Zunjarrao 		DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
19305232f801SHarish Zunjarrao 				  "status %04X\n", ha->host_no, __func__,
19315232f801SHarish Zunjarrao 				  mbox_sts[0]));
19325232f801SHarish Zunjarrao 	}
19335232f801SHarish Zunjarrao 	return status;
19345232f801SHarish Zunjarrao }
1935*cfb27874SManish Dusane 
1936*cfb27874SManish Dusane /**
1937*cfb27874SManish Dusane  * qla4_8xxx_set_param - set driver version in firmware.
1938*cfb27874SManish Dusane  * @ha: Pointer to host adapter structure.
1939*cfb27874SManish Dusane  * @param: Parameter to set i.e driver version
1940*cfb27874SManish Dusane  **/
1941*cfb27874SManish Dusane int qla4_8xxx_set_param(struct scsi_qla_host *ha, int param)
1942*cfb27874SManish Dusane {
1943*cfb27874SManish Dusane 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1944*cfb27874SManish Dusane 	uint32_t mbox_sts[MBOX_REG_COUNT];
1945*cfb27874SManish Dusane 	uint32_t status;
1946*cfb27874SManish Dusane 
1947*cfb27874SManish Dusane 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1948*cfb27874SManish Dusane 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1949*cfb27874SManish Dusane 
1950*cfb27874SManish Dusane 	mbox_cmd[0] = MBOX_CMD_SET_PARAM;
1951*cfb27874SManish Dusane 	if (param == SET_DRVR_VERSION) {
1952*cfb27874SManish Dusane 		mbox_cmd[1] = SET_DRVR_VERSION;
1953*cfb27874SManish Dusane 		strncpy((char *)&mbox_cmd[2], QLA4XXX_DRIVER_VERSION,
1954*cfb27874SManish Dusane 			MAX_DRVR_VER_LEN);
1955*cfb27874SManish Dusane 	} else {
1956*cfb27874SManish Dusane 		ql4_printk(KERN_ERR, ha, "%s: invalid parameter 0x%x\n",
1957*cfb27874SManish Dusane 			   __func__, param);
1958*cfb27874SManish Dusane 		status = QLA_ERROR;
1959*cfb27874SManish Dusane 		goto exit_set_param;
1960*cfb27874SManish Dusane 	}
1961*cfb27874SManish Dusane 
1962*cfb27874SManish Dusane 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, mbox_cmd,
1963*cfb27874SManish Dusane 					 mbox_sts);
1964*cfb27874SManish Dusane 	if (status == QLA_ERROR)
1965*cfb27874SManish Dusane 		ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",
1966*cfb27874SManish Dusane 			   __func__, mbox_sts[0]);
1967*cfb27874SManish Dusane 
1968*cfb27874SManish Dusane exit_set_param:
1969*cfb27874SManish Dusane 	return status;
1970*cfb27874SManish Dusane }
1971