xref: /linux/drivers/scsi/qla4xxx/ql4_mbx.c (revision 6085491c34b37fa806f70ccd3fb2bf08416e9e98)
1afaf5a2dSDavid Somayajulu /*
2afaf5a2dSDavid Somayajulu  * QLogic iSCSI HBA Driver
37d01d069SVikas Chaudhary  * Copyright (c)  2003-2010 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 
13afaf5a2dSDavid Somayajulu 
14afaf5a2dSDavid Somayajulu /**
15afaf5a2dSDavid Somayajulu  * qla4xxx_mailbox_command - issues mailbox commands
16afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
17afaf5a2dSDavid Somayajulu  * @inCount: number of mailbox registers to load.
18afaf5a2dSDavid Somayajulu  * @outCount: number of mailbox registers to return.
19afaf5a2dSDavid Somayajulu  * @mbx_cmd: data pointer for mailbox in registers.
20afaf5a2dSDavid Somayajulu  * @mbx_sts: data pointer for mailbox out registers.
21afaf5a2dSDavid Somayajulu  *
2270f23fd6SJustin P. Mattock  * This routine issue mailbox commands and waits for completion.
23afaf5a2dSDavid Somayajulu  * If outCount is 0, this routine completes successfully WITHOUT waiting
24afaf5a2dSDavid Somayajulu  * for the mailbox command to complete.
25afaf5a2dSDavid Somayajulu  **/
26f4f5df23SVikas Chaudhary int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
27afaf5a2dSDavid Somayajulu 			    uint8_t outCount, uint32_t *mbx_cmd,
28afaf5a2dSDavid Somayajulu 			    uint32_t *mbx_sts)
29afaf5a2dSDavid Somayajulu {
30afaf5a2dSDavid Somayajulu 	int status = QLA_ERROR;
31afaf5a2dSDavid Somayajulu 	uint8_t i;
32afaf5a2dSDavid Somayajulu 	u_long wait_count;
33afaf5a2dSDavid Somayajulu 	uint32_t intr_status;
34afaf5a2dSDavid Somayajulu 	unsigned long flags = 0;
3599b53bf5SPrasanna Mumbai 	uint32_t dev_state;
36afaf5a2dSDavid Somayajulu 
37afaf5a2dSDavid Somayajulu 	/* Make sure that pointers are valid */
38afaf5a2dSDavid Somayajulu 	if (!mbx_cmd || !mbx_sts) {
39afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts "
40afaf5a2dSDavid Somayajulu 			      "pointer\n", ha->host_no, __func__));
41477ffb9dSDavid C Somayajulu 		return status;
42477ffb9dSDavid C Somayajulu 	}
4321033639SNilesh Javali 
4499b53bf5SPrasanna Mumbai 	if (is_qla8022(ha)) {
4599b53bf5SPrasanna Mumbai 		if (test_bit(AF_FW_RECOVERY, &ha->flags)) {
4699b53bf5SPrasanna Mumbai 			DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: "
4799b53bf5SPrasanna Mumbai 			    "prematurely completing mbx cmd as firmware "
4899b53bf5SPrasanna Mumbai 			    "recovery detected\n", ha->host_no, __func__));
4921033639SNilesh Javali 			return status;
5021033639SNilesh Javali 		}
5199b53bf5SPrasanna Mumbai 		/* Do not send any mbx cmd if h/w is in failed state*/
5299b53bf5SPrasanna Mumbai 		qla4_8xxx_idc_lock(ha);
5399b53bf5SPrasanna Mumbai 		dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
5499b53bf5SPrasanna Mumbai 		qla4_8xxx_idc_unlock(ha);
5599b53bf5SPrasanna Mumbai 		if (dev_state == QLA82XX_DEV_FAILED) {
5699b53bf5SPrasanna Mumbai 			ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: H/W is in "
5799b53bf5SPrasanna Mumbai 			    "failed state, do not send any mailbox commands\n",
5899b53bf5SPrasanna Mumbai 			    ha->host_no, __func__);
5999b53bf5SPrasanna Mumbai 			return status;
6099b53bf5SPrasanna Mumbai 		}
6199b53bf5SPrasanna Mumbai 	}
6221033639SNilesh Javali 
632232be0dSLalit Chandivade 	if ((is_aer_supported(ha)) &&
642232be0dSLalit Chandivade 	    (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) {
652232be0dSLalit Chandivade 		DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, "
662232be0dSLalit Chandivade 		    "timeout MBX Exiting.\n", ha->host_no, __func__));
672232be0dSLalit Chandivade 		return status;
682232be0dSLalit Chandivade 	}
692232be0dSLalit Chandivade 
70477ffb9dSDavid C Somayajulu 	/* Mailbox code active */
71477ffb9dSDavid C Somayajulu 	wait_count = MBOX_TOV * 100;
72477ffb9dSDavid C Somayajulu 
73477ffb9dSDavid C Somayajulu 	while (wait_count--) {
74477ffb9dSDavid C Somayajulu 		mutex_lock(&ha->mbox_sem);
75477ffb9dSDavid C Somayajulu 		if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) {
76477ffb9dSDavid C Somayajulu 			set_bit(AF_MBOX_COMMAND, &ha->flags);
77477ffb9dSDavid C Somayajulu 			mutex_unlock(&ha->mbox_sem);
78477ffb9dSDavid C Somayajulu 			break;
79477ffb9dSDavid C Somayajulu 		}
80477ffb9dSDavid C Somayajulu 		mutex_unlock(&ha->mbox_sem);
81477ffb9dSDavid C Somayajulu 		if (!wait_count) {
82477ffb9dSDavid C Somayajulu 			DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n",
83477ffb9dSDavid C Somayajulu 				ha->host_no, __func__));
84477ffb9dSDavid C Somayajulu 			return status;
85477ffb9dSDavid C Somayajulu 		}
86477ffb9dSDavid C Somayajulu 		msleep(10);
87afaf5a2dSDavid Somayajulu 	}
88afaf5a2dSDavid Somayajulu 
89afaf5a2dSDavid Somayajulu 	spin_lock_irqsave(&ha->hardware_lock, flags);
90f4f5df23SVikas Chaudhary 
91afaf5a2dSDavid Somayajulu 	ha->mbox_status_count = outCount;
92afaf5a2dSDavid Somayajulu 	for (i = 0; i < outCount; i++)
93afaf5a2dSDavid Somayajulu 		ha->mbox_status[i] = 0;
94afaf5a2dSDavid Somayajulu 
95f4f5df23SVikas Chaudhary 	if (is_qla8022(ha)) {
96f4f5df23SVikas Chaudhary 		/* Load all mailbox registers, except mailbox 0. */
97f4f5df23SVikas Chaudhary 		DEBUG5(
98f4f5df23SVikas Chaudhary 		    printk("scsi%ld: %s: Cmd ", ha->host_no, __func__);
99f4f5df23SVikas Chaudhary 		    for (i = 0; i < inCount; i++)
100f4f5df23SVikas Chaudhary 			printk("mb%d=%04x ", i, mbx_cmd[i]);
101f4f5df23SVikas Chaudhary 		    printk("\n"));
102f4f5df23SVikas Chaudhary 
103f4f5df23SVikas Chaudhary 		for (i = 1; i < inCount; i++)
104f4f5df23SVikas Chaudhary 			writel(mbx_cmd[i], &ha->qla4_8xxx_reg->mailbox_in[i]);
105f4f5df23SVikas Chaudhary 		writel(mbx_cmd[0], &ha->qla4_8xxx_reg->mailbox_in[0]);
106f4f5df23SVikas Chaudhary 		readl(&ha->qla4_8xxx_reg->mailbox_in[0]);
107f4f5df23SVikas Chaudhary 		writel(HINT_MBX_INT_PENDING, &ha->qla4_8xxx_reg->hint);
108f4f5df23SVikas Chaudhary 	} else {
109afaf5a2dSDavid Somayajulu 		/* Load all mailbox registers, except mailbox 0. */
110afaf5a2dSDavid Somayajulu 		for (i = 1; i < inCount; i++)
111afaf5a2dSDavid Somayajulu 			writel(mbx_cmd[i], &ha->reg->mailbox[i]);
112afaf5a2dSDavid Somayajulu 
113afaf5a2dSDavid Somayajulu 		/* Wakeup firmware  */
114afaf5a2dSDavid Somayajulu 		writel(mbx_cmd[0], &ha->reg->mailbox[0]);
115afaf5a2dSDavid Somayajulu 		readl(&ha->reg->mailbox[0]);
116afaf5a2dSDavid Somayajulu 		writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status);
117afaf5a2dSDavid Somayajulu 		readl(&ha->reg->ctrl_status);
118f4f5df23SVikas Chaudhary 	}
119f4f5df23SVikas Chaudhary 
120afaf5a2dSDavid Somayajulu 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
121afaf5a2dSDavid Somayajulu 
122afaf5a2dSDavid Somayajulu 	/* Wait for completion */
123afaf5a2dSDavid Somayajulu 
124afaf5a2dSDavid Somayajulu 	/*
125afaf5a2dSDavid Somayajulu 	 * If we don't want status, don't wait for the mailbox command to
126afaf5a2dSDavid Somayajulu 	 * complete.  For example, MBOX_CMD_RESET_FW doesn't return status,
127afaf5a2dSDavid Somayajulu 	 * you must poll the inbound Interrupt Mask for completion.
128afaf5a2dSDavid Somayajulu 	 */
129afaf5a2dSDavid Somayajulu 	if (outCount == 0) {
130afaf5a2dSDavid Somayajulu 		status = QLA_SUCCESS;
131afaf5a2dSDavid Somayajulu 		goto mbox_exit;
132afaf5a2dSDavid Somayajulu 	}
133f4f5df23SVikas Chaudhary 
134f4f5df23SVikas Chaudhary 	/*
135f4f5df23SVikas Chaudhary 	 * Wait for completion: Poll or completion queue
136f4f5df23SVikas Chaudhary 	 */
137f4f5df23SVikas Chaudhary 	if (test_bit(AF_IRQ_ATTACHED, &ha->flags) &&
138f4f5df23SVikas Chaudhary 	    test_bit(AF_INTERRUPTS_ON, &ha->flags) &&
139f4f5df23SVikas Chaudhary 	    test_bit(AF_ONLINE, &ha->flags) &&
1407eece5a0SKaren Higgins 	    !test_bit(AF_HA_REMOVAL, &ha->flags)) {
141f4f5df23SVikas Chaudhary 		/* Do not poll for completion. Use completion queue */
142f4f5df23SVikas Chaudhary 		set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
143f4f5df23SVikas Chaudhary 		wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ);
144f4f5df23SVikas Chaudhary 		clear_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
145f4f5df23SVikas Chaudhary 	} else {
146f4f5df23SVikas Chaudhary 		/* Poll for command to complete */
147afaf5a2dSDavid Somayajulu 		wait_count = jiffies + MBOX_TOV * HZ;
148afaf5a2dSDavid Somayajulu 		while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) {
149afaf5a2dSDavid Somayajulu 			if (time_after_eq(jiffies, wait_count))
150afaf5a2dSDavid Somayajulu 				break;
1512232be0dSLalit Chandivade 
152afaf5a2dSDavid Somayajulu 			/*
153afaf5a2dSDavid Somayajulu 			 * Service the interrupt.
154afaf5a2dSDavid Somayajulu 			 * The ISR will save the mailbox status registers
155afaf5a2dSDavid Somayajulu 			 * to a temporary storage location in the adapter
156afaf5a2dSDavid Somayajulu 			 * structure.
157afaf5a2dSDavid Somayajulu 			 */
158f4f5df23SVikas Chaudhary 
159f4f5df23SVikas Chaudhary 			spin_lock_irqsave(&ha->hardware_lock, flags);
160f4f5df23SVikas Chaudhary 			if (is_qla8022(ha)) {
161f4f5df23SVikas Chaudhary 				intr_status =
162f4f5df23SVikas Chaudhary 				    readl(&ha->qla4_8xxx_reg->host_int);
163f4f5df23SVikas Chaudhary 				if (intr_status & ISRX_82XX_RISC_INT) {
164afaf5a2dSDavid Somayajulu 					ha->mbox_status_count = outCount;
165f4f5df23SVikas Chaudhary 					intr_status =
166f4f5df23SVikas Chaudhary 					 readl(&ha->qla4_8xxx_reg->host_status);
167f4f5df23SVikas Chaudhary 					ha->isp_ops->interrupt_service_routine(
168f4f5df23SVikas Chaudhary 					    ha, intr_status);
169f4f5df23SVikas Chaudhary 					if (test_bit(AF_INTERRUPTS_ON,
170f4f5df23SVikas Chaudhary 					    &ha->flags) &&
171f4f5df23SVikas Chaudhary 					    test_bit(AF_INTx_ENABLED,
172f4f5df23SVikas Chaudhary 					    &ha->flags))
173f4f5df23SVikas Chaudhary 						qla4_8xxx_wr_32(ha,
174f4f5df23SVikas Chaudhary 						ha->nx_legacy_intr.tgt_mask_reg,
175f4f5df23SVikas Chaudhary 						0xfbff);
176f4f5df23SVikas Chaudhary 				}
177f4f5df23SVikas Chaudhary 			} else {
178f4f5df23SVikas Chaudhary 				intr_status = readl(&ha->reg->ctrl_status);
179f4f5df23SVikas Chaudhary 				if (intr_status & INTR_PENDING) {
180f4f5df23SVikas Chaudhary 					/*
181f4f5df23SVikas Chaudhary 					 * Service the interrupt.
182f4f5df23SVikas Chaudhary 					 * The ISR will save the mailbox status
183f4f5df23SVikas Chaudhary 					 * registers to a temporary storage
184f4f5df23SVikas Chaudhary 					 * location in the adapter structure.
185f4f5df23SVikas Chaudhary 					 */
186f4f5df23SVikas Chaudhary 					ha->mbox_status_count = outCount;
187f4f5df23SVikas Chaudhary 					ha->isp_ops->interrupt_service_routine(
188f4f5df23SVikas Chaudhary 					    ha, intr_status);
189f4f5df23SVikas Chaudhary 				}
190afaf5a2dSDavid Somayajulu 			}
191afaf5a2dSDavid Somayajulu 			spin_unlock_irqrestore(&ha->hardware_lock, flags);
192afaf5a2dSDavid Somayajulu 			msleep(10);
193afaf5a2dSDavid Somayajulu 		}
194f4f5df23SVikas Chaudhary 	}
195afaf5a2dSDavid Somayajulu 
196afaf5a2dSDavid Somayajulu 	/* Check for mailbox timeout. */
197afaf5a2dSDavid Somayajulu 	if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) {
19821033639SNilesh Javali 		if (is_qla8022(ha) &&
19921033639SNilesh Javali 		    test_bit(AF_FW_RECOVERY, &ha->flags)) {
20021033639SNilesh Javali 			DEBUG2(ql4_printk(KERN_INFO, ha,
20121033639SNilesh Javali 			    "scsi%ld: %s: prematurely completing mbx cmd as "
20221033639SNilesh Javali 			    "firmware recovery detected\n",
20321033639SNilesh Javali 			    ha->host_no, __func__));
20421033639SNilesh Javali 			goto mbox_exit;
20521033639SNilesh Javali 		}
206afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: Mailbox Cmd 0x%08X timed out ...,"
207afaf5a2dSDavid Somayajulu 			      " Scheduling Adapter Reset\n", ha->host_no,
208afaf5a2dSDavid Somayajulu 			      mbx_cmd[0]));
209afaf5a2dSDavid Somayajulu 		ha->mailbox_timeout_count++;
210afaf5a2dSDavid Somayajulu 		mbx_sts[0] = (-1);
211afaf5a2dSDavid Somayajulu 		set_bit(DPC_RESET_HA, &ha->dpc_flags);
212afaf5a2dSDavid Somayajulu 		goto mbox_exit;
213afaf5a2dSDavid Somayajulu 	}
214afaf5a2dSDavid Somayajulu 
215afaf5a2dSDavid Somayajulu 	/*
216afaf5a2dSDavid Somayajulu 	 * Copy the mailbox out registers to the caller's mailbox in/out
217afaf5a2dSDavid Somayajulu 	 * structure.
218afaf5a2dSDavid Somayajulu 	 */
219afaf5a2dSDavid Somayajulu 	spin_lock_irqsave(&ha->hardware_lock, flags);
220afaf5a2dSDavid Somayajulu 	for (i = 0; i < outCount; i++)
221afaf5a2dSDavid Somayajulu 		mbx_sts[i] = ha->mbox_status[i];
222afaf5a2dSDavid Somayajulu 
223afaf5a2dSDavid Somayajulu 	/* Set return status and error flags (if applicable). */
224afaf5a2dSDavid Somayajulu 	switch (ha->mbox_status[0]) {
225afaf5a2dSDavid Somayajulu 	case MBOX_STS_COMMAND_COMPLETE:
226afaf5a2dSDavid Somayajulu 		status = QLA_SUCCESS;
227afaf5a2dSDavid Somayajulu 		break;
228afaf5a2dSDavid Somayajulu 
229afaf5a2dSDavid Somayajulu 	case MBOX_STS_INTERMEDIATE_COMPLETION:
230afaf5a2dSDavid Somayajulu 		status = QLA_SUCCESS;
231afaf5a2dSDavid Somayajulu 		break;
232afaf5a2dSDavid Somayajulu 
233afaf5a2dSDavid Somayajulu 	case MBOX_STS_BUSY:
234afaf5a2dSDavid Somayajulu 		DEBUG2( printk("scsi%ld: %s: Cmd = %08X, ISP BUSY\n",
235afaf5a2dSDavid Somayajulu 			       ha->host_no, __func__, mbx_cmd[0]));
236afaf5a2dSDavid Somayajulu 		ha->mailbox_timeout_count++;
237afaf5a2dSDavid Somayajulu 		break;
238afaf5a2dSDavid Somayajulu 
239afaf5a2dSDavid Somayajulu 	default:
240afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: **** FAILED, cmd = %08X, "
241afaf5a2dSDavid Somayajulu 			      "sts = %08X ****\n", ha->host_no, __func__,
242afaf5a2dSDavid Somayajulu 			      mbx_cmd[0], mbx_sts[0]));
243afaf5a2dSDavid Somayajulu 		break;
244afaf5a2dSDavid Somayajulu 	}
245afaf5a2dSDavid Somayajulu 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
246afaf5a2dSDavid Somayajulu 
247afaf5a2dSDavid Somayajulu mbox_exit:
248477ffb9dSDavid C Somayajulu 	mutex_lock(&ha->mbox_sem);
249afaf5a2dSDavid Somayajulu 	clear_bit(AF_MBOX_COMMAND, &ha->flags);
250afaf5a2dSDavid Somayajulu 	mutex_unlock(&ha->mbox_sem);
251477ffb9dSDavid C Somayajulu 	clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
252afaf5a2dSDavid Somayajulu 
253afaf5a2dSDavid Somayajulu 	return status;
254afaf5a2dSDavid Somayajulu }
255afaf5a2dSDavid Somayajulu 
25621033639SNilesh Javali void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha)
25721033639SNilesh Javali {
25821033639SNilesh Javali 	set_bit(AF_FW_RECOVERY, &ha->flags);
25921033639SNilesh Javali 	ql4_printk(KERN_INFO, ha, "scsi%ld: %s: set FW RECOVERY!\n",
26021033639SNilesh Javali 	    ha->host_no, __func__);
26121033639SNilesh Javali 
26221033639SNilesh Javali 	if (test_bit(AF_MBOX_COMMAND, &ha->flags)) {
26321033639SNilesh Javali 		if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags)) {
26421033639SNilesh Javali 			complete(&ha->mbx_intr_comp);
26521033639SNilesh Javali 			ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw "
26621033639SNilesh Javali 			    "recovery, doing premature completion of "
26721033639SNilesh Javali 			    "mbx cmd\n", ha->host_no, __func__);
26821033639SNilesh Javali 
26921033639SNilesh Javali 		} else {
27021033639SNilesh Javali 			set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
27121033639SNilesh Javali 			ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw "
27221033639SNilesh Javali 			    "recovery, doing premature completion of "
27321033639SNilesh Javali 			    "polling mbx cmd\n", ha->host_no, __func__);
27421033639SNilesh Javali 		}
27521033639SNilesh Javali 	}
27621033639SNilesh Javali }
27721033639SNilesh Javali 
278f4f5df23SVikas Chaudhary static uint8_t
2792a49a78eSVikas Chaudhary qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
2802a49a78eSVikas Chaudhary 		 uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)
2812a49a78eSVikas Chaudhary {
2822a49a78eSVikas Chaudhary 	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
2832a49a78eSVikas Chaudhary 	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
2842657c800SShyam Sundar 
2852657c800SShyam Sundar 	if (is_qla8022(ha))
2862657c800SShyam Sundar 		qla4_8xxx_wr_32(ha, ha->nx_db_wr_ptr, 0);
2872657c800SShyam Sundar 
2882a49a78eSVikas Chaudhary 	mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE;
2892a49a78eSVikas Chaudhary 	mbox_cmd[1] = 0;
2902a49a78eSVikas Chaudhary 	mbox_cmd[2] = LSDW(init_fw_cb_dma);
2912a49a78eSVikas Chaudhary 	mbox_cmd[3] = MSDW(init_fw_cb_dma);
2922a49a78eSVikas Chaudhary 	mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
2932a49a78eSVikas Chaudhary 	mbox_cmd[5] = (IFCB_VER_MAX << 8) | IFCB_VER_MIN;
2942a49a78eSVikas Chaudhary 
2952a49a78eSVikas Chaudhary 	if (qla4xxx_mailbox_command(ha, 6, 6, mbox_cmd, mbox_sts) !=
2962a49a78eSVikas Chaudhary 	    QLA_SUCCESS) {
2972a49a78eSVikas Chaudhary 		DEBUG2(printk(KERN_WARNING "scsi%ld: %s: "
2982a49a78eSVikas Chaudhary 			      "MBOX_CMD_INITIALIZE_FIRMWARE"
2992a49a78eSVikas Chaudhary 			      " failed w/ status %04X\n",
3002a49a78eSVikas Chaudhary 			      ha->host_no, __func__, mbox_sts[0]));
3012a49a78eSVikas Chaudhary 		return QLA_ERROR;
3022a49a78eSVikas Chaudhary 	}
3032a49a78eSVikas Chaudhary 	return QLA_SUCCESS;
3042a49a78eSVikas Chaudhary }
3052a49a78eSVikas Chaudhary 
306d00efe3fSMike Christie uint8_t
3072a49a78eSVikas Chaudhary qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
3082a49a78eSVikas Chaudhary 		 uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)
3092a49a78eSVikas Chaudhary {
3102a49a78eSVikas Chaudhary 	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
3112a49a78eSVikas Chaudhary 	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
3122a49a78eSVikas Chaudhary 	mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
3132a49a78eSVikas Chaudhary 	mbox_cmd[2] = LSDW(init_fw_cb_dma);
3142a49a78eSVikas Chaudhary 	mbox_cmd[3] = MSDW(init_fw_cb_dma);
3152a49a78eSVikas Chaudhary 	mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
3162a49a78eSVikas Chaudhary 
3172a49a78eSVikas Chaudhary 	if (qla4xxx_mailbox_command(ha, 5, 5, mbox_cmd, mbox_sts) !=
3182a49a78eSVikas Chaudhary 	    QLA_SUCCESS) {
3192a49a78eSVikas Chaudhary 		DEBUG2(printk(KERN_WARNING "scsi%ld: %s: "
3202a49a78eSVikas Chaudhary 			      "MBOX_CMD_GET_INIT_FW_CTRL_BLOCK"
3212a49a78eSVikas Chaudhary 			      " failed w/ status %04X\n",
3222a49a78eSVikas Chaudhary 			      ha->host_no, __func__, mbox_sts[0]));
3232a49a78eSVikas Chaudhary 		return QLA_ERROR;
3242a49a78eSVikas Chaudhary 	}
3252a49a78eSVikas Chaudhary 	return QLA_SUCCESS;
3262a49a78eSVikas Chaudhary }
3272a49a78eSVikas Chaudhary 
328f4f5df23SVikas Chaudhary static void
3292a49a78eSVikas Chaudhary qla4xxx_update_local_ip(struct scsi_qla_host *ha,
3302a49a78eSVikas Chaudhary 			struct addr_ctrl_blk *init_fw_cb)
3312a49a78eSVikas Chaudhary {
3322bab08fcSVikas Chaudhary 	ha->ip_config.tcp_options = le16_to_cpu(init_fw_cb->ipv4_tcp_opts);
3332bab08fcSVikas Chaudhary 	ha->ip_config.ipv4_options = le16_to_cpu(init_fw_cb->ipv4_ip_opts);
3342bab08fcSVikas Chaudhary 	ha->ip_config.ipv4_addr_state =
3352bab08fcSVikas Chaudhary 				le16_to_cpu(init_fw_cb->ipv4_addr_state);
336943c157bSVikas Chaudhary 	ha->ip_config.eth_mtu_size =
337943c157bSVikas Chaudhary 				le16_to_cpu(init_fw_cb->eth_mtu_size);
3382ada7fc5SVikas Chaudhary 	ha->ip_config.ipv4_port = le16_to_cpu(init_fw_cb->ipv4_port);
3392bab08fcSVikas Chaudhary 
3402bab08fcSVikas Chaudhary 	if (ha->acb_version == ACB_SUPPORTED) {
3412bab08fcSVikas Chaudhary 		ha->ip_config.ipv6_options = le16_to_cpu(init_fw_cb->ipv6_opts);
3422bab08fcSVikas Chaudhary 		ha->ip_config.ipv6_addl_options =
3432bab08fcSVikas Chaudhary 				le16_to_cpu(init_fw_cb->ipv6_addtl_opts);
3442bab08fcSVikas Chaudhary 	}
3452bab08fcSVikas Chaudhary 
3462a49a78eSVikas Chaudhary 	/* Save IPv4 Address Info */
3472bab08fcSVikas Chaudhary 	memcpy(ha->ip_config.ip_address, init_fw_cb->ipv4_addr,
3482bab08fcSVikas Chaudhary 	       min(sizeof(ha->ip_config.ip_address),
3492bab08fcSVikas Chaudhary 		   sizeof(init_fw_cb->ipv4_addr)));
3502bab08fcSVikas Chaudhary 	memcpy(ha->ip_config.subnet_mask, init_fw_cb->ipv4_subnet,
3512bab08fcSVikas Chaudhary 	       min(sizeof(ha->ip_config.subnet_mask),
3522bab08fcSVikas Chaudhary 		   sizeof(init_fw_cb->ipv4_subnet)));
3532bab08fcSVikas Chaudhary 	memcpy(ha->ip_config.gateway, init_fw_cb->ipv4_gw_addr,
3542bab08fcSVikas Chaudhary 	       min(sizeof(ha->ip_config.gateway),
3552bab08fcSVikas Chaudhary 		   sizeof(init_fw_cb->ipv4_gw_addr)));
3562a49a78eSVikas Chaudhary 
3576ac73e8cSVikas Chaudhary 	ha->ip_config.ipv4_vlan_tag = be16_to_cpu(init_fw_cb->ipv4_vlan_tag);
3586ac73e8cSVikas Chaudhary 
3592a49a78eSVikas Chaudhary 	if (is_ipv6_enabled(ha)) {
3602a49a78eSVikas Chaudhary 		/* Save IPv6 Address */
3612bab08fcSVikas Chaudhary 		ha->ip_config.ipv6_link_local_state =
3622bab08fcSVikas Chaudhary 			le16_to_cpu(init_fw_cb->ipv6_lnk_lcl_addr_state);
3632bab08fcSVikas Chaudhary 		ha->ip_config.ipv6_addr0_state =
3642bab08fcSVikas Chaudhary 				le16_to_cpu(init_fw_cb->ipv6_addr0_state);
3652bab08fcSVikas Chaudhary 		ha->ip_config.ipv6_addr1_state =
3662bab08fcSVikas Chaudhary 				le16_to_cpu(init_fw_cb->ipv6_addr1_state);
3672bab08fcSVikas Chaudhary 		ha->ip_config.ipv6_default_router_state =
3682bab08fcSVikas Chaudhary 				le16_to_cpu(init_fw_cb->ipv6_dflt_rtr_state);
3692bab08fcSVikas Chaudhary 		ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[0] = 0xFE;
3702bab08fcSVikas Chaudhary 		ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[1] = 0x80;
3712a49a78eSVikas Chaudhary 
3722bab08fcSVikas Chaudhary 		memcpy(&ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[8],
3732a49a78eSVikas Chaudhary 		       init_fw_cb->ipv6_if_id,
3742bab08fcSVikas Chaudhary 		       min(sizeof(ha->ip_config.ipv6_link_local_addr)/2,
3752a49a78eSVikas Chaudhary 			   sizeof(init_fw_cb->ipv6_if_id)));
3762bab08fcSVikas Chaudhary 		memcpy(&ha->ip_config.ipv6_addr0, init_fw_cb->ipv6_addr0,
3772bab08fcSVikas Chaudhary 		       min(sizeof(ha->ip_config.ipv6_addr0),
3782a49a78eSVikas Chaudhary 			   sizeof(init_fw_cb->ipv6_addr0)));
3792bab08fcSVikas Chaudhary 		memcpy(&ha->ip_config.ipv6_addr1, init_fw_cb->ipv6_addr1,
3802bab08fcSVikas Chaudhary 		       min(sizeof(ha->ip_config.ipv6_addr1),
3812a49a78eSVikas Chaudhary 			   sizeof(init_fw_cb->ipv6_addr1)));
3822bab08fcSVikas Chaudhary 		memcpy(&ha->ip_config.ipv6_default_router_addr,
3832a49a78eSVikas Chaudhary 		       init_fw_cb->ipv6_dflt_rtr_addr,
3842bab08fcSVikas Chaudhary 		       min(sizeof(ha->ip_config.ipv6_default_router_addr),
3852a49a78eSVikas Chaudhary 			   sizeof(init_fw_cb->ipv6_dflt_rtr_addr)));
3866ac73e8cSVikas Chaudhary 		ha->ip_config.ipv6_vlan_tag =
3876ac73e8cSVikas Chaudhary 				be16_to_cpu(init_fw_cb->ipv6_vlan_tag);
3882ada7fc5SVikas Chaudhary 		ha->ip_config.ipv6_port = le16_to_cpu(init_fw_cb->ipv6_port);
3892a49a78eSVikas Chaudhary 	}
3902a49a78eSVikas Chaudhary }
3912a49a78eSVikas Chaudhary 
392d00efe3fSMike Christie uint8_t
3932a49a78eSVikas Chaudhary qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
3942a49a78eSVikas Chaudhary 			  uint32_t *mbox_cmd,
3952a49a78eSVikas Chaudhary 			  uint32_t *mbox_sts,
3962a49a78eSVikas Chaudhary 			  struct addr_ctrl_blk  *init_fw_cb,
3972a49a78eSVikas Chaudhary 			  dma_addr_t init_fw_cb_dma)
3982a49a78eSVikas Chaudhary {
3992a49a78eSVikas Chaudhary 	if (qla4xxx_get_ifcb(ha, mbox_cmd, mbox_sts, init_fw_cb_dma)
4002a49a78eSVikas Chaudhary 	    != QLA_SUCCESS) {
4012a49a78eSVikas Chaudhary 		DEBUG2(printk(KERN_WARNING
4022a49a78eSVikas Chaudhary 			      "scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",
4032a49a78eSVikas Chaudhary 			      ha->host_no, __func__));
4042a49a78eSVikas Chaudhary 		return QLA_ERROR;
4052a49a78eSVikas Chaudhary 	}
4062a49a78eSVikas Chaudhary 
4072a49a78eSVikas Chaudhary 	DEBUG2(qla4xxx_dump_buffer(init_fw_cb, sizeof(struct addr_ctrl_blk)));
4082a49a78eSVikas Chaudhary 
4092a49a78eSVikas Chaudhary 	/* Save some info in adapter structure. */
4102a49a78eSVikas Chaudhary 	ha->acb_version = init_fw_cb->acb_version;
4112a49a78eSVikas Chaudhary 	ha->firmware_options = le16_to_cpu(init_fw_cb->fw_options);
4122a49a78eSVikas Chaudhary 	ha->heartbeat_interval = init_fw_cb->hb_interval;
4132a49a78eSVikas Chaudhary 	memcpy(ha->name_string, init_fw_cb->iscsi_name,
4142a49a78eSVikas Chaudhary 		min(sizeof(ha->name_string),
4152a49a78eSVikas Chaudhary 		sizeof(init_fw_cb->iscsi_name)));
4162a49a78eSVikas Chaudhary 	/*memcpy(ha->alias, init_fw_cb->Alias,
4172a49a78eSVikas Chaudhary 	       min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/
4182a49a78eSVikas Chaudhary 
4192a49a78eSVikas Chaudhary 	qla4xxx_update_local_ip(ha, init_fw_cb);
4202a49a78eSVikas Chaudhary 
4212a49a78eSVikas Chaudhary 	return QLA_SUCCESS;
4222a49a78eSVikas Chaudhary }
4232a49a78eSVikas Chaudhary 
424afaf5a2dSDavid Somayajulu /**
425afaf5a2dSDavid Somayajulu  * qla4xxx_initialize_fw_cb - initializes firmware control block.
426afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
427afaf5a2dSDavid Somayajulu  **/
428afaf5a2dSDavid Somayajulu int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
429afaf5a2dSDavid Somayajulu {
4302a49a78eSVikas Chaudhary 	struct addr_ctrl_blk *init_fw_cb;
431afaf5a2dSDavid Somayajulu 	dma_addr_t init_fw_cb_dma;
432afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
433afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
434afaf5a2dSDavid Somayajulu 	int status = QLA_ERROR;
435afaf5a2dSDavid Somayajulu 
436afaf5a2dSDavid Somayajulu 	init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
4372a49a78eSVikas Chaudhary 					sizeof(struct addr_ctrl_blk),
438afaf5a2dSDavid Somayajulu 					&init_fw_cb_dma, GFP_KERNEL);
439afaf5a2dSDavid Somayajulu 	if (init_fw_cb == NULL) {
440afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n",
441afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__));
442beabe7c1SPrasanna Mumbai 		goto exit_init_fw_cb_no_free;
443afaf5a2dSDavid Somayajulu 	}
4442a49a78eSVikas Chaudhary 	memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
445afaf5a2dSDavid Somayajulu 
446afaf5a2dSDavid Somayajulu 	/* Get Initialize Firmware Control Block. */
447afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
448afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
449c0e344c9SDavid C Somayajulu 
4502a49a78eSVikas Chaudhary 	if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) !=
451afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
452afaf5a2dSDavid Somayajulu 		dma_free_coherent(&ha->pdev->dev,
4532a49a78eSVikas Chaudhary 				  sizeof(struct addr_ctrl_blk),
454afaf5a2dSDavid Somayajulu 				  init_fw_cb, init_fw_cb_dma);
4552a49a78eSVikas Chaudhary 		goto exit_init_fw_cb;
456afaf5a2dSDavid Somayajulu 	}
457afaf5a2dSDavid Somayajulu 
458afaf5a2dSDavid Somayajulu 	/* Initialize request and response queues. */
459afaf5a2dSDavid Somayajulu 	qla4xxx_init_rings(ha);
460afaf5a2dSDavid Somayajulu 
461afaf5a2dSDavid Somayajulu 	/* Fill in the request and response queue information. */
4622a49a78eSVikas Chaudhary 	init_fw_cb->rqq_consumer_idx = cpu_to_le16(ha->request_out);
4632a49a78eSVikas Chaudhary 	init_fw_cb->compq_producer_idx = cpu_to_le16(ha->response_in);
4642a49a78eSVikas Chaudhary 	init_fw_cb->rqq_len = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH);
4652a49a78eSVikas Chaudhary 	init_fw_cb->compq_len = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH);
4662a49a78eSVikas Chaudhary 	init_fw_cb->rqq_addr_lo = cpu_to_le32(LSDW(ha->request_dma));
4672a49a78eSVikas Chaudhary 	init_fw_cb->rqq_addr_hi = cpu_to_le32(MSDW(ha->request_dma));
4682a49a78eSVikas Chaudhary 	init_fw_cb->compq_addr_lo = cpu_to_le32(LSDW(ha->response_dma));
4692a49a78eSVikas Chaudhary 	init_fw_cb->compq_addr_hi = cpu_to_le32(MSDW(ha->response_dma));
4702a49a78eSVikas Chaudhary 	init_fw_cb->shdwreg_addr_lo = cpu_to_le32(LSDW(ha->shadow_regs_dma));
4712a49a78eSVikas Chaudhary 	init_fw_cb->shdwreg_addr_hi = cpu_to_le32(MSDW(ha->shadow_regs_dma));
472afaf5a2dSDavid Somayajulu 
473afaf5a2dSDavid Somayajulu 	/* Set up required options. */
4742a49a78eSVikas Chaudhary 	init_fw_cb->fw_options |=
475afaf5a2dSDavid Somayajulu 		__constant_cpu_to_le16(FWOPT_SESSION_MODE |
476afaf5a2dSDavid Somayajulu 				       FWOPT_INITIATOR_MODE);
4772657c800SShyam Sundar 
4782657c800SShyam Sundar 	if (is_qla8022(ha))
4792657c800SShyam Sundar 		init_fw_cb->fw_options |=
4802657c800SShyam Sundar 		    __constant_cpu_to_le16(FWOPT_ENABLE_CRBDB);
4812657c800SShyam Sundar 
4822a49a78eSVikas Chaudhary 	init_fw_cb->fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
483afaf5a2dSDavid Somayajulu 
484d32cee3cSPrasanna Mumbai 	init_fw_cb->add_fw_options = 0;
485d32cee3cSPrasanna Mumbai 	init_fw_cb->add_fw_options |=
486b3a271a9SManish Rangankar 			__constant_cpu_to_le16(ADFWOPT_SERIALIZE_TASK_MGMT);
487b3a271a9SManish Rangankar 	init_fw_cb->add_fw_options |=
488b3a271a9SManish Rangankar 			__constant_cpu_to_le16(ADFWOPT_AUTOCONN_DISABLE);
489d32cee3cSPrasanna Mumbai 
4902a49a78eSVikas Chaudhary 	if (qla4xxx_set_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)
4912a49a78eSVikas Chaudhary 		!= QLA_SUCCESS) {
4922a49a78eSVikas Chaudhary 		DEBUG2(printk(KERN_WARNING
4932a49a78eSVikas Chaudhary 			      "scsi%ld: %s: Failed to set init_fw_ctrl_blk\n",
4942a49a78eSVikas Chaudhary 			      ha->host_no, __func__));
4952a49a78eSVikas Chaudhary 		goto exit_init_fw_cb;
496afaf5a2dSDavid Somayajulu 	}
4972a49a78eSVikas Chaudhary 
4982a49a78eSVikas Chaudhary 	if (qla4xxx_update_local_ifcb(ha, &mbox_cmd[0], &mbox_sts[0],
4992a49a78eSVikas Chaudhary 		init_fw_cb, init_fw_cb_dma) != QLA_SUCCESS) {
5002a49a78eSVikas Chaudhary 		DEBUG2(printk("scsi%ld: %s: Failed to update local ifcb\n",
5012a49a78eSVikas Chaudhary 				ha->host_no, __func__));
5022a49a78eSVikas Chaudhary 		goto exit_init_fw_cb;
5032a49a78eSVikas Chaudhary 	}
5042a49a78eSVikas Chaudhary 	status = QLA_SUCCESS;
5052a49a78eSVikas Chaudhary 
5062a49a78eSVikas Chaudhary exit_init_fw_cb:
5072a49a78eSVikas Chaudhary 	dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
508afaf5a2dSDavid Somayajulu 				init_fw_cb, init_fw_cb_dma);
509beabe7c1SPrasanna Mumbai exit_init_fw_cb_no_free:
510afaf5a2dSDavid Somayajulu 	return status;
511afaf5a2dSDavid Somayajulu }
512afaf5a2dSDavid Somayajulu 
513afaf5a2dSDavid Somayajulu /**
514afaf5a2dSDavid Somayajulu  * qla4xxx_get_dhcp_ip_address - gets HBA ip address via DHCP
515afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
516afaf5a2dSDavid Somayajulu  **/
517afaf5a2dSDavid Somayajulu int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha)
518afaf5a2dSDavid Somayajulu {
5192a49a78eSVikas Chaudhary 	struct addr_ctrl_blk *init_fw_cb;
520afaf5a2dSDavid Somayajulu 	dma_addr_t init_fw_cb_dma;
521afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
522afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
523afaf5a2dSDavid Somayajulu 
524afaf5a2dSDavid Somayajulu 	init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
5252a49a78eSVikas Chaudhary 					sizeof(struct addr_ctrl_blk),
526afaf5a2dSDavid Somayajulu 					&init_fw_cb_dma, GFP_KERNEL);
527afaf5a2dSDavid Somayajulu 	if (init_fw_cb == NULL) {
528afaf5a2dSDavid Somayajulu 		printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no,
529afaf5a2dSDavid Somayajulu 		       __func__);
530beabe7c1SPrasanna Mumbai 		return QLA_ERROR;
531afaf5a2dSDavid Somayajulu 	}
532afaf5a2dSDavid Somayajulu 
533afaf5a2dSDavid Somayajulu 	/* Get Initialize Firmware Control Block. */
5342a49a78eSVikas Chaudhary 	memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
5352a49a78eSVikas Chaudhary 	if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) !=
536afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
537afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",
538afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__));
539afaf5a2dSDavid Somayajulu 		dma_free_coherent(&ha->pdev->dev,
5402a49a78eSVikas Chaudhary 				  sizeof(struct addr_ctrl_blk),
541afaf5a2dSDavid Somayajulu 				  init_fw_cb, init_fw_cb_dma);
542afaf5a2dSDavid Somayajulu 		return QLA_ERROR;
543afaf5a2dSDavid Somayajulu 	}
544afaf5a2dSDavid Somayajulu 
545afaf5a2dSDavid Somayajulu 	/* Save IP Address. */
5462a49a78eSVikas Chaudhary 	qla4xxx_update_local_ip(ha, init_fw_cb);
5472a49a78eSVikas Chaudhary 	dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
548afaf5a2dSDavid Somayajulu 				init_fw_cb, init_fw_cb_dma);
549afaf5a2dSDavid Somayajulu 
550afaf5a2dSDavid Somayajulu 	return QLA_SUCCESS;
551afaf5a2dSDavid Somayajulu }
552afaf5a2dSDavid Somayajulu 
553afaf5a2dSDavid Somayajulu /**
554afaf5a2dSDavid Somayajulu  * qla4xxx_get_firmware_state - gets firmware state of HBA
555afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
556afaf5a2dSDavid Somayajulu  **/
557afaf5a2dSDavid Somayajulu int qla4xxx_get_firmware_state(struct scsi_qla_host * ha)
558afaf5a2dSDavid Somayajulu {
559afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
560afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
561afaf5a2dSDavid Somayajulu 
562afaf5a2dSDavid Somayajulu 	/* Get firmware version */
563afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
564afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
565c0e344c9SDavid C Somayajulu 
566afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_FW_STATE;
567c0e344c9SDavid C Somayajulu 
568c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 4, &mbox_cmd[0], &mbox_sts[0]) !=
569afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
570afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ "
571afaf5a2dSDavid Somayajulu 			      "status %04X\n", ha->host_no, __func__,
572afaf5a2dSDavid Somayajulu 			      mbox_sts[0]));
573afaf5a2dSDavid Somayajulu 		return QLA_ERROR;
574afaf5a2dSDavid Somayajulu 	}
575afaf5a2dSDavid Somayajulu 	ha->firmware_state = mbox_sts[1];
576afaf5a2dSDavid Somayajulu 	ha->board_id = mbox_sts[2];
577afaf5a2dSDavid Somayajulu 	ha->addl_fw_state = mbox_sts[3];
578afaf5a2dSDavid Somayajulu 	DEBUG2(printk("scsi%ld: %s firmware_state=0x%x\n",
579afaf5a2dSDavid Somayajulu 		      ha->host_no, __func__, ha->firmware_state);)
580afaf5a2dSDavid Somayajulu 
581afaf5a2dSDavid Somayajulu 	return QLA_SUCCESS;
582afaf5a2dSDavid Somayajulu }
583afaf5a2dSDavid Somayajulu 
584afaf5a2dSDavid Somayajulu /**
585afaf5a2dSDavid Somayajulu  * qla4xxx_get_firmware_status - retrieves firmware status
586afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
587afaf5a2dSDavid Somayajulu  **/
588afaf5a2dSDavid Somayajulu int qla4xxx_get_firmware_status(struct scsi_qla_host * ha)
589afaf5a2dSDavid Somayajulu {
590afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
591afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
592afaf5a2dSDavid Somayajulu 
593afaf5a2dSDavid Somayajulu 	/* Get firmware version */
594afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
595afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
596c0e344c9SDavid C Somayajulu 
597afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS;
598c0e344c9SDavid C Somayajulu 
599c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) !=
600afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
601afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ "
602afaf5a2dSDavid Somayajulu 			      "status %04X\n", ha->host_no, __func__,
603afaf5a2dSDavid Somayajulu 			      mbox_sts[0]));
604afaf5a2dSDavid Somayajulu 		return QLA_ERROR;
605afaf5a2dSDavid Somayajulu 	}
606f4f5df23SVikas Chaudhary 
607f4f5df23SVikas Chaudhary 	ql4_printk(KERN_INFO, ha, "%ld firmare IOCBs available (%d).\n",
608f581a3f7SVikas Chaudhary 	    ha->host_no, mbox_sts[2]);
609f4f5df23SVikas Chaudhary 
610afaf5a2dSDavid Somayajulu 	return QLA_SUCCESS;
611afaf5a2dSDavid Somayajulu }
612afaf5a2dSDavid Somayajulu 
613afaf5a2dSDavid Somayajulu /**
614afaf5a2dSDavid Somayajulu  * qla4xxx_get_fwddb_entry - retrieves firmware ddb entry
615afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
616afaf5a2dSDavid Somayajulu  * @fw_ddb_index: Firmware's device database index
617afaf5a2dSDavid Somayajulu  * @fw_ddb_entry: Pointer to firmware's device database entry structure
618afaf5a2dSDavid Somayajulu  * @num_valid_ddb_entries: Pointer to number of valid ddb entries
619afaf5a2dSDavid Somayajulu  * @next_ddb_index: Pointer to next valid device database index
620afaf5a2dSDavid Somayajulu  * @fw_ddb_device_state: Pointer to device state
621afaf5a2dSDavid Somayajulu  **/
622afaf5a2dSDavid Somayajulu int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
623afaf5a2dSDavid Somayajulu 			    uint16_t fw_ddb_index,
624afaf5a2dSDavid Somayajulu 			    struct dev_db_entry *fw_ddb_entry,
625afaf5a2dSDavid Somayajulu 			    dma_addr_t fw_ddb_entry_dma,
626afaf5a2dSDavid Somayajulu 			    uint32_t *num_valid_ddb_entries,
627afaf5a2dSDavid Somayajulu 			    uint32_t *next_ddb_index,
628afaf5a2dSDavid Somayajulu 			    uint32_t *fw_ddb_device_state,
629afaf5a2dSDavid Somayajulu 			    uint32_t *conn_err_detail,
630afaf5a2dSDavid Somayajulu 			    uint16_t *tcp_source_port_num,
631afaf5a2dSDavid Somayajulu 			    uint16_t *connection_id)
632afaf5a2dSDavid Somayajulu {
633afaf5a2dSDavid Somayajulu 	int status = QLA_ERROR;
6342a49a78eSVikas Chaudhary 	uint16_t options;
635afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
636afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
637afaf5a2dSDavid Somayajulu 
638afaf5a2dSDavid Somayajulu 	/* Make sure the device index is valid */
639afaf5a2dSDavid Somayajulu 	if (fw_ddb_index >= MAX_DDB_ENTRIES) {
640f4f5df23SVikas Chaudhary 		DEBUG2(printk("scsi%ld: %s: ddb [%d] out of range.\n",
641afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__, fw_ddb_index));
642afaf5a2dSDavid Somayajulu 		goto exit_get_fwddb;
643afaf5a2dSDavid Somayajulu 	}
644afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
645afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
646c0e344c9SDavid C Somayajulu 
647afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY;
648afaf5a2dSDavid Somayajulu 	mbox_cmd[1] = (uint32_t) fw_ddb_index;
649afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
650afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
651c0e344c9SDavid C Somayajulu 	mbox_cmd[4] = sizeof(struct dev_db_entry);
652c0e344c9SDavid C Somayajulu 
653c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 7, &mbox_cmd[0], &mbox_sts[0]) ==
654afaf5a2dSDavid Somayajulu 	    QLA_ERROR) {
655afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed"
656afaf5a2dSDavid Somayajulu 			      " with status 0x%04X\n", ha->host_no, __func__,
657afaf5a2dSDavid Somayajulu 			      mbox_sts[0]));
658afaf5a2dSDavid Somayajulu 		goto exit_get_fwddb;
659afaf5a2dSDavid Somayajulu 	}
660afaf5a2dSDavid Somayajulu 	if (fw_ddb_index != mbox_sts[1]) {
661f4f5df23SVikas Chaudhary 		DEBUG2(printk("scsi%ld: %s: ddb mismatch [%d] != [%d].\n",
662afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__, fw_ddb_index,
663afaf5a2dSDavid Somayajulu 			      mbox_sts[1]));
664afaf5a2dSDavid Somayajulu 		goto exit_get_fwddb;
665afaf5a2dSDavid Somayajulu 	}
666afaf5a2dSDavid Somayajulu 	if (fw_ddb_entry) {
6672a49a78eSVikas Chaudhary 		options = le16_to_cpu(fw_ddb_entry->options);
6682a49a78eSVikas Chaudhary 		if (options & DDB_OPT_IPV6_DEVICE) {
669c2660df3SVikas Chaudhary 			ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d "
6702a49a78eSVikas Chaudhary 				"Next %d State %04x ConnErr %08x %pI6 "
6712a49a78eSVikas Chaudhary 				":%04d \"%s\"\n", __func__, fw_ddb_index,
6722a49a78eSVikas Chaudhary 				mbox_sts[0], mbox_sts[2], mbox_sts[3],
6732a49a78eSVikas Chaudhary 				mbox_sts[4], mbox_sts[5],
6742a49a78eSVikas Chaudhary 				fw_ddb_entry->ip_addr,
675c0e344c9SDavid C Somayajulu 				le16_to_cpu(fw_ddb_entry->port),
676c0e344c9SDavid C Somayajulu 				fw_ddb_entry->iscsi_name);
6772a49a78eSVikas Chaudhary 		} else {
678c2660df3SVikas Chaudhary 			ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d "
6792a49a78eSVikas Chaudhary 				"Next %d State %04x ConnErr %08x %pI4 "
6802a49a78eSVikas Chaudhary 				":%04d \"%s\"\n", __func__, fw_ddb_index,
6812a49a78eSVikas Chaudhary 				mbox_sts[0], mbox_sts[2], mbox_sts[3],
6822a49a78eSVikas Chaudhary 				mbox_sts[4], mbox_sts[5],
6832a49a78eSVikas Chaudhary 				fw_ddb_entry->ip_addr,
6842a49a78eSVikas Chaudhary 				le16_to_cpu(fw_ddb_entry->port),
6852a49a78eSVikas Chaudhary 				fw_ddb_entry->iscsi_name);
6862a49a78eSVikas Chaudhary 		}
687afaf5a2dSDavid Somayajulu 	}
688afaf5a2dSDavid Somayajulu 	if (num_valid_ddb_entries)
689afaf5a2dSDavid Somayajulu 		*num_valid_ddb_entries = mbox_sts[2];
690afaf5a2dSDavid Somayajulu 	if (next_ddb_index)
691afaf5a2dSDavid Somayajulu 		*next_ddb_index = mbox_sts[3];
692afaf5a2dSDavid Somayajulu 	if (fw_ddb_device_state)
693afaf5a2dSDavid Somayajulu 		*fw_ddb_device_state = mbox_sts[4];
694afaf5a2dSDavid Somayajulu 
695afaf5a2dSDavid Somayajulu 	/*
696afaf5a2dSDavid Somayajulu 	 * RA: This mailbox has been changed to pass connection error and
697afaf5a2dSDavid Somayajulu 	 * details.  Its true for ISP4010 as per Version E - Not sure when it
698afaf5a2dSDavid Somayajulu 	 * was changed.	 Get the time2wait from the fw_dd_entry field :
699afaf5a2dSDavid Somayajulu 	 * default_time2wait which we call it as minTime2Wait DEV_DB_ENTRY
700afaf5a2dSDavid Somayajulu 	 * struct.
701afaf5a2dSDavid Somayajulu 	 */
702afaf5a2dSDavid Somayajulu 	if (conn_err_detail)
703afaf5a2dSDavid Somayajulu 		*conn_err_detail = mbox_sts[5];
704afaf5a2dSDavid Somayajulu 	if (tcp_source_port_num)
7051482338fSRandy Dunlap 		*tcp_source_port_num = (uint16_t) (mbox_sts[6] >> 16);
706afaf5a2dSDavid Somayajulu 	if (connection_id)
707afaf5a2dSDavid Somayajulu 		*connection_id = (uint16_t) mbox_sts[6] & 0x00FF;
708afaf5a2dSDavid Somayajulu 	status = QLA_SUCCESS;
709afaf5a2dSDavid Somayajulu 
710afaf5a2dSDavid Somayajulu exit_get_fwddb:
711afaf5a2dSDavid Somayajulu 	return status;
712afaf5a2dSDavid Somayajulu }
713afaf5a2dSDavid Somayajulu 
714b3a271a9SManish Rangankar int qla4xxx_conn_open(struct scsi_qla_host *ha, uint16_t fw_ddb_index)
715b3a271a9SManish Rangankar {
716b3a271a9SManish Rangankar 	uint32_t mbox_cmd[MBOX_REG_COUNT];
717b3a271a9SManish Rangankar 	uint32_t mbox_sts[MBOX_REG_COUNT];
718b3a271a9SManish Rangankar 	int status;
719b3a271a9SManish Rangankar 
720b3a271a9SManish Rangankar 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
721b3a271a9SManish Rangankar 	memset(&mbox_sts, 0, sizeof(mbox_sts));
722b3a271a9SManish Rangankar 
723b3a271a9SManish Rangankar 	mbox_cmd[0] = MBOX_CMD_CONN_OPEN;
724b3a271a9SManish Rangankar 	mbox_cmd[1] = fw_ddb_index;
725b3a271a9SManish Rangankar 
726b3a271a9SManish Rangankar 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
727b3a271a9SManish Rangankar 					 &mbox_sts[0]);
728b3a271a9SManish Rangankar 	DEBUG2(ql4_printk(KERN_INFO, ha,
729b3a271a9SManish Rangankar 			  "%s: status = %d mbx0 = 0x%x mbx1 = 0x%x\n",
730b3a271a9SManish Rangankar 			  __func__, status, mbox_sts[0], mbox_sts[1]));
731b3a271a9SManish Rangankar 	return status;
732b3a271a9SManish Rangankar }
733b3a271a9SManish Rangankar 
734afaf5a2dSDavid Somayajulu /**
735afaf5a2dSDavid Somayajulu  * qla4xxx_set_fwddb_entry - sets a ddb entry.
736afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
737afaf5a2dSDavid Somayajulu  * @fw_ddb_index: Firmware's device database index
738b3a271a9SManish Rangankar  * @fw_ddb_entry_dma: dma address of ddb entry
739b3a271a9SManish Rangankar  * @mbx_sts: mailbox 0 to be returned or NULL
740afaf5a2dSDavid Somayajulu  *
741afaf5a2dSDavid Somayajulu  * This routine initializes or updates the adapter's device database
742b3a271a9SManish Rangankar  * entry for the specified device.
743afaf5a2dSDavid Somayajulu  **/
744afaf5a2dSDavid Somayajulu int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
745b3a271a9SManish Rangankar 			  dma_addr_t fw_ddb_entry_dma, uint32_t *mbx_sts)
746afaf5a2dSDavid Somayajulu {
747afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
748afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
749f4f5df23SVikas Chaudhary 	int status;
750afaf5a2dSDavid Somayajulu 
751afaf5a2dSDavid Somayajulu 	/* Do not wait for completion. The firmware will send us an
752afaf5a2dSDavid Somayajulu 	 * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status.
753afaf5a2dSDavid Somayajulu 	 */
754afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
755afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
756afaf5a2dSDavid Somayajulu 
757afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_SET_DATABASE_ENTRY;
758afaf5a2dSDavid Somayajulu 	mbox_cmd[1] = (uint32_t) fw_ddb_index;
759afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
760afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
761c0e344c9SDavid C Somayajulu 	mbox_cmd[4] = sizeof(struct dev_db_entry);
762c0e344c9SDavid C Somayajulu 
763f4f5df23SVikas Chaudhary 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0],
764f4f5df23SVikas Chaudhary 					 &mbox_sts[0]);
765b3a271a9SManish Rangankar 	if (mbx_sts)
766b3a271a9SManish Rangankar 		*mbx_sts = mbox_sts[0];
767f4f5df23SVikas Chaudhary 	DEBUG2(printk("scsi%ld: %s: status=%d mbx0=0x%x mbx4=0x%x\n",
768f4f5df23SVikas Chaudhary 	    ha->host_no, __func__, status, mbox_sts[0], mbox_sts[4]);)
769f4f5df23SVikas Chaudhary 
770f4f5df23SVikas Chaudhary 	return status;
771afaf5a2dSDavid Somayajulu }
772afaf5a2dSDavid Somayajulu 
773b3a271a9SManish Rangankar int qla4xxx_session_logout_ddb(struct scsi_qla_host *ha,
774b3a271a9SManish Rangankar 			       struct ddb_entry *ddb_entry, int options)
775b3a271a9SManish Rangankar {
776b3a271a9SManish Rangankar 	int status;
777b3a271a9SManish Rangankar 	uint32_t mbox_cmd[MBOX_REG_COUNT];
778b3a271a9SManish Rangankar 	uint32_t mbox_sts[MBOX_REG_COUNT];
779b3a271a9SManish Rangankar 
780b3a271a9SManish Rangankar 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
781b3a271a9SManish Rangankar 	memset(&mbox_sts, 0, sizeof(mbox_sts));
782b3a271a9SManish Rangankar 
783b3a271a9SManish Rangankar 	mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
784b3a271a9SManish Rangankar 	mbox_cmd[1] = ddb_entry->fw_ddb_index;
785b3a271a9SManish Rangankar 	mbox_cmd[3] = options;
786b3a271a9SManish Rangankar 
787b3a271a9SManish Rangankar 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
788b3a271a9SManish Rangankar 					 &mbox_sts[0]);
789b3a271a9SManish Rangankar 	if (status != QLA_SUCCESS) {
790b3a271a9SManish Rangankar 		DEBUG2(ql4_printk(KERN_INFO, ha,
791b3a271a9SManish Rangankar 				  "%s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
792b3a271a9SManish Rangankar 				  "failed sts %04X %04X", __func__,
793b3a271a9SManish Rangankar 				  mbox_sts[0], mbox_sts[1]));
794b3a271a9SManish Rangankar 	}
795b3a271a9SManish Rangankar 
796b3a271a9SManish Rangankar 	return status;
797b3a271a9SManish Rangankar }
798b3a271a9SManish Rangankar 
799afaf5a2dSDavid Somayajulu /**
800afaf5a2dSDavid Somayajulu  * qla4xxx_get_crash_record - retrieves crash record.
801afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
802afaf5a2dSDavid Somayajulu  *
803afaf5a2dSDavid Somayajulu  * This routine retrieves a crash record from the QLA4010 after an 8002h aen.
804afaf5a2dSDavid Somayajulu  **/
805afaf5a2dSDavid Somayajulu void qla4xxx_get_crash_record(struct scsi_qla_host * ha)
806afaf5a2dSDavid Somayajulu {
807afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
808afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
809afaf5a2dSDavid Somayajulu 	struct crash_record *crash_record = NULL;
810afaf5a2dSDavid Somayajulu 	dma_addr_t crash_record_dma = 0;
811afaf5a2dSDavid Somayajulu 	uint32_t crash_record_size = 0;
812c0e344c9SDavid C Somayajulu 
813afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
814afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_cmd));
815afaf5a2dSDavid Somayajulu 
816afaf5a2dSDavid Somayajulu 	/* Get size of crash record. */
817afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
818c0e344c9SDavid C Somayajulu 
819c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
820afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
821afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n",
822afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__));
823afaf5a2dSDavid Somayajulu 		goto exit_get_crash_record;
824afaf5a2dSDavid Somayajulu 	}
825afaf5a2dSDavid Somayajulu 	crash_record_size = mbox_sts[4];
826afaf5a2dSDavid Somayajulu 	if (crash_record_size == 0) {
827afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: ERROR: Crash record size is 0!\n",
828afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__));
829afaf5a2dSDavid Somayajulu 		goto exit_get_crash_record;
830afaf5a2dSDavid Somayajulu 	}
831afaf5a2dSDavid Somayajulu 
832afaf5a2dSDavid Somayajulu 	/* Alloc Memory for Crash Record. */
833afaf5a2dSDavid Somayajulu 	crash_record = dma_alloc_coherent(&ha->pdev->dev, crash_record_size,
834afaf5a2dSDavid Somayajulu 					  &crash_record_dma, GFP_KERNEL);
835afaf5a2dSDavid Somayajulu 	if (crash_record == NULL)
836afaf5a2dSDavid Somayajulu 		goto exit_get_crash_record;
837afaf5a2dSDavid Somayajulu 
838afaf5a2dSDavid Somayajulu 	/* Get Crash Record. */
839c0e344c9SDavid C Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
840c0e344c9SDavid C Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_cmd));
841c0e344c9SDavid C Somayajulu 
842afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
843afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = LSDW(crash_record_dma);
844afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = MSDW(crash_record_dma);
845afaf5a2dSDavid Somayajulu 	mbox_cmd[4] = crash_record_size;
846c0e344c9SDavid C Somayajulu 
847c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
848afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS)
849afaf5a2dSDavid Somayajulu 		goto exit_get_crash_record;
850afaf5a2dSDavid Somayajulu 
851afaf5a2dSDavid Somayajulu 	/* Dump Crash Record. */
852afaf5a2dSDavid Somayajulu 
853afaf5a2dSDavid Somayajulu exit_get_crash_record:
854afaf5a2dSDavid Somayajulu 	if (crash_record)
855afaf5a2dSDavid Somayajulu 		dma_free_coherent(&ha->pdev->dev, crash_record_size,
856afaf5a2dSDavid Somayajulu 				  crash_record, crash_record_dma);
857afaf5a2dSDavid Somayajulu }
858afaf5a2dSDavid Somayajulu 
859afaf5a2dSDavid Somayajulu /**
860afaf5a2dSDavid Somayajulu  * qla4xxx_get_conn_event_log - retrieves connection event log
861afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
862afaf5a2dSDavid Somayajulu  **/
863afaf5a2dSDavid Somayajulu void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha)
864afaf5a2dSDavid Somayajulu {
865afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
866afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
867afaf5a2dSDavid Somayajulu 	struct conn_event_log_entry *event_log = NULL;
868afaf5a2dSDavid Somayajulu 	dma_addr_t event_log_dma = 0;
869afaf5a2dSDavid Somayajulu 	uint32_t event_log_size = 0;
870afaf5a2dSDavid Somayajulu 	uint32_t num_valid_entries;
871afaf5a2dSDavid Somayajulu 	uint32_t      oldest_entry = 0;
872afaf5a2dSDavid Somayajulu 	uint32_t	max_event_log_entries;
873afaf5a2dSDavid Somayajulu 	uint8_t		i;
874afaf5a2dSDavid Somayajulu 
875afaf5a2dSDavid Somayajulu 
876afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
877afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_cmd));
878afaf5a2dSDavid Somayajulu 
879afaf5a2dSDavid Somayajulu 	/* Get size of crash record. */
880afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
881c0e344c9SDavid C Somayajulu 
882c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
883afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS)
884afaf5a2dSDavid Somayajulu 		goto exit_get_event_log;
885afaf5a2dSDavid Somayajulu 
886afaf5a2dSDavid Somayajulu 	event_log_size = mbox_sts[4];
887afaf5a2dSDavid Somayajulu 	if (event_log_size == 0)
888afaf5a2dSDavid Somayajulu 		goto exit_get_event_log;
889afaf5a2dSDavid Somayajulu 
890afaf5a2dSDavid Somayajulu 	/* Alloc Memory for Crash Record. */
891afaf5a2dSDavid Somayajulu 	event_log = dma_alloc_coherent(&ha->pdev->dev, event_log_size,
892afaf5a2dSDavid Somayajulu 				       &event_log_dma, GFP_KERNEL);
893afaf5a2dSDavid Somayajulu 	if (event_log == NULL)
894afaf5a2dSDavid Somayajulu 		goto exit_get_event_log;
895afaf5a2dSDavid Somayajulu 
896afaf5a2dSDavid Somayajulu 	/* Get Crash Record. */
897c0e344c9SDavid C Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
898c0e344c9SDavid C Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_cmd));
899c0e344c9SDavid C Somayajulu 
900afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
901afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = LSDW(event_log_dma);
902afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = MSDW(event_log_dma);
903c0e344c9SDavid C Somayajulu 
904c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
905afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
906afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event "
907afaf5a2dSDavid Somayajulu 			      "log!\n", ha->host_no, __func__));
908afaf5a2dSDavid Somayajulu 		goto exit_get_event_log;
909afaf5a2dSDavid Somayajulu 	}
910afaf5a2dSDavid Somayajulu 
911afaf5a2dSDavid Somayajulu 	/* Dump Event Log. */
912afaf5a2dSDavid Somayajulu 	num_valid_entries = mbox_sts[1];
913afaf5a2dSDavid Somayajulu 
914afaf5a2dSDavid Somayajulu 	max_event_log_entries = event_log_size /
915afaf5a2dSDavid Somayajulu 		sizeof(struct conn_event_log_entry);
916afaf5a2dSDavid Somayajulu 
917afaf5a2dSDavid Somayajulu 	if (num_valid_entries > max_event_log_entries)
918afaf5a2dSDavid Somayajulu 		oldest_entry = num_valid_entries % max_event_log_entries;
919afaf5a2dSDavid Somayajulu 
920afaf5a2dSDavid Somayajulu 	DEBUG3(printk("scsi%ld: Connection Event Log Dump (%d entries):\n",
921afaf5a2dSDavid Somayajulu 		      ha->host_no, num_valid_entries));
922afaf5a2dSDavid Somayajulu 
92311010fecSAndrew Vasquez 	if (ql4xextended_error_logging == 3) {
924afaf5a2dSDavid Somayajulu 		if (oldest_entry == 0) {
925afaf5a2dSDavid Somayajulu 			/* Circular Buffer has not wrapped around */
926afaf5a2dSDavid Somayajulu 			for (i=0; i < num_valid_entries; i++) {
927afaf5a2dSDavid Somayajulu 				qla4xxx_dump_buffer((uint8_t *)event_log+
928afaf5a2dSDavid Somayajulu 						    (i*sizeof(*event_log)),
929afaf5a2dSDavid Somayajulu 						    sizeof(*event_log));
930afaf5a2dSDavid Somayajulu 			}
931afaf5a2dSDavid Somayajulu 		}
932afaf5a2dSDavid Somayajulu 		else {
933afaf5a2dSDavid Somayajulu 			/* Circular Buffer has wrapped around -
934afaf5a2dSDavid Somayajulu 			 * display accordingly*/
935afaf5a2dSDavid Somayajulu 			for (i=oldest_entry; i < max_event_log_entries; i++) {
936afaf5a2dSDavid Somayajulu 				qla4xxx_dump_buffer((uint8_t *)event_log+
937afaf5a2dSDavid Somayajulu 						    (i*sizeof(*event_log)),
938afaf5a2dSDavid Somayajulu 						    sizeof(*event_log));
939afaf5a2dSDavid Somayajulu 			}
940afaf5a2dSDavid Somayajulu 			for (i=0; i < oldest_entry; i++) {
941afaf5a2dSDavid Somayajulu 				qla4xxx_dump_buffer((uint8_t *)event_log+
942afaf5a2dSDavid Somayajulu 						    (i*sizeof(*event_log)),
943afaf5a2dSDavid Somayajulu 						    sizeof(*event_log));
944afaf5a2dSDavid Somayajulu 			}
945afaf5a2dSDavid Somayajulu 		}
946afaf5a2dSDavid Somayajulu 	}
947afaf5a2dSDavid Somayajulu 
948afaf5a2dSDavid Somayajulu exit_get_event_log:
949afaf5a2dSDavid Somayajulu 	if (event_log)
950afaf5a2dSDavid Somayajulu 		dma_free_coherent(&ha->pdev->dev, event_log_size, event_log,
951afaf5a2dSDavid Somayajulu 				  event_log_dma);
952afaf5a2dSDavid Somayajulu }
953afaf5a2dSDavid Somayajulu 
954afaf5a2dSDavid Somayajulu /**
95509a0f719SVikas Chaudhary  * qla4xxx_abort_task - issues Abort Task
95609a0f719SVikas Chaudhary  * @ha: Pointer to host adapter structure.
95709a0f719SVikas Chaudhary  * @srb: Pointer to srb entry
95809a0f719SVikas Chaudhary  *
95909a0f719SVikas Chaudhary  * This routine performs a LUN RESET on the specified target/lun.
96009a0f719SVikas Chaudhary  * The caller must ensure that the ddb_entry and lun_entry pointers
96109a0f719SVikas Chaudhary  * are valid before calling this routine.
96209a0f719SVikas Chaudhary  **/
96309a0f719SVikas Chaudhary int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb)
96409a0f719SVikas Chaudhary {
96509a0f719SVikas Chaudhary 	uint32_t mbox_cmd[MBOX_REG_COUNT];
96609a0f719SVikas Chaudhary 	uint32_t mbox_sts[MBOX_REG_COUNT];
96709a0f719SVikas Chaudhary 	struct scsi_cmnd *cmd = srb->cmd;
96809a0f719SVikas Chaudhary 	int status = QLA_SUCCESS;
96909a0f719SVikas Chaudhary 	unsigned long flags = 0;
97009a0f719SVikas Chaudhary 	uint32_t index;
97109a0f719SVikas Chaudhary 
97209a0f719SVikas Chaudhary 	/*
97309a0f719SVikas Chaudhary 	 * Send abort task command to ISP, so that the ISP will return
97409a0f719SVikas Chaudhary 	 * request with ABORT status
97509a0f719SVikas Chaudhary 	 */
97609a0f719SVikas Chaudhary 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
97709a0f719SVikas Chaudhary 	memset(&mbox_sts, 0, sizeof(mbox_sts));
97809a0f719SVikas Chaudhary 
97909a0f719SVikas Chaudhary 	spin_lock_irqsave(&ha->hardware_lock, flags);
98009a0f719SVikas Chaudhary 	index = (unsigned long)(unsigned char *)cmd->host_scribble;
98109a0f719SVikas Chaudhary 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
98209a0f719SVikas Chaudhary 
98309a0f719SVikas Chaudhary 	/* Firmware already posted completion on response queue */
98409a0f719SVikas Chaudhary 	if (index == MAX_SRBS)
98509a0f719SVikas Chaudhary 		return status;
98609a0f719SVikas Chaudhary 
98709a0f719SVikas Chaudhary 	mbox_cmd[0] = MBOX_CMD_ABORT_TASK;
9886790d4feSKaren Higgins 	mbox_cmd[1] = srb->ddb->fw_ddb_index;
98909a0f719SVikas Chaudhary 	mbox_cmd[2] = index;
99009a0f719SVikas Chaudhary 	/* Immediate Command Enable */
99109a0f719SVikas Chaudhary 	mbox_cmd[5] = 0x01;
99209a0f719SVikas Chaudhary 
99309a0f719SVikas Chaudhary 	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0],
99409a0f719SVikas Chaudhary 	    &mbox_sts[0]);
99509a0f719SVikas Chaudhary 	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE) {
99609a0f719SVikas Chaudhary 		status = QLA_ERROR;
99709a0f719SVikas Chaudhary 
99809a0f719SVikas Chaudhary 		DEBUG2(printk(KERN_WARNING "scsi%ld:%d:%d: abort task FAILED: "
99909a0f719SVikas Chaudhary 		    "mbx0=%04X, mb1=%04X, mb2=%04X, mb3=%04X, mb4=%04X\n",
100009a0f719SVikas Chaudhary 		    ha->host_no, cmd->device->id, cmd->device->lun, mbox_sts[0],
100109a0f719SVikas Chaudhary 		    mbox_sts[1], mbox_sts[2], mbox_sts[3], mbox_sts[4]));
100209a0f719SVikas Chaudhary 	}
100309a0f719SVikas Chaudhary 
100409a0f719SVikas Chaudhary 	return status;
100509a0f719SVikas Chaudhary }
100609a0f719SVikas Chaudhary 
100709a0f719SVikas Chaudhary /**
1008afaf5a2dSDavid Somayajulu  * qla4xxx_reset_lun - issues LUN Reset
1009afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
1010f4f5df23SVikas Chaudhary  * @ddb_entry: Pointer to device database entry
1011f4f5df23SVikas Chaudhary  * @lun: lun number
1012afaf5a2dSDavid Somayajulu  *
1013afaf5a2dSDavid Somayajulu  * This routine performs a LUN RESET on the specified target/lun.
1014afaf5a2dSDavid Somayajulu  * The caller must ensure that the ddb_entry and lun_entry pointers
1015afaf5a2dSDavid Somayajulu  * are valid before calling this routine.
1016afaf5a2dSDavid Somayajulu  **/
1017afaf5a2dSDavid Somayajulu int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
1018afaf5a2dSDavid Somayajulu 		      int lun)
1019afaf5a2dSDavid Somayajulu {
1020afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1021afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
1022afaf5a2dSDavid Somayajulu 	int status = QLA_SUCCESS;
1023afaf5a2dSDavid Somayajulu 
1024afaf5a2dSDavid Somayajulu 	DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no,
1025f4f5df23SVikas Chaudhary 		      ddb_entry->fw_ddb_index, lun));
1026afaf5a2dSDavid Somayajulu 
1027afaf5a2dSDavid Somayajulu 	/*
1028afaf5a2dSDavid Somayajulu 	 * Send lun reset command to ISP, so that the ISP will return all
1029afaf5a2dSDavid Somayajulu 	 * outstanding requests with RESET status
1030afaf5a2dSDavid Somayajulu 	 */
1031afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1032afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1033c0e344c9SDavid C Somayajulu 
1034afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_LUN_RESET;
1035afaf5a2dSDavid Somayajulu 	mbox_cmd[1] = ddb_entry->fw_ddb_index;
1036afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = lun << 8;
1037afaf5a2dSDavid Somayajulu 	mbox_cmd[5] = 0x01;	/* Immediate Command Enable */
1038c0e344c9SDavid C Somayajulu 
1039c0e344c9SDavid C Somayajulu 	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]);
1040afaf5a2dSDavid Somayajulu 	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
1041afaf5a2dSDavid Somayajulu 	    mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
1042afaf5a2dSDavid Somayajulu 		status = QLA_ERROR;
1043afaf5a2dSDavid Somayajulu 
1044afaf5a2dSDavid Somayajulu 	return status;
1045afaf5a2dSDavid Somayajulu }
1046afaf5a2dSDavid Somayajulu 
1047ce545039SMike Christie /**
1048ce545039SMike Christie  * qla4xxx_reset_target - issues target Reset
1049ce545039SMike Christie  * @ha: Pointer to host adapter structure.
1050ce545039SMike Christie  * @db_entry: Pointer to device database entry
1051ce545039SMike Christie  * @un_entry: Pointer to lun entry structure
1052ce545039SMike Christie  *
1053ce545039SMike Christie  * This routine performs a TARGET RESET on the specified target.
1054ce545039SMike Christie  * The caller must ensure that the ddb_entry pointers
1055ce545039SMike Christie  * are valid before calling this routine.
1056ce545039SMike Christie  **/
1057ce545039SMike Christie int qla4xxx_reset_target(struct scsi_qla_host *ha,
1058ce545039SMike Christie 			 struct ddb_entry *ddb_entry)
1059ce545039SMike Christie {
1060ce545039SMike Christie 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1061ce545039SMike Christie 	uint32_t mbox_sts[MBOX_REG_COUNT];
1062ce545039SMike Christie 	int status = QLA_SUCCESS;
1063ce545039SMike Christie 
1064ce545039SMike Christie 	DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no,
1065f4f5df23SVikas Chaudhary 		      ddb_entry->fw_ddb_index));
1066ce545039SMike Christie 
1067ce545039SMike Christie 	/*
1068ce545039SMike Christie 	 * Send target reset command to ISP, so that the ISP will return all
1069ce545039SMike Christie 	 * outstanding requests with RESET status
1070ce545039SMike Christie 	 */
1071ce545039SMike Christie 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1072ce545039SMike Christie 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1073ce545039SMike Christie 
1074ce545039SMike Christie 	mbox_cmd[0] = MBOX_CMD_TARGET_WARM_RESET;
1075ce545039SMike Christie 	mbox_cmd[1] = ddb_entry->fw_ddb_index;
1076ce545039SMike Christie 	mbox_cmd[5] = 0x01;	/* Immediate Command Enable */
1077ce545039SMike Christie 
1078ce545039SMike Christie 	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
1079ce545039SMike Christie 				&mbox_sts[0]);
1080ce545039SMike Christie 	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
1081ce545039SMike Christie 	    mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
1082ce545039SMike Christie 		status = QLA_ERROR;
1083ce545039SMike Christie 
1084ce545039SMike Christie 	return status;
1085ce545039SMike Christie }
1086afaf5a2dSDavid Somayajulu 
1087afaf5a2dSDavid Somayajulu int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
1088afaf5a2dSDavid Somayajulu 		      uint32_t offset, uint32_t len)
1089afaf5a2dSDavid Somayajulu {
1090afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1091afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
1092afaf5a2dSDavid Somayajulu 
1093afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1094afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1095c0e344c9SDavid C Somayajulu 
1096afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_READ_FLASH;
1097afaf5a2dSDavid Somayajulu 	mbox_cmd[1] = LSDW(dma_addr);
1098afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = MSDW(dma_addr);
1099afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = offset;
1100afaf5a2dSDavid Somayajulu 	mbox_cmd[4] = len;
1101c0e344c9SDavid C Somayajulu 
1102c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], &mbox_sts[0]) !=
1103afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
1104afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ "
1105afaf5a2dSDavid Somayajulu 		    "status %04X %04X, offset %08x, len %08x\n", ha->host_no,
1106afaf5a2dSDavid Somayajulu 		    __func__, mbox_sts[0], mbox_sts[1], offset, len));
1107afaf5a2dSDavid Somayajulu 		return QLA_ERROR;
1108afaf5a2dSDavid Somayajulu 	}
1109afaf5a2dSDavid Somayajulu 	return QLA_SUCCESS;
1110afaf5a2dSDavid Somayajulu }
1111afaf5a2dSDavid Somayajulu 
1112afaf5a2dSDavid Somayajulu /**
11137ad633c0SHarish Zunjarrao  * qla4xxx_about_firmware - gets FW, iscsi draft and boot loader version
1114afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
1115afaf5a2dSDavid Somayajulu  *
11167ad633c0SHarish Zunjarrao  * Retrieves the FW version, iSCSI draft version & bootloader version of HBA.
11177ad633c0SHarish Zunjarrao  * Mailboxes 2 & 3 may hold an address for data. Make sure that we write 0 to
11187ad633c0SHarish Zunjarrao  * those mailboxes, if unused.
1119afaf5a2dSDavid Somayajulu  **/
11207ad633c0SHarish Zunjarrao int qla4xxx_about_firmware(struct scsi_qla_host *ha)
1121afaf5a2dSDavid Somayajulu {
11227ad633c0SHarish Zunjarrao 	struct about_fw_info *about_fw = NULL;
11237ad633c0SHarish Zunjarrao 	dma_addr_t about_fw_dma;
1124afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1125afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
11267ad633c0SHarish Zunjarrao 	int status = QLA_ERROR;
1127afaf5a2dSDavid Somayajulu 
11287ad633c0SHarish Zunjarrao 	about_fw = dma_alloc_coherent(&ha->pdev->dev,
11297ad633c0SHarish Zunjarrao 				      sizeof(struct about_fw_info),
11307ad633c0SHarish Zunjarrao 				      &about_fw_dma, GFP_KERNEL);
11317ad633c0SHarish Zunjarrao 	if (!about_fw) {
11327ad633c0SHarish Zunjarrao 		DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Unable to alloc memory "
11337ad633c0SHarish Zunjarrao 				  "for about_fw\n", __func__));
11347ad633c0SHarish Zunjarrao 		return status;
11357ad633c0SHarish Zunjarrao 	}
11367ad633c0SHarish Zunjarrao 
11377ad633c0SHarish Zunjarrao 	memset(about_fw, 0, sizeof(struct about_fw_info));
1138afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1139afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1140c0e344c9SDavid C Somayajulu 
1141afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_ABOUT_FW;
11427ad633c0SHarish Zunjarrao 	mbox_cmd[2] = LSDW(about_fw_dma);
11437ad633c0SHarish Zunjarrao 	mbox_cmd[3] = MSDW(about_fw_dma);
11447ad633c0SHarish Zunjarrao 	mbox_cmd[4] = sizeof(struct about_fw_info);
1145c0e344c9SDavid C Somayajulu 
11467ad633c0SHarish Zunjarrao 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT,
11477ad633c0SHarish Zunjarrao 					 &mbox_cmd[0], &mbox_sts[0]);
11487ad633c0SHarish Zunjarrao 	if (status != QLA_SUCCESS) {
11497ad633c0SHarish Zunjarrao 		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_ABOUT_FW "
11507ad633c0SHarish Zunjarrao 				  "failed w/ status %04X\n", __func__,
11517ad633c0SHarish Zunjarrao 				  mbox_sts[0]));
11527ad633c0SHarish Zunjarrao 		goto exit_about_fw;
1153afaf5a2dSDavid Somayajulu 	}
1154afaf5a2dSDavid Somayajulu 
11557ad633c0SHarish Zunjarrao 	/* Save version information. */
11567ad633c0SHarish Zunjarrao 	ha->firmware_version[0] = le16_to_cpu(about_fw->fw_major);
11577ad633c0SHarish Zunjarrao 	ha->firmware_version[1] = le16_to_cpu(about_fw->fw_minor);
11587ad633c0SHarish Zunjarrao 	ha->patch_number = le16_to_cpu(about_fw->fw_patch);
11597ad633c0SHarish Zunjarrao 	ha->build_number = le16_to_cpu(about_fw->fw_build);
11607ad633c0SHarish Zunjarrao 	ha->iscsi_major = le16_to_cpu(about_fw->iscsi_major);
11617ad633c0SHarish Zunjarrao 	ha->iscsi_minor = le16_to_cpu(about_fw->iscsi_minor);
11627ad633c0SHarish Zunjarrao 	ha->bootload_major = le16_to_cpu(about_fw->bootload_major);
11637ad633c0SHarish Zunjarrao 	ha->bootload_minor = le16_to_cpu(about_fw->bootload_minor);
11647ad633c0SHarish Zunjarrao 	ha->bootload_patch = le16_to_cpu(about_fw->bootload_patch);
11657ad633c0SHarish Zunjarrao 	ha->bootload_build = le16_to_cpu(about_fw->bootload_build);
11667ad633c0SHarish Zunjarrao 	status = QLA_SUCCESS;
1167afaf5a2dSDavid Somayajulu 
11687ad633c0SHarish Zunjarrao exit_about_fw:
11697ad633c0SHarish Zunjarrao 	dma_free_coherent(&ha->pdev->dev, sizeof(struct about_fw_info),
11707ad633c0SHarish Zunjarrao 			  about_fw, about_fw_dma);
11717ad633c0SHarish Zunjarrao 	return status;
1172afaf5a2dSDavid Somayajulu }
1173afaf5a2dSDavid Somayajulu 
1174b3a271a9SManish Rangankar static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options,
117547975477SAdrian Bunk 				   dma_addr_t dma_addr)
1176afaf5a2dSDavid Somayajulu {
1177afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1178afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
1179afaf5a2dSDavid Somayajulu 
1180afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1181afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1182afaf5a2dSDavid Somayajulu 
1183afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS;
1184b3a271a9SManish Rangankar 	mbox_cmd[1] = options;
1185afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = LSDW(dma_addr);
1186afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = MSDW(dma_addr);
1187afaf5a2dSDavid Somayajulu 
1188c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=
1189afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
1190afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
1191afaf5a2dSDavid Somayajulu 		     ha->host_no, __func__, mbox_sts[0]));
1192afaf5a2dSDavid Somayajulu 		return QLA_ERROR;
1193afaf5a2dSDavid Somayajulu 	}
1194afaf5a2dSDavid Somayajulu 	return QLA_SUCCESS;
1195afaf5a2dSDavid Somayajulu }
1196afaf5a2dSDavid Somayajulu 
1197b3a271a9SManish Rangankar int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index,
1198b3a271a9SManish Rangankar 			  uint32_t *mbx_sts)
1199afaf5a2dSDavid Somayajulu {
1200b3a271a9SManish Rangankar 	int status;
1201afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1202afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
1203afaf5a2dSDavid Somayajulu 
1204afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1205afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1206afaf5a2dSDavid Somayajulu 
1207afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY;
1208b3a271a9SManish Rangankar 	mbox_cmd[1] = ddb_index;
1209afaf5a2dSDavid Somayajulu 
1210b3a271a9SManish Rangankar 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
1211b3a271a9SManish Rangankar 					 &mbox_sts[0]);
1212b3a271a9SManish Rangankar 	if (status != QLA_SUCCESS) {
1213b3a271a9SManish Rangankar 		DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",
1214b3a271a9SManish Rangankar 				   __func__, mbox_sts[0]));
1215afaf5a2dSDavid Somayajulu 	}
1216afaf5a2dSDavid Somayajulu 
1217b3a271a9SManish Rangankar 	*mbx_sts = mbox_sts[0];
1218b3a271a9SManish Rangankar 	return status;
1219afaf5a2dSDavid Somayajulu }
1220afaf5a2dSDavid Somayajulu 
1221b3a271a9SManish Rangankar int qla4xxx_clear_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index)
1222b3a271a9SManish Rangankar {
1223b3a271a9SManish Rangankar 	int status;
1224b3a271a9SManish Rangankar 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1225b3a271a9SManish Rangankar 	uint32_t mbox_sts[MBOX_REG_COUNT];
1226b3a271a9SManish Rangankar 
1227b3a271a9SManish Rangankar 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1228b3a271a9SManish Rangankar 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1229b3a271a9SManish Rangankar 
1230b3a271a9SManish Rangankar 	mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY;
1231b3a271a9SManish Rangankar 	mbox_cmd[1] = ddb_index;
1232b3a271a9SManish Rangankar 
1233b3a271a9SManish Rangankar 	status = qla4xxx_mailbox_command(ha, 2, 1, &mbox_cmd[0],
1234b3a271a9SManish Rangankar 					 &mbox_sts[0]);
1235b3a271a9SManish Rangankar 	if (status != QLA_SUCCESS) {
1236b3a271a9SManish Rangankar 		DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",
1237b3a271a9SManish Rangankar 				   __func__, mbox_sts[0]));
1238b3a271a9SManish Rangankar 	}
1239b3a271a9SManish Rangankar 
1240b3a271a9SManish Rangankar 	return status;
1241b3a271a9SManish Rangankar }
1242b3a271a9SManish Rangankar 
1243d00efe3fSMike Christie int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
1244d00efe3fSMike Christie 		      uint32_t offset, uint32_t length, uint32_t options)
1245d00efe3fSMike Christie {
1246d00efe3fSMike Christie 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1247d00efe3fSMike Christie 	uint32_t mbox_sts[MBOX_REG_COUNT];
1248d00efe3fSMike Christie 	int status = QLA_SUCCESS;
1249d00efe3fSMike Christie 
1250d00efe3fSMike Christie 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1251d00efe3fSMike Christie 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1252d00efe3fSMike Christie 
1253d00efe3fSMike Christie 	mbox_cmd[0] = MBOX_CMD_WRITE_FLASH;
1254d00efe3fSMike Christie 	mbox_cmd[1] = LSDW(dma_addr);
1255d00efe3fSMike Christie 	mbox_cmd[2] = MSDW(dma_addr);
1256d00efe3fSMike Christie 	mbox_cmd[3] = offset;
1257d00efe3fSMike Christie 	mbox_cmd[4] = length;
1258d00efe3fSMike Christie 	mbox_cmd[5] = options;
1259d00efe3fSMike Christie 
1260d00efe3fSMike Christie 	status = qla4xxx_mailbox_command(ha, 6, 2, &mbox_cmd[0], &mbox_sts[0]);
1261d00efe3fSMike Christie 	if (status != QLA_SUCCESS) {
1262d00efe3fSMike Christie 		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_WRITE_FLASH "
1263d00efe3fSMike Christie 				  "failed w/ status %04X, mbx1 %04X\n",
1264d00efe3fSMike Christie 				  __func__, mbox_sts[0], mbox_sts[1]));
1265d00efe3fSMike Christie 	}
1266d00efe3fSMike Christie 	return status;
1267d00efe3fSMike Christie }
1268d00efe3fSMike Christie 
12692a991c21SManish Rangankar int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha,
12702a991c21SManish Rangankar 			    struct dev_db_entry *fw_ddb_entry,
12712a991c21SManish Rangankar 			    dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index)
12722a991c21SManish Rangankar {
12732a991c21SManish Rangankar 	uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO;
12742a991c21SManish Rangankar 	uint32_t dev_db_end_offset;
12752a991c21SManish Rangankar 	int status = QLA_ERROR;
12762a991c21SManish Rangankar 
12772a991c21SManish Rangankar 	memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry));
12782a991c21SManish Rangankar 
12792a991c21SManish Rangankar 	dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry));
12802a991c21SManish Rangankar 	dev_db_end_offset = FLASH_OFFSET_DB_END;
12812a991c21SManish Rangankar 
12822a991c21SManish Rangankar 	if (dev_db_start_offset > dev_db_end_offset) {
12832a991c21SManish Rangankar 		DEBUG2(ql4_printk(KERN_ERR, ha,
12842a991c21SManish Rangankar 				  "%s:Invalid DDB index %d", __func__,
12852a991c21SManish Rangankar 				  ddb_index));
12862a991c21SManish Rangankar 		goto exit_bootdb_failed;
12872a991c21SManish Rangankar 	}
12882a991c21SManish Rangankar 
12892a991c21SManish Rangankar 	if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset,
12902a991c21SManish Rangankar 			      sizeof(*fw_ddb_entry)) != QLA_SUCCESS) {
12912a991c21SManish Rangankar 		ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash"
12922a991c21SManish Rangankar 			   "failed\n", ha->host_no, __func__);
12932a991c21SManish Rangankar 		goto exit_bootdb_failed;
12942a991c21SManish Rangankar 	}
12952a991c21SManish Rangankar 
12962a991c21SManish Rangankar 	if (fw_ddb_entry->cookie == DDB_VALID_COOKIE)
12972a991c21SManish Rangankar 		status = QLA_SUCCESS;
12982a991c21SManish Rangankar 
12992a991c21SManish Rangankar exit_bootdb_failed:
13002a991c21SManish Rangankar 	return status;
13012a991c21SManish Rangankar }
13022a991c21SManish Rangankar 
13032a991c21SManish Rangankar int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,
13042a991c21SManish Rangankar 		     uint16_t idx)
13052a991c21SManish Rangankar {
13062a991c21SManish Rangankar 	int ret = 0;
13072a991c21SManish Rangankar 	int rval = QLA_ERROR;
13082a991c21SManish Rangankar 	uint32_t offset = 0;
13092a991c21SManish Rangankar 	struct ql4_chap_table *chap_table;
13102a991c21SManish Rangankar 	dma_addr_t chap_dma;
13112a991c21SManish Rangankar 
13122a991c21SManish Rangankar 	chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);
13132a991c21SManish Rangankar 	if (chap_table == NULL) {
13142a991c21SManish Rangankar 		ret = -ENOMEM;
13152a991c21SManish Rangankar 		goto exit_get_chap;
13162a991c21SManish Rangankar 	}
13172a991c21SManish Rangankar 
13182a991c21SManish Rangankar 	memset(chap_table, 0, sizeof(struct ql4_chap_table));
13192a991c21SManish Rangankar 
13202a991c21SManish Rangankar 	offset = 0x06000000 | (idx * sizeof(struct ql4_chap_table));
13212a991c21SManish Rangankar 
13222a991c21SManish Rangankar 	rval = qla4xxx_get_flash(ha, chap_dma, offset,
13232a991c21SManish Rangankar 				 sizeof(struct ql4_chap_table));
13242a991c21SManish Rangankar 	if (rval != QLA_SUCCESS) {
13252a991c21SManish Rangankar 		ret = -EINVAL;
13262a991c21SManish Rangankar 		goto exit_get_chap;
13272a991c21SManish Rangankar 	}
13282a991c21SManish Rangankar 
13292a991c21SManish Rangankar 	DEBUG2(ql4_printk(KERN_INFO, ha, "Chap Cookie: x%x\n",
13302a991c21SManish Rangankar 		__le16_to_cpu(chap_table->cookie)));
13312a991c21SManish Rangankar 
13322a991c21SManish Rangankar 	if (__le16_to_cpu(chap_table->cookie) != CHAP_VALID_COOKIE) {
13332a991c21SManish Rangankar 		ql4_printk(KERN_ERR, ha, "No valid chap entry found\n");
13342a991c21SManish Rangankar 		goto exit_get_chap;
13352a991c21SManish Rangankar 	}
13362a991c21SManish Rangankar 
13372a991c21SManish Rangankar 	strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
13382a991c21SManish Rangankar 	strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
13392a991c21SManish Rangankar 	chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE);
13402a991c21SManish Rangankar 
13412a991c21SManish Rangankar exit_get_chap:
13422a991c21SManish Rangankar 	dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
13432a991c21SManish Rangankar 	return ret;
13442a991c21SManish Rangankar }
13452a991c21SManish Rangankar 
1346b3a271a9SManish Rangankar static int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username,
1347b3a271a9SManish Rangankar 			    char *password, uint16_t idx, int bidi)
1348b3a271a9SManish Rangankar {
1349b3a271a9SManish Rangankar 	int ret = 0;
1350b3a271a9SManish Rangankar 	int rval = QLA_ERROR;
1351b3a271a9SManish Rangankar 	uint32_t offset = 0;
1352b3a271a9SManish Rangankar 	struct ql4_chap_table *chap_table;
1353b3a271a9SManish Rangankar 	dma_addr_t chap_dma;
1354b3a271a9SManish Rangankar 
1355b3a271a9SManish Rangankar 	chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);
1356b3a271a9SManish Rangankar 	if (chap_table == NULL) {
1357b3a271a9SManish Rangankar 		ret =  -ENOMEM;
1358b3a271a9SManish Rangankar 		goto exit_set_chap;
1359b3a271a9SManish Rangankar 	}
1360b3a271a9SManish Rangankar 
1361b3a271a9SManish Rangankar 	memset(chap_table, 0, sizeof(struct ql4_chap_table));
1362b3a271a9SManish Rangankar 	if (bidi)
1363b3a271a9SManish Rangankar 		chap_table->flags |= BIT_6; /* peer */
1364b3a271a9SManish Rangankar 	else
1365b3a271a9SManish Rangankar 		chap_table->flags |= BIT_7; /* local */
1366b3a271a9SManish Rangankar 	chap_table->secret_len = strlen(password);
1367b3a271a9SManish Rangankar 	strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN);
1368b3a271a9SManish Rangankar 	strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN);
1369b3a271a9SManish Rangankar 	chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE);
1370b3a271a9SManish Rangankar 	offset = 0x06000000 | (idx * sizeof(struct ql4_chap_table));
1371b3a271a9SManish Rangankar 	rval = qla4xxx_set_flash(ha, chap_dma, offset,
1372b3a271a9SManish Rangankar 				sizeof(struct ql4_chap_table),
1373b3a271a9SManish Rangankar 				FLASH_OPT_RMW_COMMIT);
1374b3a271a9SManish Rangankar 	dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
1375b3a271a9SManish Rangankar 	if (rval != QLA_SUCCESS)
1376b3a271a9SManish Rangankar 		ret =  -EINVAL;
1377b3a271a9SManish Rangankar 
1378b3a271a9SManish Rangankar exit_set_chap:
1379b3a271a9SManish Rangankar 	return ret;
1380b3a271a9SManish Rangankar }
1381b3a271a9SManish Rangankar 
1382d00efe3fSMike Christie int qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha,
1383d00efe3fSMike Christie 				   uint16_t fw_ddb_index,
1384d00efe3fSMike Christie 				   uint16_t connection_id,
1385d00efe3fSMike Christie 				   uint16_t option)
1386d00efe3fSMike Christie {
1387d00efe3fSMike Christie 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1388d00efe3fSMike Christie 	uint32_t mbox_sts[MBOX_REG_COUNT];
1389d00efe3fSMike Christie 	int status = QLA_SUCCESS;
1390d00efe3fSMike Christie 
1391d00efe3fSMike Christie 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1392d00efe3fSMike Christie 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1393d00efe3fSMike Christie 
1394d00efe3fSMike Christie 	mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
1395d00efe3fSMike Christie 	mbox_cmd[1] = fw_ddb_index;
1396d00efe3fSMike Christie 	mbox_cmd[2] = connection_id;
1397d00efe3fSMike Christie 	mbox_cmd[3] = option;
1398d00efe3fSMike Christie 
1399d00efe3fSMike Christie 	status = qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]);
1400d00efe3fSMike Christie 	if (status != QLA_SUCCESS) {
1401d00efe3fSMike Christie 		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_CONN_CLOSE "
1402d00efe3fSMike Christie 				  "option %04x failed w/ status %04X %04X\n",
1403d00efe3fSMike Christie 				  __func__, option, mbox_sts[0], mbox_sts[1]));
1404d00efe3fSMike Christie 	}
1405d00efe3fSMike Christie 	return status;
1406d00efe3fSMike Christie }
1407d00efe3fSMike Christie 
1408d00efe3fSMike Christie int qla4xxx_disable_acb(struct scsi_qla_host *ha)
1409d00efe3fSMike Christie {
1410d00efe3fSMike Christie 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1411d00efe3fSMike Christie 	uint32_t mbox_sts[MBOX_REG_COUNT];
1412d00efe3fSMike Christie 	int status = QLA_SUCCESS;
1413d00efe3fSMike Christie 
1414d00efe3fSMike Christie 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1415d00efe3fSMike Christie 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1416d00efe3fSMike Christie 
1417d00efe3fSMike Christie 	mbox_cmd[0] = MBOX_CMD_DISABLE_ACB;
1418d00efe3fSMike Christie 
1419d00efe3fSMike Christie 	status = qla4xxx_mailbox_command(ha, 8, 5, &mbox_cmd[0], &mbox_sts[0]);
1420d00efe3fSMike Christie 	if (status != QLA_SUCCESS) {
1421d00efe3fSMike Christie 		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_DISABLE_ACB "
1422d00efe3fSMike Christie 				  "failed w/ status %04X %04X %04X", __func__,
1423d00efe3fSMike Christie 				  mbox_sts[0], mbox_sts[1], mbox_sts[2]));
1424d00efe3fSMike Christie 	}
1425d00efe3fSMike Christie 	return status;
1426d00efe3fSMike Christie }
1427d00efe3fSMike Christie 
1428*6085491cSHarish Zunjarrao int qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma,
1429*6085491cSHarish Zunjarrao 		    uint32_t acb_type, uint32_t len)
1430d00efe3fSMike Christie {
1431*6085491cSHarish Zunjarrao 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1432*6085491cSHarish Zunjarrao 	uint32_t mbox_sts[MBOX_REG_COUNT];
1433d00efe3fSMike Christie 	int status = QLA_SUCCESS;
1434d00efe3fSMike Christie 
1435*6085491cSHarish Zunjarrao 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1436*6085491cSHarish Zunjarrao 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1437*6085491cSHarish Zunjarrao 
1438d00efe3fSMike Christie 	mbox_cmd[0] = MBOX_CMD_GET_ACB;
1439*6085491cSHarish Zunjarrao 	mbox_cmd[1] = acb_type;
1440d00efe3fSMike Christie 	mbox_cmd[2] = LSDW(acb_dma);
1441d00efe3fSMike Christie 	mbox_cmd[3] = MSDW(acb_dma);
1442*6085491cSHarish Zunjarrao 	mbox_cmd[4] = len;
1443d00efe3fSMike Christie 
1444d00efe3fSMike Christie 	status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);
1445d00efe3fSMike Christie 	if (status != QLA_SUCCESS) {
1446d00efe3fSMike Christie 		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_GET_ACB "
1447d00efe3fSMike Christie 				  "failed w/ status %04X\n", __func__,
1448d00efe3fSMike Christie 				  mbox_sts[0]));
1449d00efe3fSMike Christie 	}
1450d00efe3fSMike Christie 	return status;
1451d00efe3fSMike Christie }
1452d00efe3fSMike Christie 
1453d00efe3fSMike Christie int qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
1454d00efe3fSMike Christie 		    uint32_t *mbox_sts, dma_addr_t acb_dma)
1455d00efe3fSMike Christie {
1456d00efe3fSMike Christie 	int status = QLA_SUCCESS;
1457d00efe3fSMike Christie 
1458d00efe3fSMike Christie 	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
1459d00efe3fSMike Christie 	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
1460d00efe3fSMike Christie 	mbox_cmd[0] = MBOX_CMD_SET_ACB;
1461d00efe3fSMike Christie 	mbox_cmd[1] = 0; /* Primary ACB */
1462d00efe3fSMike Christie 	mbox_cmd[2] = LSDW(acb_dma);
1463d00efe3fSMike Christie 	mbox_cmd[3] = MSDW(acb_dma);
1464d00efe3fSMike Christie 	mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
1465d00efe3fSMike Christie 
1466d00efe3fSMike Christie 	status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);
1467d00efe3fSMike Christie 	if (status != QLA_SUCCESS) {
1468d00efe3fSMike Christie 		DEBUG2(ql4_printk(KERN_WARNING, ha,  "%s: MBOX_CMD_SET_ACB "
1469d00efe3fSMike Christie 				  "failed w/ status %04X\n", __func__,
1470d00efe3fSMike Christie 				  mbox_sts[0]));
1471d00efe3fSMike Christie 	}
1472d00efe3fSMike Christie 	return status;
1473d00efe3fSMike Christie }
1474b3a271a9SManish Rangankar 
1475b3a271a9SManish Rangankar int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
1476b3a271a9SManish Rangankar 			       struct ddb_entry *ddb_entry,
1477b3a271a9SManish Rangankar 			       struct iscsi_cls_conn *cls_conn,
1478b3a271a9SManish Rangankar 			       uint32_t *mbx_sts)
1479b3a271a9SManish Rangankar {
1480b3a271a9SManish Rangankar 	struct dev_db_entry *fw_ddb_entry;
1481b3a271a9SManish Rangankar 	struct iscsi_conn *conn;
1482b3a271a9SManish Rangankar 	struct iscsi_session *sess;
1483b3a271a9SManish Rangankar 	struct qla_conn *qla_conn;
1484b3a271a9SManish Rangankar 	struct sockaddr *dst_addr;
1485b3a271a9SManish Rangankar 	dma_addr_t fw_ddb_entry_dma;
1486b3a271a9SManish Rangankar 	int status = QLA_SUCCESS;
1487b3a271a9SManish Rangankar 	int rval = 0;
1488b3a271a9SManish Rangankar 	struct sockaddr_in *addr;
1489b3a271a9SManish Rangankar 	struct sockaddr_in6 *addr6;
1490b3a271a9SManish Rangankar 	char *ip;
1491b3a271a9SManish Rangankar 	uint16_t iscsi_opts = 0;
1492b3a271a9SManish Rangankar 	uint32_t options = 0;
1493b3a271a9SManish Rangankar 	uint16_t idx;
1494b3a271a9SManish Rangankar 	int max_chap_entries = 0;
1495b3a271a9SManish Rangankar 
1496b3a271a9SManish Rangankar 	fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
1497b3a271a9SManish Rangankar 					  &fw_ddb_entry_dma, GFP_KERNEL);
1498b3a271a9SManish Rangankar 	if (!fw_ddb_entry) {
1499b3a271a9SManish Rangankar 		DEBUG2(ql4_printk(KERN_ERR, ha,
1500b3a271a9SManish Rangankar 				  "%s: Unable to allocate dma buffer.\n",
1501b3a271a9SManish Rangankar 				  __func__));
1502b3a271a9SManish Rangankar 		rval = -ENOMEM;
1503b3a271a9SManish Rangankar 		goto exit_set_param_no_free;
1504b3a271a9SManish Rangankar 	}
1505b3a271a9SManish Rangankar 
1506b3a271a9SManish Rangankar 	conn = cls_conn->dd_data;
1507b3a271a9SManish Rangankar 	qla_conn = conn->dd_data;
1508b3a271a9SManish Rangankar 	sess = conn->session;
1509b3a271a9SManish Rangankar 	dst_addr = &qla_conn->qla_ep->dst_addr;
1510b3a271a9SManish Rangankar 
1511b3a271a9SManish Rangankar 	if (dst_addr->sa_family == AF_INET6)
1512b3a271a9SManish Rangankar 		options |= IPV6_DEFAULT_DDB_ENTRY;
1513b3a271a9SManish Rangankar 
1514b3a271a9SManish Rangankar 	status = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma);
1515b3a271a9SManish Rangankar 	if (status == QLA_ERROR) {
1516b3a271a9SManish Rangankar 		rval = -EINVAL;
1517b3a271a9SManish Rangankar 		goto exit_set_param;
1518b3a271a9SManish Rangankar 	}
1519b3a271a9SManish Rangankar 
1520b3a271a9SManish Rangankar 	iscsi_opts = le16_to_cpu(fw_ddb_entry->iscsi_options);
1521b3a271a9SManish Rangankar 	memset(fw_ddb_entry->iscsi_alias, 0, sizeof(fw_ddb_entry->iscsi_alias));
1522b3a271a9SManish Rangankar 
1523b3a271a9SManish Rangankar 	memset(fw_ddb_entry->iscsi_name, 0, sizeof(fw_ddb_entry->iscsi_name));
1524b3a271a9SManish Rangankar 
1525b3a271a9SManish Rangankar 	if (sess->targetname != NULL) {
1526b3a271a9SManish Rangankar 		memcpy(fw_ddb_entry->iscsi_name, sess->targetname,
1527b3a271a9SManish Rangankar 		       min(strlen(sess->targetname),
1528b3a271a9SManish Rangankar 		       sizeof(fw_ddb_entry->iscsi_name)));
1529b3a271a9SManish Rangankar 	}
1530b3a271a9SManish Rangankar 
1531b3a271a9SManish Rangankar 	memset(fw_ddb_entry->ip_addr, 0, sizeof(fw_ddb_entry->ip_addr));
1532b3a271a9SManish Rangankar 	memset(fw_ddb_entry->tgt_addr, 0, sizeof(fw_ddb_entry->tgt_addr));
1533b3a271a9SManish Rangankar 
1534b3a271a9SManish Rangankar 	fw_ddb_entry->options =  DDB_OPT_TARGET | DDB_OPT_AUTO_SENDTGTS_DISABLE;
1535b3a271a9SManish Rangankar 
1536b3a271a9SManish Rangankar 	if (dst_addr->sa_family == AF_INET) {
1537b3a271a9SManish Rangankar 		addr = (struct sockaddr_in *)dst_addr;
1538b3a271a9SManish Rangankar 		ip = (char *)&addr->sin_addr;
1539b3a271a9SManish Rangankar 		memcpy(fw_ddb_entry->ip_addr, ip, IP_ADDR_LEN);
1540b3a271a9SManish Rangankar 		fw_ddb_entry->port = cpu_to_le16(ntohs(addr->sin_port));
1541b3a271a9SManish Rangankar 		DEBUG2(ql4_printk(KERN_INFO, ha,
1542b3a271a9SManish Rangankar 				  "%s: Destination Address [%pI4]: index [%d]\n",
1543b3a271a9SManish Rangankar 				   __func__, fw_ddb_entry->ip_addr,
1544b3a271a9SManish Rangankar 				  ddb_entry->fw_ddb_index));
1545b3a271a9SManish Rangankar 	} else if (dst_addr->sa_family == AF_INET6) {
1546b3a271a9SManish Rangankar 		addr6 = (struct sockaddr_in6 *)dst_addr;
1547b3a271a9SManish Rangankar 		ip = (char *)&addr6->sin6_addr;
1548b3a271a9SManish Rangankar 		memcpy(fw_ddb_entry->ip_addr, ip, IPv6_ADDR_LEN);
1549b3a271a9SManish Rangankar 		fw_ddb_entry->port = cpu_to_le16(ntohs(addr6->sin6_port));
1550b3a271a9SManish Rangankar 		fw_ddb_entry->options |= DDB_OPT_IPV6_DEVICE;
1551b3a271a9SManish Rangankar 		DEBUG2(ql4_printk(KERN_INFO, ha,
1552b3a271a9SManish Rangankar 				  "%s: Destination Address [%pI6]: index [%d]\n",
1553b3a271a9SManish Rangankar 				   __func__, fw_ddb_entry->ip_addr,
1554b3a271a9SManish Rangankar 				  ddb_entry->fw_ddb_index));
1555b3a271a9SManish Rangankar 	} else {
1556b3a271a9SManish Rangankar 		ql4_printk(KERN_ERR, ha,
1557b3a271a9SManish Rangankar 			   "%s: Failed to get IP Address\n",
1558b3a271a9SManish Rangankar 			   __func__);
1559b3a271a9SManish Rangankar 		rval = -EINVAL;
1560b3a271a9SManish Rangankar 		goto exit_set_param;
1561b3a271a9SManish Rangankar 	}
1562b3a271a9SManish Rangankar 
1563b3a271a9SManish Rangankar 	if (is_qla8022(ha))
1564b3a271a9SManish Rangankar 		max_chap_entries = MAX_CHAP_ENTRIES_82XX;
1565b3a271a9SManish Rangankar 	else
1566b3a271a9SManish Rangankar 		max_chap_entries = MAX_CHAP_ENTRIES_40XX;
1567b3a271a9SManish Rangankar 	/* CHAP */
1568b3a271a9SManish Rangankar 	if (sess->username != NULL && sess->password != NULL) {
1569b3a271a9SManish Rangankar 		if (strlen(sess->username) && strlen(sess->password)) {
1570b3a271a9SManish Rangankar 			iscsi_opts |= BIT_7;
1571b3a271a9SManish Rangankar 			idx = ddb_entry->fw_ddb_index * 2;
1572b3a271a9SManish Rangankar 			if (idx > max_chap_entries) {
1573b3a271a9SManish Rangankar 				ql4_printk(KERN_ERR, ha,
1574b3a271a9SManish Rangankar 					   "%s: Invalid ddb or chap index\n",
1575b3a271a9SManish Rangankar 					   __func__);
1576b3a271a9SManish Rangankar 				rval  = -EINVAL;
1577b3a271a9SManish Rangankar 				goto exit_set_param;
1578b3a271a9SManish Rangankar 			}
1579b3a271a9SManish Rangankar 
1580b3a271a9SManish Rangankar 			rval = qla4xxx_set_chap(ha, sess->username,
1581b3a271a9SManish Rangankar 						sess->password, idx, 0);
1582b3a271a9SManish Rangankar 			if (rval)
1583b3a271a9SManish Rangankar 				goto exit_set_param;
1584b3a271a9SManish Rangankar 
1585b3a271a9SManish Rangankar 			fw_ddb_entry->chap_tbl_idx = cpu_to_le16(idx);
1586b3a271a9SManish Rangankar 		}
1587b3a271a9SManish Rangankar 	}
1588b3a271a9SManish Rangankar 
1589b3a271a9SManish Rangankar 	if (sess->username_in != NULL && sess->password_in != NULL) {
1590b3a271a9SManish Rangankar 		/* Check if BIDI CHAP */
1591b3a271a9SManish Rangankar 		if (strlen(sess->username_in) && strlen(sess->password_in)) {
1592b3a271a9SManish Rangankar 			iscsi_opts |= BIT_4;
1593b3a271a9SManish Rangankar 			idx = (ddb_entry->fw_ddb_index * 2) + 1;
1594b3a271a9SManish Rangankar 			if (idx > max_chap_entries) {
1595b3a271a9SManish Rangankar 				ql4_printk(KERN_ERR, ha,
1596b3a271a9SManish Rangankar 					   "%s: Invalid ddb or bidi chap "
1597b3a271a9SManish Rangankar 					   "index\n", __func__);
1598b3a271a9SManish Rangankar 				rval  = -EINVAL;
1599b3a271a9SManish Rangankar 				goto exit_set_param;
1600b3a271a9SManish Rangankar 			}
1601b3a271a9SManish Rangankar 			rval = qla4xxx_set_chap(ha, sess->username_in,
1602b3a271a9SManish Rangankar 						sess->password_in, idx, 0);
1603b3a271a9SManish Rangankar 			if (rval)
1604b3a271a9SManish Rangankar 				goto exit_set_param;
1605b3a271a9SManish Rangankar 		}
1606b3a271a9SManish Rangankar 	}
1607b3a271a9SManish Rangankar 
1608b3a271a9SManish Rangankar 	if (sess->initial_r2t_en)
1609b3a271a9SManish Rangankar 		iscsi_opts |= BIT_10;
1610b3a271a9SManish Rangankar 
1611b3a271a9SManish Rangankar 	if (sess->imm_data_en)
1612b3a271a9SManish Rangankar 		iscsi_opts |= BIT_11;
1613b3a271a9SManish Rangankar 
1614b3a271a9SManish Rangankar 	fw_ddb_entry->iscsi_options = cpu_to_le16(iscsi_opts);
1615b3a271a9SManish Rangankar 
1616b3a271a9SManish Rangankar 	if (conn->max_recv_dlength)
1617b3a271a9SManish Rangankar 		fw_ddb_entry->iscsi_max_rcv_data_seg_len =
1618b3a271a9SManish Rangankar 		  __constant_cpu_to_le16((conn->max_recv_dlength / BYTE_UNITS));
1619b3a271a9SManish Rangankar 
1620b3a271a9SManish Rangankar 	if (sess->max_r2t)
1621b3a271a9SManish Rangankar 		fw_ddb_entry->iscsi_max_outsnd_r2t = cpu_to_le16(sess->max_r2t);
1622b3a271a9SManish Rangankar 
1623b3a271a9SManish Rangankar 	if (sess->first_burst)
1624b3a271a9SManish Rangankar 		fw_ddb_entry->iscsi_first_burst_len =
1625b3a271a9SManish Rangankar 		       __constant_cpu_to_le16((sess->first_burst / BYTE_UNITS));
1626b3a271a9SManish Rangankar 
1627b3a271a9SManish Rangankar 	if (sess->max_burst)
1628b3a271a9SManish Rangankar 		fw_ddb_entry->iscsi_max_burst_len =
1629b3a271a9SManish Rangankar 			__constant_cpu_to_le16((sess->max_burst / BYTE_UNITS));
1630b3a271a9SManish Rangankar 
1631b3a271a9SManish Rangankar 	if (sess->time2wait)
1632b3a271a9SManish Rangankar 		fw_ddb_entry->iscsi_def_time2wait =
1633b3a271a9SManish Rangankar 			cpu_to_le16(sess->time2wait);
1634b3a271a9SManish Rangankar 
1635b3a271a9SManish Rangankar 	if (sess->time2retain)
1636b3a271a9SManish Rangankar 		fw_ddb_entry->iscsi_def_time2retain =
1637b3a271a9SManish Rangankar 			cpu_to_le16(sess->time2retain);
1638b3a271a9SManish Rangankar 
1639b3a271a9SManish Rangankar 	status = qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index,
1640b3a271a9SManish Rangankar 				       fw_ddb_entry_dma, mbx_sts);
1641b3a271a9SManish Rangankar 
1642b3a271a9SManish Rangankar 	if (status != QLA_SUCCESS)
1643b3a271a9SManish Rangankar 		rval = -EINVAL;
1644b3a271a9SManish Rangankar exit_set_param:
1645b3a271a9SManish Rangankar 	dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
1646b3a271a9SManish Rangankar 			  fw_ddb_entry, fw_ddb_entry_dma);
1647b3a271a9SManish Rangankar exit_set_param_no_free:
1648b3a271a9SManish Rangankar 	return rval;
1649b3a271a9SManish Rangankar }
1650b3a271a9SManish Rangankar 
1651b3a271a9SManish Rangankar int qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index,
1652b3a271a9SManish Rangankar 			  uint16_t stats_size, dma_addr_t stats_dma)
1653b3a271a9SManish Rangankar {
1654b3a271a9SManish Rangankar 	int status = QLA_SUCCESS;
1655b3a271a9SManish Rangankar 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1656b3a271a9SManish Rangankar 	uint32_t mbox_sts[MBOX_REG_COUNT];
1657b3a271a9SManish Rangankar 
1658b3a271a9SManish Rangankar 	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
1659b3a271a9SManish Rangankar 	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
1660b3a271a9SManish Rangankar 	mbox_cmd[0] = MBOX_CMD_GET_MANAGEMENT_DATA;
1661b3a271a9SManish Rangankar 	mbox_cmd[1] = fw_ddb_index;
1662b3a271a9SManish Rangankar 	mbox_cmd[2] = LSDW(stats_dma);
1663b3a271a9SManish Rangankar 	mbox_cmd[3] = MSDW(stats_dma);
1664b3a271a9SManish Rangankar 	mbox_cmd[4] = stats_size;
1665b3a271a9SManish Rangankar 
1666b3a271a9SManish Rangankar 	status = qla4xxx_mailbox_command(ha, 5, 1, &mbox_cmd[0], &mbox_sts[0]);
1667b3a271a9SManish Rangankar 	if (status != QLA_SUCCESS) {
1668b3a271a9SManish Rangankar 		DEBUG2(ql4_printk(KERN_WARNING, ha,
1669b3a271a9SManish Rangankar 				  "%s: MBOX_CMD_GET_MANAGEMENT_DATA "
1670b3a271a9SManish Rangankar 				  "failed w/ status %04X\n", __func__,
1671b3a271a9SManish Rangankar 				  mbox_sts[0]));
1672b3a271a9SManish Rangankar 	}
1673b3a271a9SManish Rangankar 	return status;
1674b3a271a9SManish Rangankar }
16758b0402e1SHarish Zunjarrao 
16768b0402e1SHarish Zunjarrao int qla4xxx_get_ip_state(struct scsi_qla_host *ha, uint32_t acb_idx,
16778b0402e1SHarish Zunjarrao 			 uint32_t ip_idx, uint32_t *sts)
16788b0402e1SHarish Zunjarrao {
16798b0402e1SHarish Zunjarrao 	uint32_t mbox_cmd[MBOX_REG_COUNT];
16808b0402e1SHarish Zunjarrao 	uint32_t mbox_sts[MBOX_REG_COUNT];
16818b0402e1SHarish Zunjarrao 	int status = QLA_SUCCESS;
16828b0402e1SHarish Zunjarrao 
16838b0402e1SHarish Zunjarrao 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
16848b0402e1SHarish Zunjarrao 	memset(&mbox_sts, 0, sizeof(mbox_sts));
16858b0402e1SHarish Zunjarrao 	mbox_cmd[0] = MBOX_CMD_GET_IP_ADDR_STATE;
16868b0402e1SHarish Zunjarrao 	mbox_cmd[1] = acb_idx;
16878b0402e1SHarish Zunjarrao 	mbox_cmd[2] = ip_idx;
16888b0402e1SHarish Zunjarrao 
16898b0402e1SHarish Zunjarrao 	status = qla4xxx_mailbox_command(ha, 3, 8, &mbox_cmd[0], &mbox_sts[0]);
16908b0402e1SHarish Zunjarrao 	if (status != QLA_SUCCESS) {
16918b0402e1SHarish Zunjarrao 		DEBUG2(ql4_printk(KERN_WARNING, ha,  "%s: "
16928b0402e1SHarish Zunjarrao 				  "MBOX_CMD_GET_IP_ADDR_STATE failed w/ "
16938b0402e1SHarish Zunjarrao 				  "status %04X\n", __func__, mbox_sts[0]));
16948b0402e1SHarish Zunjarrao 	}
16958b0402e1SHarish Zunjarrao 	memcpy(sts, mbox_sts, sizeof(mbox_sts));
16968b0402e1SHarish Zunjarrao 	return status;
16978b0402e1SHarish Zunjarrao }
16987c07d139SHarish Zunjarrao 
16997c07d139SHarish Zunjarrao int qla4xxx_get_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,
17007c07d139SHarish Zunjarrao 		      uint32_t offset, uint32_t size)
17017c07d139SHarish Zunjarrao {
17027c07d139SHarish Zunjarrao 	int status = QLA_SUCCESS;
17037c07d139SHarish Zunjarrao 	uint32_t mbox_cmd[MBOX_REG_COUNT];
17047c07d139SHarish Zunjarrao 	uint32_t mbox_sts[MBOX_REG_COUNT];
17057c07d139SHarish Zunjarrao 
17067c07d139SHarish Zunjarrao 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
17077c07d139SHarish Zunjarrao 	memset(&mbox_sts, 0, sizeof(mbox_sts));
17087c07d139SHarish Zunjarrao 
17097c07d139SHarish Zunjarrao 	mbox_cmd[0] = MBOX_CMD_GET_NVRAM;
17107c07d139SHarish Zunjarrao 	mbox_cmd[1] = LSDW(nvram_dma);
17117c07d139SHarish Zunjarrao 	mbox_cmd[2] = MSDW(nvram_dma);
17127c07d139SHarish Zunjarrao 	mbox_cmd[3] = offset;
17137c07d139SHarish Zunjarrao 	mbox_cmd[4] = size;
17147c07d139SHarish Zunjarrao 
17157c07d139SHarish Zunjarrao 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
17167c07d139SHarish Zunjarrao 					 &mbox_sts[0]);
17177c07d139SHarish Zunjarrao 	if (status != QLA_SUCCESS) {
17187c07d139SHarish Zunjarrao 		DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
17197c07d139SHarish Zunjarrao 				  "status %04X\n", ha->host_no, __func__,
17207c07d139SHarish Zunjarrao 				  mbox_sts[0]));
17217c07d139SHarish Zunjarrao 	}
17227c07d139SHarish Zunjarrao 	return status;
17237c07d139SHarish Zunjarrao }
17247c07d139SHarish Zunjarrao 
17257c07d139SHarish Zunjarrao int qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,
17267c07d139SHarish Zunjarrao 		      uint32_t offset, uint32_t size)
17277c07d139SHarish Zunjarrao {
17287c07d139SHarish Zunjarrao 	int status = QLA_SUCCESS;
17297c07d139SHarish Zunjarrao 	uint32_t mbox_cmd[MBOX_REG_COUNT];
17307c07d139SHarish Zunjarrao 	uint32_t mbox_sts[MBOX_REG_COUNT];
17317c07d139SHarish Zunjarrao 
17327c07d139SHarish Zunjarrao 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
17337c07d139SHarish Zunjarrao 	memset(&mbox_sts, 0, sizeof(mbox_sts));
17347c07d139SHarish Zunjarrao 
17357c07d139SHarish Zunjarrao 	mbox_cmd[0] = MBOX_CMD_SET_NVRAM;
17367c07d139SHarish Zunjarrao 	mbox_cmd[1] = LSDW(nvram_dma);
17377c07d139SHarish Zunjarrao 	mbox_cmd[2] = MSDW(nvram_dma);
17387c07d139SHarish Zunjarrao 	mbox_cmd[3] = offset;
17397c07d139SHarish Zunjarrao 	mbox_cmd[4] = size;
17407c07d139SHarish Zunjarrao 
17417c07d139SHarish Zunjarrao 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
17427c07d139SHarish Zunjarrao 					 &mbox_sts[0]);
17437c07d139SHarish Zunjarrao 	if (status != QLA_SUCCESS) {
17447c07d139SHarish Zunjarrao 		DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
17457c07d139SHarish Zunjarrao 				  "status %04X\n", ha->host_no, __func__,
17467c07d139SHarish Zunjarrao 				  mbox_sts[0]));
17477c07d139SHarish Zunjarrao 	}
17487c07d139SHarish Zunjarrao 	return status;
17497c07d139SHarish Zunjarrao }
17505232f801SHarish Zunjarrao 
17515232f801SHarish Zunjarrao int qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha,
17525232f801SHarish Zunjarrao 				     uint32_t region, uint32_t field0,
17535232f801SHarish Zunjarrao 				     uint32_t field1)
17545232f801SHarish Zunjarrao {
17555232f801SHarish Zunjarrao 	int status = QLA_SUCCESS;
17565232f801SHarish Zunjarrao 	uint32_t mbox_cmd[MBOX_REG_COUNT];
17575232f801SHarish Zunjarrao 	uint32_t mbox_sts[MBOX_REG_COUNT];
17585232f801SHarish Zunjarrao 
17595232f801SHarish Zunjarrao 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
17605232f801SHarish Zunjarrao 	memset(&mbox_sts, 0, sizeof(mbox_sts));
17615232f801SHarish Zunjarrao 
17625232f801SHarish Zunjarrao 	mbox_cmd[0] = MBOX_CMD_RESTORE_FACTORY_DEFAULTS;
17635232f801SHarish Zunjarrao 	mbox_cmd[3] = region;
17645232f801SHarish Zunjarrao 	mbox_cmd[4] = field0;
17655232f801SHarish Zunjarrao 	mbox_cmd[5] = field1;
17665232f801SHarish Zunjarrao 
17675232f801SHarish Zunjarrao 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0],
17685232f801SHarish Zunjarrao 					 &mbox_sts[0]);
17695232f801SHarish Zunjarrao 	if (status != QLA_SUCCESS) {
17705232f801SHarish Zunjarrao 		DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
17715232f801SHarish Zunjarrao 				  "status %04X\n", ha->host_no, __func__,
17725232f801SHarish Zunjarrao 				  mbox_sts[0]));
17735232f801SHarish Zunjarrao 	}
17745232f801SHarish Zunjarrao 	return status;
17755232f801SHarish Zunjarrao }
1776