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