xref: /linux/drivers/scsi/qla4xxx/ql4_mbx.c (revision 7eece5a084264c1bff908b0d6a1b176b39dd272f)
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  *
22f4f5df23SVikas Chaudhary  * This routine isssue 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 	/* To prevent overwriting mailbox registers for a command that has
90f4f5df23SVikas Chaudhary 	 * not yet been serviced, check to see if an active command
91f4f5df23SVikas Chaudhary 	 * (AEN, IOCB, etc.) is interrupting, then service it.
92afaf5a2dSDavid Somayajulu 	 * -----------------------------------------------------------------
93afaf5a2dSDavid Somayajulu 	 */
94afaf5a2dSDavid Somayajulu 	spin_lock_irqsave(&ha->hardware_lock, flags);
95f4f5df23SVikas Chaudhary 
96e6b07df8SLalit Chandivade 	if (!is_qla8022(ha)) {
97afaf5a2dSDavid Somayajulu 		intr_status = readl(&ha->reg->ctrl_status);
98afaf5a2dSDavid Somayajulu 		if (intr_status & CSR_SCSI_PROCESSOR_INTR) {
99afaf5a2dSDavid Somayajulu 			/* Service existing interrupt */
100f4f5df23SVikas Chaudhary 			ha->isp_ops->interrupt_service_routine(ha, intr_status);
101afaf5a2dSDavid Somayajulu 			clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
102afaf5a2dSDavid Somayajulu 		}
103f4f5df23SVikas Chaudhary 	}
104afaf5a2dSDavid Somayajulu 
105afaf5a2dSDavid Somayajulu 	ha->mbox_status_count = outCount;
106afaf5a2dSDavid Somayajulu 	for (i = 0; i < outCount; i++)
107afaf5a2dSDavid Somayajulu 		ha->mbox_status[i] = 0;
108afaf5a2dSDavid Somayajulu 
109f4f5df23SVikas Chaudhary 	if (is_qla8022(ha)) {
110f4f5df23SVikas Chaudhary 		/* Load all mailbox registers, except mailbox 0. */
111f4f5df23SVikas Chaudhary 		DEBUG5(
112f4f5df23SVikas Chaudhary 		    printk("scsi%ld: %s: Cmd ", ha->host_no, __func__);
113f4f5df23SVikas Chaudhary 		    for (i = 0; i < inCount; i++)
114f4f5df23SVikas Chaudhary 			printk("mb%d=%04x ", i, mbx_cmd[i]);
115f4f5df23SVikas Chaudhary 		    printk("\n"));
116f4f5df23SVikas Chaudhary 
117f4f5df23SVikas Chaudhary 		for (i = 1; i < inCount; i++)
118f4f5df23SVikas Chaudhary 			writel(mbx_cmd[i], &ha->qla4_8xxx_reg->mailbox_in[i]);
119f4f5df23SVikas Chaudhary 		writel(mbx_cmd[0], &ha->qla4_8xxx_reg->mailbox_in[0]);
120f4f5df23SVikas Chaudhary 		readl(&ha->qla4_8xxx_reg->mailbox_in[0]);
121f4f5df23SVikas Chaudhary 		writel(HINT_MBX_INT_PENDING, &ha->qla4_8xxx_reg->hint);
122f4f5df23SVikas Chaudhary 	} else {
123afaf5a2dSDavid Somayajulu 		/* Load all mailbox registers, except mailbox 0. */
124afaf5a2dSDavid Somayajulu 		for (i = 1; i < inCount; i++)
125afaf5a2dSDavid Somayajulu 			writel(mbx_cmd[i], &ha->reg->mailbox[i]);
126afaf5a2dSDavid Somayajulu 
127afaf5a2dSDavid Somayajulu 		/* Wakeup firmware  */
128afaf5a2dSDavid Somayajulu 		writel(mbx_cmd[0], &ha->reg->mailbox[0]);
129afaf5a2dSDavid Somayajulu 		readl(&ha->reg->mailbox[0]);
130afaf5a2dSDavid Somayajulu 		writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status);
131afaf5a2dSDavid Somayajulu 		readl(&ha->reg->ctrl_status);
132f4f5df23SVikas Chaudhary 	}
133f4f5df23SVikas Chaudhary 
134afaf5a2dSDavid Somayajulu 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
135afaf5a2dSDavid Somayajulu 
136afaf5a2dSDavid Somayajulu 	/* Wait for completion */
137afaf5a2dSDavid Somayajulu 
138afaf5a2dSDavid Somayajulu 	/*
139afaf5a2dSDavid Somayajulu 	 * If we don't want status, don't wait for the mailbox command to
140afaf5a2dSDavid Somayajulu 	 * complete.  For example, MBOX_CMD_RESET_FW doesn't return status,
141afaf5a2dSDavid Somayajulu 	 * you must poll the inbound Interrupt Mask for completion.
142afaf5a2dSDavid Somayajulu 	 */
143afaf5a2dSDavid Somayajulu 	if (outCount == 0) {
144afaf5a2dSDavid Somayajulu 		status = QLA_SUCCESS;
145afaf5a2dSDavid Somayajulu 		goto mbox_exit;
146afaf5a2dSDavid Somayajulu 	}
147f4f5df23SVikas Chaudhary 
148f4f5df23SVikas Chaudhary 	/*
149f4f5df23SVikas Chaudhary 	 * Wait for completion: Poll or completion queue
150f4f5df23SVikas Chaudhary 	 */
151f4f5df23SVikas Chaudhary 	if (test_bit(AF_IRQ_ATTACHED, &ha->flags) &&
152f4f5df23SVikas Chaudhary 	    test_bit(AF_INTERRUPTS_ON, &ha->flags) &&
153f4f5df23SVikas Chaudhary 	    test_bit(AF_ONLINE, &ha->flags) &&
154*7eece5a0SKaren Higgins 	    !test_bit(AF_HA_REMOVAL, &ha->flags)) {
155f4f5df23SVikas Chaudhary 		/* Do not poll for completion. Use completion queue */
156f4f5df23SVikas Chaudhary 		set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
157f4f5df23SVikas Chaudhary 		wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ);
158f4f5df23SVikas Chaudhary 		clear_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
159f4f5df23SVikas Chaudhary 	} else {
160f4f5df23SVikas Chaudhary 		/* Poll for command to complete */
161afaf5a2dSDavid Somayajulu 		wait_count = jiffies + MBOX_TOV * HZ;
162afaf5a2dSDavid Somayajulu 		while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) {
163afaf5a2dSDavid Somayajulu 			if (time_after_eq(jiffies, wait_count))
164afaf5a2dSDavid Somayajulu 				break;
1652232be0dSLalit Chandivade 
166afaf5a2dSDavid Somayajulu 			/*
167afaf5a2dSDavid Somayajulu 			 * Service the interrupt.
168afaf5a2dSDavid Somayajulu 			 * The ISR will save the mailbox status registers
169afaf5a2dSDavid Somayajulu 			 * to a temporary storage location in the adapter
170afaf5a2dSDavid Somayajulu 			 * structure.
171afaf5a2dSDavid Somayajulu 			 */
172f4f5df23SVikas Chaudhary 
173f4f5df23SVikas Chaudhary 			spin_lock_irqsave(&ha->hardware_lock, flags);
174f4f5df23SVikas Chaudhary 			if (is_qla8022(ha)) {
175f4f5df23SVikas Chaudhary 				intr_status =
176f4f5df23SVikas Chaudhary 				    readl(&ha->qla4_8xxx_reg->host_int);
177f4f5df23SVikas Chaudhary 				if (intr_status & ISRX_82XX_RISC_INT) {
178afaf5a2dSDavid Somayajulu 					ha->mbox_status_count = outCount;
179f4f5df23SVikas Chaudhary 					intr_status =
180f4f5df23SVikas Chaudhary 					 readl(&ha->qla4_8xxx_reg->host_status);
181f4f5df23SVikas Chaudhary 					ha->isp_ops->interrupt_service_routine(
182f4f5df23SVikas Chaudhary 					    ha, intr_status);
183f4f5df23SVikas Chaudhary 					if (test_bit(AF_INTERRUPTS_ON,
184f4f5df23SVikas Chaudhary 					    &ha->flags) &&
185f4f5df23SVikas Chaudhary 					    test_bit(AF_INTx_ENABLED,
186f4f5df23SVikas Chaudhary 					    &ha->flags))
187f4f5df23SVikas Chaudhary 						qla4_8xxx_wr_32(ha,
188f4f5df23SVikas Chaudhary 						ha->nx_legacy_intr.tgt_mask_reg,
189f4f5df23SVikas Chaudhary 						0xfbff);
190f4f5df23SVikas Chaudhary 				}
191f4f5df23SVikas Chaudhary 			} else {
192f4f5df23SVikas Chaudhary 				intr_status = readl(&ha->reg->ctrl_status);
193f4f5df23SVikas Chaudhary 				if (intr_status & INTR_PENDING) {
194f4f5df23SVikas Chaudhary 					/*
195f4f5df23SVikas Chaudhary 					 * Service the interrupt.
196f4f5df23SVikas Chaudhary 					 * The ISR will save the mailbox status
197f4f5df23SVikas Chaudhary 					 * registers to a temporary storage
198f4f5df23SVikas Chaudhary 					 * location in the adapter structure.
199f4f5df23SVikas Chaudhary 					 */
200f4f5df23SVikas Chaudhary 					ha->mbox_status_count = outCount;
201f4f5df23SVikas Chaudhary 					ha->isp_ops->interrupt_service_routine(
202f4f5df23SVikas Chaudhary 					    ha, intr_status);
203f4f5df23SVikas Chaudhary 				}
204afaf5a2dSDavid Somayajulu 			}
205afaf5a2dSDavid Somayajulu 			spin_unlock_irqrestore(&ha->hardware_lock, flags);
206afaf5a2dSDavid Somayajulu 			msleep(10);
207afaf5a2dSDavid Somayajulu 		}
208f4f5df23SVikas Chaudhary 	}
209afaf5a2dSDavid Somayajulu 
210afaf5a2dSDavid Somayajulu 	/* Check for mailbox timeout. */
211afaf5a2dSDavid Somayajulu 	if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) {
21221033639SNilesh Javali 		if (is_qla8022(ha) &&
21321033639SNilesh Javali 		    test_bit(AF_FW_RECOVERY, &ha->flags)) {
21421033639SNilesh Javali 			DEBUG2(ql4_printk(KERN_INFO, ha,
21521033639SNilesh Javali 			    "scsi%ld: %s: prematurely completing mbx cmd as "
21621033639SNilesh Javali 			    "firmware recovery detected\n",
21721033639SNilesh Javali 			    ha->host_no, __func__));
21821033639SNilesh Javali 			goto mbox_exit;
21921033639SNilesh Javali 		}
220afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: Mailbox Cmd 0x%08X timed out ...,"
221afaf5a2dSDavid Somayajulu 			      " Scheduling Adapter Reset\n", ha->host_no,
222afaf5a2dSDavid Somayajulu 			      mbx_cmd[0]));
223afaf5a2dSDavid Somayajulu 		ha->mailbox_timeout_count++;
224afaf5a2dSDavid Somayajulu 		mbx_sts[0] = (-1);
225afaf5a2dSDavid Somayajulu 		set_bit(DPC_RESET_HA, &ha->dpc_flags);
226afaf5a2dSDavid Somayajulu 		goto mbox_exit;
227afaf5a2dSDavid Somayajulu 	}
228afaf5a2dSDavid Somayajulu 
229afaf5a2dSDavid Somayajulu 	/*
230afaf5a2dSDavid Somayajulu 	 * Copy the mailbox out registers to the caller's mailbox in/out
231afaf5a2dSDavid Somayajulu 	 * structure.
232afaf5a2dSDavid Somayajulu 	 */
233afaf5a2dSDavid Somayajulu 	spin_lock_irqsave(&ha->hardware_lock, flags);
234afaf5a2dSDavid Somayajulu 	for (i = 0; i < outCount; i++)
235afaf5a2dSDavid Somayajulu 		mbx_sts[i] = ha->mbox_status[i];
236afaf5a2dSDavid Somayajulu 
237afaf5a2dSDavid Somayajulu 	/* Set return status and error flags (if applicable). */
238afaf5a2dSDavid Somayajulu 	switch (ha->mbox_status[0]) {
239afaf5a2dSDavid Somayajulu 	case MBOX_STS_COMMAND_COMPLETE:
240afaf5a2dSDavid Somayajulu 		status = QLA_SUCCESS;
241afaf5a2dSDavid Somayajulu 		break;
242afaf5a2dSDavid Somayajulu 
243afaf5a2dSDavid Somayajulu 	case MBOX_STS_INTERMEDIATE_COMPLETION:
244afaf5a2dSDavid Somayajulu 		status = QLA_SUCCESS;
245afaf5a2dSDavid Somayajulu 		break;
246afaf5a2dSDavid Somayajulu 
247afaf5a2dSDavid Somayajulu 	case MBOX_STS_BUSY:
248afaf5a2dSDavid Somayajulu 		DEBUG2( printk("scsi%ld: %s: Cmd = %08X, ISP BUSY\n",
249afaf5a2dSDavid Somayajulu 			       ha->host_no, __func__, mbx_cmd[0]));
250afaf5a2dSDavid Somayajulu 		ha->mailbox_timeout_count++;
251afaf5a2dSDavid Somayajulu 		break;
252afaf5a2dSDavid Somayajulu 
253afaf5a2dSDavid Somayajulu 	default:
254afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: **** FAILED, cmd = %08X, "
255afaf5a2dSDavid Somayajulu 			      "sts = %08X ****\n", ha->host_no, __func__,
256afaf5a2dSDavid Somayajulu 			      mbx_cmd[0], mbx_sts[0]));
257afaf5a2dSDavid Somayajulu 		break;
258afaf5a2dSDavid Somayajulu 	}
259afaf5a2dSDavid Somayajulu 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
260afaf5a2dSDavid Somayajulu 
261afaf5a2dSDavid Somayajulu mbox_exit:
262477ffb9dSDavid C Somayajulu 	mutex_lock(&ha->mbox_sem);
263afaf5a2dSDavid Somayajulu 	clear_bit(AF_MBOX_COMMAND, &ha->flags);
264afaf5a2dSDavid Somayajulu 	mutex_unlock(&ha->mbox_sem);
265477ffb9dSDavid C Somayajulu 	clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
266afaf5a2dSDavid Somayajulu 
267afaf5a2dSDavid Somayajulu 	return status;
268afaf5a2dSDavid Somayajulu }
269afaf5a2dSDavid Somayajulu 
27021033639SNilesh Javali void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha)
27121033639SNilesh Javali {
27221033639SNilesh Javali 	set_bit(AF_FW_RECOVERY, &ha->flags);
27321033639SNilesh Javali 	ql4_printk(KERN_INFO, ha, "scsi%ld: %s: set FW RECOVERY!\n",
27421033639SNilesh Javali 	    ha->host_no, __func__);
27521033639SNilesh Javali 
27621033639SNilesh Javali 	if (test_bit(AF_MBOX_COMMAND, &ha->flags)) {
27721033639SNilesh Javali 		if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags)) {
27821033639SNilesh Javali 			complete(&ha->mbx_intr_comp);
27921033639SNilesh Javali 			ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw "
28021033639SNilesh Javali 			    "recovery, doing premature completion of "
28121033639SNilesh Javali 			    "mbx cmd\n", ha->host_no, __func__);
28221033639SNilesh Javali 
28321033639SNilesh Javali 		} else {
28421033639SNilesh Javali 			set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
28521033639SNilesh Javali 			ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw "
28621033639SNilesh Javali 			    "recovery, doing premature completion of "
28721033639SNilesh Javali 			    "polling mbx cmd\n", ha->host_no, __func__);
28821033639SNilesh Javali 		}
28921033639SNilesh Javali 	}
29021033639SNilesh Javali }
29121033639SNilesh Javali 
292f4f5df23SVikas Chaudhary static uint8_t
2932a49a78eSVikas Chaudhary qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
2942a49a78eSVikas Chaudhary 		 uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)
2952a49a78eSVikas Chaudhary {
2962a49a78eSVikas Chaudhary 	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
2972a49a78eSVikas Chaudhary 	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
2982657c800SShyam Sundar 
2992657c800SShyam Sundar 	if (is_qla8022(ha))
3002657c800SShyam Sundar 		qla4_8xxx_wr_32(ha, ha->nx_db_wr_ptr, 0);
3012657c800SShyam Sundar 
3022a49a78eSVikas Chaudhary 	mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE;
3032a49a78eSVikas Chaudhary 	mbox_cmd[1] = 0;
3042a49a78eSVikas Chaudhary 	mbox_cmd[2] = LSDW(init_fw_cb_dma);
3052a49a78eSVikas Chaudhary 	mbox_cmd[3] = MSDW(init_fw_cb_dma);
3062a49a78eSVikas Chaudhary 	mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
3072a49a78eSVikas Chaudhary 	mbox_cmd[5] = (IFCB_VER_MAX << 8) | IFCB_VER_MIN;
3082a49a78eSVikas Chaudhary 
3092a49a78eSVikas Chaudhary 	if (qla4xxx_mailbox_command(ha, 6, 6, mbox_cmd, mbox_sts) !=
3102a49a78eSVikas Chaudhary 	    QLA_SUCCESS) {
3112a49a78eSVikas Chaudhary 		DEBUG2(printk(KERN_WARNING "scsi%ld: %s: "
3122a49a78eSVikas Chaudhary 			      "MBOX_CMD_INITIALIZE_FIRMWARE"
3132a49a78eSVikas Chaudhary 			      " failed w/ status %04X\n",
3142a49a78eSVikas Chaudhary 			      ha->host_no, __func__, mbox_sts[0]));
3152a49a78eSVikas Chaudhary 		return QLA_ERROR;
3162a49a78eSVikas Chaudhary 	}
3172a49a78eSVikas Chaudhary 	return QLA_SUCCESS;
3182a49a78eSVikas Chaudhary }
3192a49a78eSVikas Chaudhary 
320f4f5df23SVikas Chaudhary static uint8_t
3212a49a78eSVikas Chaudhary qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
3222a49a78eSVikas Chaudhary 		 uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)
3232a49a78eSVikas Chaudhary {
3242a49a78eSVikas Chaudhary 	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
3252a49a78eSVikas Chaudhary 	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
3262a49a78eSVikas Chaudhary 	mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
3272a49a78eSVikas Chaudhary 	mbox_cmd[2] = LSDW(init_fw_cb_dma);
3282a49a78eSVikas Chaudhary 	mbox_cmd[3] = MSDW(init_fw_cb_dma);
3292a49a78eSVikas Chaudhary 	mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
3302a49a78eSVikas Chaudhary 
3312a49a78eSVikas Chaudhary 	if (qla4xxx_mailbox_command(ha, 5, 5, mbox_cmd, mbox_sts) !=
3322a49a78eSVikas Chaudhary 	    QLA_SUCCESS) {
3332a49a78eSVikas Chaudhary 		DEBUG2(printk(KERN_WARNING "scsi%ld: %s: "
3342a49a78eSVikas Chaudhary 			      "MBOX_CMD_GET_INIT_FW_CTRL_BLOCK"
3352a49a78eSVikas Chaudhary 			      " failed w/ status %04X\n",
3362a49a78eSVikas Chaudhary 			      ha->host_no, __func__, mbox_sts[0]));
3372a49a78eSVikas Chaudhary 		return QLA_ERROR;
3382a49a78eSVikas Chaudhary 	}
3392a49a78eSVikas Chaudhary 	return QLA_SUCCESS;
3402a49a78eSVikas Chaudhary }
3412a49a78eSVikas Chaudhary 
342f4f5df23SVikas Chaudhary static void
3432a49a78eSVikas Chaudhary qla4xxx_update_local_ip(struct scsi_qla_host *ha,
3442a49a78eSVikas Chaudhary 			 struct addr_ctrl_blk  *init_fw_cb)
3452a49a78eSVikas Chaudhary {
3462a49a78eSVikas Chaudhary 	/* Save IPv4 Address Info */
3472a49a78eSVikas Chaudhary 	memcpy(ha->ip_address, init_fw_cb->ipv4_addr,
3482a49a78eSVikas Chaudhary 		min(sizeof(ha->ip_address), sizeof(init_fw_cb->ipv4_addr)));
3492a49a78eSVikas Chaudhary 	memcpy(ha->subnet_mask, init_fw_cb->ipv4_subnet,
3502a49a78eSVikas Chaudhary 		min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->ipv4_subnet)));
3512a49a78eSVikas Chaudhary 	memcpy(ha->gateway, init_fw_cb->ipv4_gw_addr,
3522a49a78eSVikas Chaudhary 		min(sizeof(ha->gateway), sizeof(init_fw_cb->ipv4_gw_addr)));
3532a49a78eSVikas Chaudhary 
3542a49a78eSVikas Chaudhary 	if (is_ipv6_enabled(ha)) {
3552a49a78eSVikas Chaudhary 		/* Save IPv6 Address */
3562a49a78eSVikas Chaudhary 		ha->ipv6_link_local_state = init_fw_cb->ipv6_lnk_lcl_addr_state;
3572a49a78eSVikas Chaudhary 		ha->ipv6_addr0_state = init_fw_cb->ipv6_addr0_state;
3582a49a78eSVikas Chaudhary 		ha->ipv6_addr1_state = init_fw_cb->ipv6_addr1_state;
3592a49a78eSVikas Chaudhary 		ha->ipv6_default_router_state = init_fw_cb->ipv6_dflt_rtr_state;
3602a49a78eSVikas Chaudhary 		ha->ipv6_link_local_addr.in6_u.u6_addr8[0] = 0xFE;
3612a49a78eSVikas Chaudhary 		ha->ipv6_link_local_addr.in6_u.u6_addr8[1] = 0x80;
3622a49a78eSVikas Chaudhary 
3632a49a78eSVikas Chaudhary 		memcpy(&ha->ipv6_link_local_addr.in6_u.u6_addr8[8],
3642a49a78eSVikas Chaudhary 			init_fw_cb->ipv6_if_id,
3652a49a78eSVikas Chaudhary 			min(sizeof(ha->ipv6_link_local_addr)/2,
3662a49a78eSVikas Chaudhary 			sizeof(init_fw_cb->ipv6_if_id)));
3672a49a78eSVikas Chaudhary 		memcpy(&ha->ipv6_addr0, init_fw_cb->ipv6_addr0,
3682a49a78eSVikas Chaudhary 			min(sizeof(ha->ipv6_addr0),
3692a49a78eSVikas Chaudhary 			sizeof(init_fw_cb->ipv6_addr0)));
3702a49a78eSVikas Chaudhary 		memcpy(&ha->ipv6_addr1, init_fw_cb->ipv6_addr1,
3712a49a78eSVikas Chaudhary 			min(sizeof(ha->ipv6_addr1),
3722a49a78eSVikas Chaudhary 			sizeof(init_fw_cb->ipv6_addr1)));
3732a49a78eSVikas Chaudhary 		memcpy(&ha->ipv6_default_router_addr,
3742a49a78eSVikas Chaudhary 			init_fw_cb->ipv6_dflt_rtr_addr,
3752a49a78eSVikas Chaudhary 			min(sizeof(ha->ipv6_default_router_addr),
3762a49a78eSVikas Chaudhary 			sizeof(init_fw_cb->ipv6_dflt_rtr_addr)));
3772a49a78eSVikas Chaudhary 	}
3782a49a78eSVikas Chaudhary }
3792a49a78eSVikas Chaudhary 
380f4f5df23SVikas Chaudhary static uint8_t
3812a49a78eSVikas Chaudhary qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
3822a49a78eSVikas Chaudhary 			  uint32_t *mbox_cmd,
3832a49a78eSVikas Chaudhary 			  uint32_t *mbox_sts,
3842a49a78eSVikas Chaudhary 			  struct addr_ctrl_blk  *init_fw_cb,
3852a49a78eSVikas Chaudhary 			  dma_addr_t init_fw_cb_dma)
3862a49a78eSVikas Chaudhary {
3872a49a78eSVikas Chaudhary 	if (qla4xxx_get_ifcb(ha, mbox_cmd, mbox_sts, init_fw_cb_dma)
3882a49a78eSVikas Chaudhary 	    != QLA_SUCCESS) {
3892a49a78eSVikas Chaudhary 		DEBUG2(printk(KERN_WARNING
3902a49a78eSVikas Chaudhary 			      "scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",
3912a49a78eSVikas Chaudhary 			      ha->host_no, __func__));
3922a49a78eSVikas Chaudhary 		return QLA_ERROR;
3932a49a78eSVikas Chaudhary 	}
3942a49a78eSVikas Chaudhary 
3952a49a78eSVikas Chaudhary 	DEBUG2(qla4xxx_dump_buffer(init_fw_cb, sizeof(struct addr_ctrl_blk)));
3962a49a78eSVikas Chaudhary 
3972a49a78eSVikas Chaudhary 	/* Save some info in adapter structure. */
3982a49a78eSVikas Chaudhary 	ha->acb_version = init_fw_cb->acb_version;
3992a49a78eSVikas Chaudhary 	ha->firmware_options = le16_to_cpu(init_fw_cb->fw_options);
4002a49a78eSVikas Chaudhary 	ha->tcp_options = le16_to_cpu(init_fw_cb->ipv4_tcp_opts);
4012a49a78eSVikas Chaudhary 	ha->ipv4_options = le16_to_cpu(init_fw_cb->ipv4_ip_opts);
4022a49a78eSVikas Chaudhary 	ha->ipv4_addr_state = le16_to_cpu(init_fw_cb->ipv4_addr_state);
4032a49a78eSVikas Chaudhary 	ha->heartbeat_interval = init_fw_cb->hb_interval;
4042a49a78eSVikas Chaudhary 	memcpy(ha->name_string, init_fw_cb->iscsi_name,
4052a49a78eSVikas Chaudhary 		min(sizeof(ha->name_string),
4062a49a78eSVikas Chaudhary 		sizeof(init_fw_cb->iscsi_name)));
4072a49a78eSVikas Chaudhary 	/*memcpy(ha->alias, init_fw_cb->Alias,
4082a49a78eSVikas Chaudhary 	       min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/
4092a49a78eSVikas Chaudhary 
4102a49a78eSVikas Chaudhary 	if (ha->acb_version == ACB_SUPPORTED) {
4112a49a78eSVikas Chaudhary 		ha->ipv6_options = init_fw_cb->ipv6_opts;
4122a49a78eSVikas Chaudhary 		ha->ipv6_addl_options = init_fw_cb->ipv6_addtl_opts;
4132a49a78eSVikas Chaudhary 	}
4142a49a78eSVikas Chaudhary 	qla4xxx_update_local_ip(ha, init_fw_cb);
4152a49a78eSVikas Chaudhary 
4162a49a78eSVikas Chaudhary 	return QLA_SUCCESS;
4172a49a78eSVikas Chaudhary }
4182a49a78eSVikas Chaudhary 
419afaf5a2dSDavid Somayajulu /**
420afaf5a2dSDavid Somayajulu  * qla4xxx_initialize_fw_cb - initializes firmware control block.
421afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
422afaf5a2dSDavid Somayajulu  **/
423afaf5a2dSDavid Somayajulu int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
424afaf5a2dSDavid Somayajulu {
4252a49a78eSVikas Chaudhary 	struct addr_ctrl_blk *init_fw_cb;
426afaf5a2dSDavid Somayajulu 	dma_addr_t init_fw_cb_dma;
427afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
428afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
429afaf5a2dSDavid Somayajulu 	int status = QLA_ERROR;
430afaf5a2dSDavid Somayajulu 
431afaf5a2dSDavid Somayajulu 	init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
4322a49a78eSVikas Chaudhary 					sizeof(struct addr_ctrl_blk),
433afaf5a2dSDavid Somayajulu 					&init_fw_cb_dma, GFP_KERNEL);
434afaf5a2dSDavid Somayajulu 	if (init_fw_cb == NULL) {
435afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n",
436afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__));
437beabe7c1SPrasanna Mumbai 		goto exit_init_fw_cb_no_free;
438afaf5a2dSDavid Somayajulu 	}
4392a49a78eSVikas Chaudhary 	memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
440afaf5a2dSDavid Somayajulu 
441afaf5a2dSDavid Somayajulu 	/* Get Initialize Firmware Control Block. */
442afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
443afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
444c0e344c9SDavid C Somayajulu 
4452a49a78eSVikas Chaudhary 	if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) !=
446afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
447afaf5a2dSDavid Somayajulu 		dma_free_coherent(&ha->pdev->dev,
4482a49a78eSVikas Chaudhary 				  sizeof(struct addr_ctrl_blk),
449afaf5a2dSDavid Somayajulu 				  init_fw_cb, init_fw_cb_dma);
4502a49a78eSVikas Chaudhary 		goto exit_init_fw_cb;
451afaf5a2dSDavid Somayajulu 	}
452afaf5a2dSDavid Somayajulu 
453afaf5a2dSDavid Somayajulu 	/* Initialize request and response queues. */
454afaf5a2dSDavid Somayajulu 	qla4xxx_init_rings(ha);
455afaf5a2dSDavid Somayajulu 
456afaf5a2dSDavid Somayajulu 	/* Fill in the request and response queue information. */
4572a49a78eSVikas Chaudhary 	init_fw_cb->rqq_consumer_idx = cpu_to_le16(ha->request_out);
4582a49a78eSVikas Chaudhary 	init_fw_cb->compq_producer_idx = cpu_to_le16(ha->response_in);
4592a49a78eSVikas Chaudhary 	init_fw_cb->rqq_len = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH);
4602a49a78eSVikas Chaudhary 	init_fw_cb->compq_len = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH);
4612a49a78eSVikas Chaudhary 	init_fw_cb->rqq_addr_lo = cpu_to_le32(LSDW(ha->request_dma));
4622a49a78eSVikas Chaudhary 	init_fw_cb->rqq_addr_hi = cpu_to_le32(MSDW(ha->request_dma));
4632a49a78eSVikas Chaudhary 	init_fw_cb->compq_addr_lo = cpu_to_le32(LSDW(ha->response_dma));
4642a49a78eSVikas Chaudhary 	init_fw_cb->compq_addr_hi = cpu_to_le32(MSDW(ha->response_dma));
4652a49a78eSVikas Chaudhary 	init_fw_cb->shdwreg_addr_lo = cpu_to_le32(LSDW(ha->shadow_regs_dma));
4662a49a78eSVikas Chaudhary 	init_fw_cb->shdwreg_addr_hi = cpu_to_le32(MSDW(ha->shadow_regs_dma));
467afaf5a2dSDavid Somayajulu 
468afaf5a2dSDavid Somayajulu 	/* Set up required options. */
4692a49a78eSVikas Chaudhary 	init_fw_cb->fw_options |=
470afaf5a2dSDavid Somayajulu 		__constant_cpu_to_le16(FWOPT_SESSION_MODE |
471afaf5a2dSDavid Somayajulu 				       FWOPT_INITIATOR_MODE);
4722657c800SShyam Sundar 
4732657c800SShyam Sundar 	if (is_qla8022(ha))
4742657c800SShyam Sundar 		init_fw_cb->fw_options |=
4752657c800SShyam Sundar 		    __constant_cpu_to_le16(FWOPT_ENABLE_CRBDB);
4762657c800SShyam Sundar 
4772a49a78eSVikas Chaudhary 	init_fw_cb->fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
478afaf5a2dSDavid Somayajulu 
4792a49a78eSVikas Chaudhary 	if (qla4xxx_set_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)
4802a49a78eSVikas Chaudhary 		!= QLA_SUCCESS) {
4812a49a78eSVikas Chaudhary 		DEBUG2(printk(KERN_WARNING
4822a49a78eSVikas Chaudhary 			      "scsi%ld: %s: Failed to set init_fw_ctrl_blk\n",
4832a49a78eSVikas Chaudhary 			      ha->host_no, __func__));
4842a49a78eSVikas Chaudhary 		goto exit_init_fw_cb;
485afaf5a2dSDavid Somayajulu 	}
4862a49a78eSVikas Chaudhary 
4872a49a78eSVikas Chaudhary 	if (qla4xxx_update_local_ifcb(ha, &mbox_cmd[0], &mbox_sts[0],
4882a49a78eSVikas Chaudhary 		init_fw_cb, init_fw_cb_dma) != QLA_SUCCESS) {
4892a49a78eSVikas Chaudhary 		DEBUG2(printk("scsi%ld: %s: Failed to update local ifcb\n",
4902a49a78eSVikas Chaudhary 				ha->host_no, __func__));
4912a49a78eSVikas Chaudhary 		goto exit_init_fw_cb;
4922a49a78eSVikas Chaudhary 	}
4932a49a78eSVikas Chaudhary 	status = QLA_SUCCESS;
4942a49a78eSVikas Chaudhary 
4952a49a78eSVikas Chaudhary exit_init_fw_cb:
4962a49a78eSVikas Chaudhary 	dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
497afaf5a2dSDavid Somayajulu 				init_fw_cb, init_fw_cb_dma);
498beabe7c1SPrasanna Mumbai exit_init_fw_cb_no_free:
499afaf5a2dSDavid Somayajulu 	return status;
500afaf5a2dSDavid Somayajulu }
501afaf5a2dSDavid Somayajulu 
502afaf5a2dSDavid Somayajulu /**
503afaf5a2dSDavid Somayajulu  * qla4xxx_get_dhcp_ip_address - gets HBA ip address via DHCP
504afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
505afaf5a2dSDavid Somayajulu  **/
506afaf5a2dSDavid Somayajulu int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha)
507afaf5a2dSDavid Somayajulu {
5082a49a78eSVikas Chaudhary 	struct addr_ctrl_blk *init_fw_cb;
509afaf5a2dSDavid Somayajulu 	dma_addr_t init_fw_cb_dma;
510afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
511afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
512afaf5a2dSDavid Somayajulu 
513afaf5a2dSDavid Somayajulu 	init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
5142a49a78eSVikas Chaudhary 					sizeof(struct addr_ctrl_blk),
515afaf5a2dSDavid Somayajulu 					&init_fw_cb_dma, GFP_KERNEL);
516afaf5a2dSDavid Somayajulu 	if (init_fw_cb == NULL) {
517afaf5a2dSDavid Somayajulu 		printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no,
518afaf5a2dSDavid Somayajulu 		       __func__);
519beabe7c1SPrasanna Mumbai 		return QLA_ERROR;
520afaf5a2dSDavid Somayajulu 	}
521afaf5a2dSDavid Somayajulu 
522afaf5a2dSDavid Somayajulu 	/* Get Initialize Firmware Control Block. */
5232a49a78eSVikas Chaudhary 	memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
5242a49a78eSVikas Chaudhary 	if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) !=
525afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
526afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",
527afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__));
528afaf5a2dSDavid Somayajulu 		dma_free_coherent(&ha->pdev->dev,
5292a49a78eSVikas Chaudhary 				  sizeof(struct addr_ctrl_blk),
530afaf5a2dSDavid Somayajulu 				  init_fw_cb, init_fw_cb_dma);
531afaf5a2dSDavid Somayajulu 		return QLA_ERROR;
532afaf5a2dSDavid Somayajulu 	}
533afaf5a2dSDavid Somayajulu 
534afaf5a2dSDavid Somayajulu 	/* Save IP Address. */
5352a49a78eSVikas Chaudhary 	qla4xxx_update_local_ip(ha, init_fw_cb);
5362a49a78eSVikas Chaudhary 	dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
537afaf5a2dSDavid Somayajulu 				init_fw_cb, init_fw_cb_dma);
538afaf5a2dSDavid Somayajulu 
539afaf5a2dSDavid Somayajulu 	return QLA_SUCCESS;
540afaf5a2dSDavid Somayajulu }
541afaf5a2dSDavid Somayajulu 
542afaf5a2dSDavid Somayajulu /**
543afaf5a2dSDavid Somayajulu  * qla4xxx_get_firmware_state - gets firmware state of HBA
544afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
545afaf5a2dSDavid Somayajulu  **/
546afaf5a2dSDavid Somayajulu int qla4xxx_get_firmware_state(struct scsi_qla_host * ha)
547afaf5a2dSDavid Somayajulu {
548afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
549afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
550afaf5a2dSDavid Somayajulu 
551afaf5a2dSDavid Somayajulu 	/* Get firmware version */
552afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
553afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
554c0e344c9SDavid C Somayajulu 
555afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_FW_STATE;
556c0e344c9SDavid C Somayajulu 
557c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 4, &mbox_cmd[0], &mbox_sts[0]) !=
558afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
559afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ "
560afaf5a2dSDavid Somayajulu 			      "status %04X\n", ha->host_no, __func__,
561afaf5a2dSDavid Somayajulu 			      mbox_sts[0]));
562afaf5a2dSDavid Somayajulu 		return QLA_ERROR;
563afaf5a2dSDavid Somayajulu 	}
564afaf5a2dSDavid Somayajulu 	ha->firmware_state = mbox_sts[1];
565afaf5a2dSDavid Somayajulu 	ha->board_id = mbox_sts[2];
566afaf5a2dSDavid Somayajulu 	ha->addl_fw_state = mbox_sts[3];
567afaf5a2dSDavid Somayajulu 	DEBUG2(printk("scsi%ld: %s firmware_state=0x%x\n",
568afaf5a2dSDavid Somayajulu 		      ha->host_no, __func__, ha->firmware_state);)
569afaf5a2dSDavid Somayajulu 
570afaf5a2dSDavid Somayajulu 	return QLA_SUCCESS;
571afaf5a2dSDavid Somayajulu }
572afaf5a2dSDavid Somayajulu 
573afaf5a2dSDavid Somayajulu /**
574afaf5a2dSDavid Somayajulu  * qla4xxx_get_firmware_status - retrieves firmware status
575afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
576afaf5a2dSDavid Somayajulu  **/
577afaf5a2dSDavid Somayajulu int qla4xxx_get_firmware_status(struct scsi_qla_host * ha)
578afaf5a2dSDavid Somayajulu {
579afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
580afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
581afaf5a2dSDavid Somayajulu 
582afaf5a2dSDavid Somayajulu 	/* Get firmware version */
583afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
584afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
585c0e344c9SDavid C Somayajulu 
586afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS;
587c0e344c9SDavid C Somayajulu 
588c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) !=
589afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
590afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ "
591afaf5a2dSDavid Somayajulu 			      "status %04X\n", ha->host_no, __func__,
592afaf5a2dSDavid Somayajulu 			      mbox_sts[0]));
593afaf5a2dSDavid Somayajulu 		return QLA_ERROR;
594afaf5a2dSDavid Somayajulu 	}
595f4f5df23SVikas Chaudhary 
596f4f5df23SVikas Chaudhary 	ql4_printk(KERN_INFO, ha, "%ld firmare IOCBs available (%d).\n",
597f581a3f7SVikas Chaudhary 	    ha->host_no, mbox_sts[2]);
598f4f5df23SVikas Chaudhary 
599afaf5a2dSDavid Somayajulu 	return QLA_SUCCESS;
600afaf5a2dSDavid Somayajulu }
601afaf5a2dSDavid Somayajulu 
602afaf5a2dSDavid Somayajulu /**
603afaf5a2dSDavid Somayajulu  * qla4xxx_get_fwddb_entry - retrieves firmware ddb entry
604afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
605afaf5a2dSDavid Somayajulu  * @fw_ddb_index: Firmware's device database index
606afaf5a2dSDavid Somayajulu  * @fw_ddb_entry: Pointer to firmware's device database entry structure
607afaf5a2dSDavid Somayajulu  * @num_valid_ddb_entries: Pointer to number of valid ddb entries
608afaf5a2dSDavid Somayajulu  * @next_ddb_index: Pointer to next valid device database index
609afaf5a2dSDavid Somayajulu  * @fw_ddb_device_state: Pointer to device state
610afaf5a2dSDavid Somayajulu  **/
611afaf5a2dSDavid Somayajulu int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
612afaf5a2dSDavid Somayajulu 			    uint16_t fw_ddb_index,
613afaf5a2dSDavid Somayajulu 			    struct dev_db_entry *fw_ddb_entry,
614afaf5a2dSDavid Somayajulu 			    dma_addr_t fw_ddb_entry_dma,
615afaf5a2dSDavid Somayajulu 			    uint32_t *num_valid_ddb_entries,
616afaf5a2dSDavid Somayajulu 			    uint32_t *next_ddb_index,
617afaf5a2dSDavid Somayajulu 			    uint32_t *fw_ddb_device_state,
618afaf5a2dSDavid Somayajulu 			    uint32_t *conn_err_detail,
619afaf5a2dSDavid Somayajulu 			    uint16_t *tcp_source_port_num,
620afaf5a2dSDavid Somayajulu 			    uint16_t *connection_id)
621afaf5a2dSDavid Somayajulu {
622afaf5a2dSDavid Somayajulu 	int status = QLA_ERROR;
6232a49a78eSVikas Chaudhary 	uint16_t options;
624afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
625afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
626afaf5a2dSDavid Somayajulu 
627afaf5a2dSDavid Somayajulu 	/* Make sure the device index is valid */
628afaf5a2dSDavid Somayajulu 	if (fw_ddb_index >= MAX_DDB_ENTRIES) {
629f4f5df23SVikas Chaudhary 		DEBUG2(printk("scsi%ld: %s: ddb [%d] out of range.\n",
630afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__, fw_ddb_index));
631afaf5a2dSDavid Somayajulu 		goto exit_get_fwddb;
632afaf5a2dSDavid Somayajulu 	}
633afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
634afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
635c0e344c9SDavid C Somayajulu 
636afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY;
637afaf5a2dSDavid Somayajulu 	mbox_cmd[1] = (uint32_t) fw_ddb_index;
638afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
639afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
640c0e344c9SDavid C Somayajulu 	mbox_cmd[4] = sizeof(struct dev_db_entry);
641c0e344c9SDavid C Somayajulu 
642c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 7, &mbox_cmd[0], &mbox_sts[0]) ==
643afaf5a2dSDavid Somayajulu 	    QLA_ERROR) {
644afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed"
645afaf5a2dSDavid Somayajulu 			      " with status 0x%04X\n", ha->host_no, __func__,
646afaf5a2dSDavid Somayajulu 			      mbox_sts[0]));
647afaf5a2dSDavid Somayajulu 		goto exit_get_fwddb;
648afaf5a2dSDavid Somayajulu 	}
649afaf5a2dSDavid Somayajulu 	if (fw_ddb_index != mbox_sts[1]) {
650f4f5df23SVikas Chaudhary 		DEBUG2(printk("scsi%ld: %s: ddb mismatch [%d] != [%d].\n",
651afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__, fw_ddb_index,
652afaf5a2dSDavid Somayajulu 			      mbox_sts[1]));
653afaf5a2dSDavid Somayajulu 		goto exit_get_fwddb;
654afaf5a2dSDavid Somayajulu 	}
655afaf5a2dSDavid Somayajulu 	if (fw_ddb_entry) {
6562a49a78eSVikas Chaudhary 		options = le16_to_cpu(fw_ddb_entry->options);
6572a49a78eSVikas Chaudhary 		if (options & DDB_OPT_IPV6_DEVICE) {
658c2660df3SVikas Chaudhary 			ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d "
6592a49a78eSVikas Chaudhary 				"Next %d State %04x ConnErr %08x %pI6 "
6602a49a78eSVikas Chaudhary 				":%04d \"%s\"\n", __func__, fw_ddb_index,
6612a49a78eSVikas Chaudhary 				mbox_sts[0], mbox_sts[2], mbox_sts[3],
6622a49a78eSVikas Chaudhary 				mbox_sts[4], mbox_sts[5],
6632a49a78eSVikas Chaudhary 				fw_ddb_entry->ip_addr,
664c0e344c9SDavid C Somayajulu 				le16_to_cpu(fw_ddb_entry->port),
665c0e344c9SDavid C Somayajulu 				fw_ddb_entry->iscsi_name);
6662a49a78eSVikas Chaudhary 		} else {
667c2660df3SVikas Chaudhary 			ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d "
6682a49a78eSVikas Chaudhary 				"Next %d State %04x ConnErr %08x %pI4 "
6692a49a78eSVikas Chaudhary 				":%04d \"%s\"\n", __func__, fw_ddb_index,
6702a49a78eSVikas Chaudhary 				mbox_sts[0], mbox_sts[2], mbox_sts[3],
6712a49a78eSVikas Chaudhary 				mbox_sts[4], mbox_sts[5],
6722a49a78eSVikas Chaudhary 				fw_ddb_entry->ip_addr,
6732a49a78eSVikas Chaudhary 				le16_to_cpu(fw_ddb_entry->port),
6742a49a78eSVikas Chaudhary 				fw_ddb_entry->iscsi_name);
6752a49a78eSVikas Chaudhary 		}
676afaf5a2dSDavid Somayajulu 	}
677afaf5a2dSDavid Somayajulu 	if (num_valid_ddb_entries)
678afaf5a2dSDavid Somayajulu 		*num_valid_ddb_entries = mbox_sts[2];
679afaf5a2dSDavid Somayajulu 	if (next_ddb_index)
680afaf5a2dSDavid Somayajulu 		*next_ddb_index = mbox_sts[3];
681afaf5a2dSDavid Somayajulu 	if (fw_ddb_device_state)
682afaf5a2dSDavid Somayajulu 		*fw_ddb_device_state = mbox_sts[4];
683afaf5a2dSDavid Somayajulu 
684afaf5a2dSDavid Somayajulu 	/*
685afaf5a2dSDavid Somayajulu 	 * RA: This mailbox has been changed to pass connection error and
686afaf5a2dSDavid Somayajulu 	 * details.  Its true for ISP4010 as per Version E - Not sure when it
687afaf5a2dSDavid Somayajulu 	 * was changed.	 Get the time2wait from the fw_dd_entry field :
688afaf5a2dSDavid Somayajulu 	 * default_time2wait which we call it as minTime2Wait DEV_DB_ENTRY
689afaf5a2dSDavid Somayajulu 	 * struct.
690afaf5a2dSDavid Somayajulu 	 */
691afaf5a2dSDavid Somayajulu 	if (conn_err_detail)
692afaf5a2dSDavid Somayajulu 		*conn_err_detail = mbox_sts[5];
693afaf5a2dSDavid Somayajulu 	if (tcp_source_port_num)
6941482338fSRandy Dunlap 		*tcp_source_port_num = (uint16_t) (mbox_sts[6] >> 16);
695afaf5a2dSDavid Somayajulu 	if (connection_id)
696afaf5a2dSDavid Somayajulu 		*connection_id = (uint16_t) mbox_sts[6] & 0x00FF;
697afaf5a2dSDavid Somayajulu 	status = QLA_SUCCESS;
698afaf5a2dSDavid Somayajulu 
699afaf5a2dSDavid Somayajulu exit_get_fwddb:
700afaf5a2dSDavid Somayajulu 	return status;
701afaf5a2dSDavid Somayajulu }
702afaf5a2dSDavid Somayajulu 
703afaf5a2dSDavid Somayajulu /**
704afaf5a2dSDavid Somayajulu  * qla4xxx_set_fwddb_entry - sets a ddb entry.
705afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
706afaf5a2dSDavid Somayajulu  * @fw_ddb_index: Firmware's device database index
707afaf5a2dSDavid Somayajulu  * @fw_ddb_entry: Pointer to firmware's ddb entry structure, or NULL.
708afaf5a2dSDavid Somayajulu  *
709afaf5a2dSDavid Somayajulu  * This routine initializes or updates the adapter's device database
710afaf5a2dSDavid Somayajulu  * entry for the specified device. It also triggers a login for the
711afaf5a2dSDavid Somayajulu  * specified device. Therefore, it may also be used as a secondary
712afaf5a2dSDavid Somayajulu  * login routine when a NULL pointer is specified for the fw_ddb_entry.
713afaf5a2dSDavid Somayajulu  **/
714afaf5a2dSDavid Somayajulu int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
715afaf5a2dSDavid Somayajulu 			  dma_addr_t fw_ddb_entry_dma)
716afaf5a2dSDavid Somayajulu {
717afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
718afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
719f4f5df23SVikas Chaudhary 	int status;
720afaf5a2dSDavid Somayajulu 
721afaf5a2dSDavid Somayajulu 	/* Do not wait for completion. The firmware will send us an
722afaf5a2dSDavid Somayajulu 	 * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status.
723afaf5a2dSDavid Somayajulu 	 */
724afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
725afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
726afaf5a2dSDavid Somayajulu 
727afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_SET_DATABASE_ENTRY;
728afaf5a2dSDavid Somayajulu 	mbox_cmd[1] = (uint32_t) fw_ddb_index;
729afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
730afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
731c0e344c9SDavid C Somayajulu 	mbox_cmd[4] = sizeof(struct dev_db_entry);
732c0e344c9SDavid C Somayajulu 
733f4f5df23SVikas Chaudhary 	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0],
734f4f5df23SVikas Chaudhary 	    &mbox_sts[0]);
735f4f5df23SVikas Chaudhary 	DEBUG2(printk("scsi%ld: %s: status=%d mbx0=0x%x mbx4=0x%x\n",
736f4f5df23SVikas Chaudhary 	    ha->host_no, __func__, status, mbox_sts[0], mbox_sts[4]);)
737f4f5df23SVikas Chaudhary 
738f4f5df23SVikas Chaudhary 	return status;
739afaf5a2dSDavid Somayajulu }
740afaf5a2dSDavid Somayajulu 
741afaf5a2dSDavid Somayajulu /**
742afaf5a2dSDavid Somayajulu  * qla4xxx_get_crash_record - retrieves crash record.
743afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
744afaf5a2dSDavid Somayajulu  *
745afaf5a2dSDavid Somayajulu  * This routine retrieves a crash record from the QLA4010 after an 8002h aen.
746afaf5a2dSDavid Somayajulu  **/
747afaf5a2dSDavid Somayajulu void qla4xxx_get_crash_record(struct scsi_qla_host * ha)
748afaf5a2dSDavid Somayajulu {
749afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
750afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
751afaf5a2dSDavid Somayajulu 	struct crash_record *crash_record = NULL;
752afaf5a2dSDavid Somayajulu 	dma_addr_t crash_record_dma = 0;
753afaf5a2dSDavid Somayajulu 	uint32_t crash_record_size = 0;
754c0e344c9SDavid C Somayajulu 
755afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
756afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_cmd));
757afaf5a2dSDavid Somayajulu 
758afaf5a2dSDavid Somayajulu 	/* Get size of crash record. */
759afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
760c0e344c9SDavid C Somayajulu 
761c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
762afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
763afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n",
764afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__));
765afaf5a2dSDavid Somayajulu 		goto exit_get_crash_record;
766afaf5a2dSDavid Somayajulu 	}
767afaf5a2dSDavid Somayajulu 	crash_record_size = mbox_sts[4];
768afaf5a2dSDavid Somayajulu 	if (crash_record_size == 0) {
769afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: ERROR: Crash record size is 0!\n",
770afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__));
771afaf5a2dSDavid Somayajulu 		goto exit_get_crash_record;
772afaf5a2dSDavid Somayajulu 	}
773afaf5a2dSDavid Somayajulu 
774afaf5a2dSDavid Somayajulu 	/* Alloc Memory for Crash Record. */
775afaf5a2dSDavid Somayajulu 	crash_record = dma_alloc_coherent(&ha->pdev->dev, crash_record_size,
776afaf5a2dSDavid Somayajulu 					  &crash_record_dma, GFP_KERNEL);
777afaf5a2dSDavid Somayajulu 	if (crash_record == NULL)
778afaf5a2dSDavid Somayajulu 		goto exit_get_crash_record;
779afaf5a2dSDavid Somayajulu 
780afaf5a2dSDavid Somayajulu 	/* Get Crash Record. */
781c0e344c9SDavid C Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
782c0e344c9SDavid C Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_cmd));
783c0e344c9SDavid C Somayajulu 
784afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
785afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = LSDW(crash_record_dma);
786afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = MSDW(crash_record_dma);
787afaf5a2dSDavid Somayajulu 	mbox_cmd[4] = crash_record_size;
788c0e344c9SDavid C Somayajulu 
789c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
790afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS)
791afaf5a2dSDavid Somayajulu 		goto exit_get_crash_record;
792afaf5a2dSDavid Somayajulu 
793afaf5a2dSDavid Somayajulu 	/* Dump Crash Record. */
794afaf5a2dSDavid Somayajulu 
795afaf5a2dSDavid Somayajulu exit_get_crash_record:
796afaf5a2dSDavid Somayajulu 	if (crash_record)
797afaf5a2dSDavid Somayajulu 		dma_free_coherent(&ha->pdev->dev, crash_record_size,
798afaf5a2dSDavid Somayajulu 				  crash_record, crash_record_dma);
799afaf5a2dSDavid Somayajulu }
800afaf5a2dSDavid Somayajulu 
801afaf5a2dSDavid Somayajulu /**
802afaf5a2dSDavid Somayajulu  * qla4xxx_get_conn_event_log - retrieves connection event log
803afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
804afaf5a2dSDavid Somayajulu  **/
805afaf5a2dSDavid Somayajulu void qla4xxx_get_conn_event_log(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 conn_event_log_entry *event_log = NULL;
810afaf5a2dSDavid Somayajulu 	dma_addr_t event_log_dma = 0;
811afaf5a2dSDavid Somayajulu 	uint32_t event_log_size = 0;
812afaf5a2dSDavid Somayajulu 	uint32_t num_valid_entries;
813afaf5a2dSDavid Somayajulu 	uint32_t      oldest_entry = 0;
814afaf5a2dSDavid Somayajulu 	uint32_t	max_event_log_entries;
815afaf5a2dSDavid Somayajulu 	uint8_t		i;
816afaf5a2dSDavid Somayajulu 
817afaf5a2dSDavid Somayajulu 
818afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
819afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_cmd));
820afaf5a2dSDavid Somayajulu 
821afaf5a2dSDavid Somayajulu 	/* Get size of crash record. */
822afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
823c0e344c9SDavid C Somayajulu 
824c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
825afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS)
826afaf5a2dSDavid Somayajulu 		goto exit_get_event_log;
827afaf5a2dSDavid Somayajulu 
828afaf5a2dSDavid Somayajulu 	event_log_size = mbox_sts[4];
829afaf5a2dSDavid Somayajulu 	if (event_log_size == 0)
830afaf5a2dSDavid Somayajulu 		goto exit_get_event_log;
831afaf5a2dSDavid Somayajulu 
832afaf5a2dSDavid Somayajulu 	/* Alloc Memory for Crash Record. */
833afaf5a2dSDavid Somayajulu 	event_log = dma_alloc_coherent(&ha->pdev->dev, event_log_size,
834afaf5a2dSDavid Somayajulu 				       &event_log_dma, GFP_KERNEL);
835afaf5a2dSDavid Somayajulu 	if (event_log == NULL)
836afaf5a2dSDavid Somayajulu 		goto exit_get_event_log;
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_CONN_EVENT_LOG;
843afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = LSDW(event_log_dma);
844afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = MSDW(event_log_dma);
845c0e344c9SDavid C Somayajulu 
846c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
847afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
848afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event "
849afaf5a2dSDavid Somayajulu 			      "log!\n", ha->host_no, __func__));
850afaf5a2dSDavid Somayajulu 		goto exit_get_event_log;
851afaf5a2dSDavid Somayajulu 	}
852afaf5a2dSDavid Somayajulu 
853afaf5a2dSDavid Somayajulu 	/* Dump Event Log. */
854afaf5a2dSDavid Somayajulu 	num_valid_entries = mbox_sts[1];
855afaf5a2dSDavid Somayajulu 
856afaf5a2dSDavid Somayajulu 	max_event_log_entries = event_log_size /
857afaf5a2dSDavid Somayajulu 		sizeof(struct conn_event_log_entry);
858afaf5a2dSDavid Somayajulu 
859afaf5a2dSDavid Somayajulu 	if (num_valid_entries > max_event_log_entries)
860afaf5a2dSDavid Somayajulu 		oldest_entry = num_valid_entries % max_event_log_entries;
861afaf5a2dSDavid Somayajulu 
862afaf5a2dSDavid Somayajulu 	DEBUG3(printk("scsi%ld: Connection Event Log Dump (%d entries):\n",
863afaf5a2dSDavid Somayajulu 		      ha->host_no, num_valid_entries));
864afaf5a2dSDavid Somayajulu 
86511010fecSAndrew Vasquez 	if (ql4xextended_error_logging == 3) {
866afaf5a2dSDavid Somayajulu 		if (oldest_entry == 0) {
867afaf5a2dSDavid Somayajulu 			/* Circular Buffer has not wrapped around */
868afaf5a2dSDavid Somayajulu 			for (i=0; i < num_valid_entries; i++) {
869afaf5a2dSDavid Somayajulu 				qla4xxx_dump_buffer((uint8_t *)event_log+
870afaf5a2dSDavid Somayajulu 						    (i*sizeof(*event_log)),
871afaf5a2dSDavid Somayajulu 						    sizeof(*event_log));
872afaf5a2dSDavid Somayajulu 			}
873afaf5a2dSDavid Somayajulu 		}
874afaf5a2dSDavid Somayajulu 		else {
875afaf5a2dSDavid Somayajulu 			/* Circular Buffer has wrapped around -
876afaf5a2dSDavid Somayajulu 			 * display accordingly*/
877afaf5a2dSDavid Somayajulu 			for (i=oldest_entry; i < max_event_log_entries; i++) {
878afaf5a2dSDavid Somayajulu 				qla4xxx_dump_buffer((uint8_t *)event_log+
879afaf5a2dSDavid Somayajulu 						    (i*sizeof(*event_log)),
880afaf5a2dSDavid Somayajulu 						    sizeof(*event_log));
881afaf5a2dSDavid Somayajulu 			}
882afaf5a2dSDavid Somayajulu 			for (i=0; i < oldest_entry; i++) {
883afaf5a2dSDavid Somayajulu 				qla4xxx_dump_buffer((uint8_t *)event_log+
884afaf5a2dSDavid Somayajulu 						    (i*sizeof(*event_log)),
885afaf5a2dSDavid Somayajulu 						    sizeof(*event_log));
886afaf5a2dSDavid Somayajulu 			}
887afaf5a2dSDavid Somayajulu 		}
888afaf5a2dSDavid Somayajulu 	}
889afaf5a2dSDavid Somayajulu 
890afaf5a2dSDavid Somayajulu exit_get_event_log:
891afaf5a2dSDavid Somayajulu 	if (event_log)
892afaf5a2dSDavid Somayajulu 		dma_free_coherent(&ha->pdev->dev, event_log_size, event_log,
893afaf5a2dSDavid Somayajulu 				  event_log_dma);
894afaf5a2dSDavid Somayajulu }
895afaf5a2dSDavid Somayajulu 
896afaf5a2dSDavid Somayajulu /**
89709a0f719SVikas Chaudhary  * qla4xxx_abort_task - issues Abort Task
89809a0f719SVikas Chaudhary  * @ha: Pointer to host adapter structure.
89909a0f719SVikas Chaudhary  * @srb: Pointer to srb entry
90009a0f719SVikas Chaudhary  *
90109a0f719SVikas Chaudhary  * This routine performs a LUN RESET on the specified target/lun.
90209a0f719SVikas Chaudhary  * The caller must ensure that the ddb_entry and lun_entry pointers
90309a0f719SVikas Chaudhary  * are valid before calling this routine.
90409a0f719SVikas Chaudhary  **/
90509a0f719SVikas Chaudhary int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb)
90609a0f719SVikas Chaudhary {
90709a0f719SVikas Chaudhary 	uint32_t mbox_cmd[MBOX_REG_COUNT];
90809a0f719SVikas Chaudhary 	uint32_t mbox_sts[MBOX_REG_COUNT];
90909a0f719SVikas Chaudhary 	struct scsi_cmnd *cmd = srb->cmd;
91009a0f719SVikas Chaudhary 	int status = QLA_SUCCESS;
91109a0f719SVikas Chaudhary 	unsigned long flags = 0;
91209a0f719SVikas Chaudhary 	uint32_t index;
91309a0f719SVikas Chaudhary 
91409a0f719SVikas Chaudhary 	/*
91509a0f719SVikas Chaudhary 	 * Send abort task command to ISP, so that the ISP will return
91609a0f719SVikas Chaudhary 	 * request with ABORT status
91709a0f719SVikas Chaudhary 	 */
91809a0f719SVikas Chaudhary 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
91909a0f719SVikas Chaudhary 	memset(&mbox_sts, 0, sizeof(mbox_sts));
92009a0f719SVikas Chaudhary 
92109a0f719SVikas Chaudhary 	spin_lock_irqsave(&ha->hardware_lock, flags);
92209a0f719SVikas Chaudhary 	index = (unsigned long)(unsigned char *)cmd->host_scribble;
92309a0f719SVikas Chaudhary 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
92409a0f719SVikas Chaudhary 
92509a0f719SVikas Chaudhary 	/* Firmware already posted completion on response queue */
92609a0f719SVikas Chaudhary 	if (index == MAX_SRBS)
92709a0f719SVikas Chaudhary 		return status;
92809a0f719SVikas Chaudhary 
92909a0f719SVikas Chaudhary 	mbox_cmd[0] = MBOX_CMD_ABORT_TASK;
9306790d4feSKaren Higgins 	mbox_cmd[1] = srb->ddb->fw_ddb_index;
93109a0f719SVikas Chaudhary 	mbox_cmd[2] = index;
93209a0f719SVikas Chaudhary 	/* Immediate Command Enable */
93309a0f719SVikas Chaudhary 	mbox_cmd[5] = 0x01;
93409a0f719SVikas Chaudhary 
93509a0f719SVikas Chaudhary 	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0],
93609a0f719SVikas Chaudhary 	    &mbox_sts[0]);
93709a0f719SVikas Chaudhary 	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE) {
93809a0f719SVikas Chaudhary 		status = QLA_ERROR;
93909a0f719SVikas Chaudhary 
94009a0f719SVikas Chaudhary 		DEBUG2(printk(KERN_WARNING "scsi%ld:%d:%d: abort task FAILED: "
94109a0f719SVikas Chaudhary 		    "mbx0=%04X, mb1=%04X, mb2=%04X, mb3=%04X, mb4=%04X\n",
94209a0f719SVikas Chaudhary 		    ha->host_no, cmd->device->id, cmd->device->lun, mbox_sts[0],
94309a0f719SVikas Chaudhary 		    mbox_sts[1], mbox_sts[2], mbox_sts[3], mbox_sts[4]));
94409a0f719SVikas Chaudhary 	}
94509a0f719SVikas Chaudhary 
94609a0f719SVikas Chaudhary 	return status;
94709a0f719SVikas Chaudhary }
94809a0f719SVikas Chaudhary 
94909a0f719SVikas Chaudhary /**
950afaf5a2dSDavid Somayajulu  * qla4xxx_reset_lun - issues LUN Reset
951afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
952f4f5df23SVikas Chaudhary  * @ddb_entry: Pointer to device database entry
953f4f5df23SVikas Chaudhary  * @lun: lun number
954afaf5a2dSDavid Somayajulu  *
955afaf5a2dSDavid Somayajulu  * This routine performs a LUN RESET on the specified target/lun.
956afaf5a2dSDavid Somayajulu  * The caller must ensure that the ddb_entry and lun_entry pointers
957afaf5a2dSDavid Somayajulu  * are valid before calling this routine.
958afaf5a2dSDavid Somayajulu  **/
959afaf5a2dSDavid Somayajulu int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
960afaf5a2dSDavid Somayajulu 		      int lun)
961afaf5a2dSDavid Somayajulu {
962afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
963afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
964afaf5a2dSDavid Somayajulu 	int status = QLA_SUCCESS;
965afaf5a2dSDavid Somayajulu 
966afaf5a2dSDavid Somayajulu 	DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no,
967f4f5df23SVikas Chaudhary 		      ddb_entry->fw_ddb_index, lun));
968afaf5a2dSDavid Somayajulu 
969afaf5a2dSDavid Somayajulu 	/*
970afaf5a2dSDavid Somayajulu 	 * Send lun reset command to ISP, so that the ISP will return all
971afaf5a2dSDavid Somayajulu 	 * outstanding requests with RESET status
972afaf5a2dSDavid Somayajulu 	 */
973afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
974afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
975c0e344c9SDavid C Somayajulu 
976afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_LUN_RESET;
977afaf5a2dSDavid Somayajulu 	mbox_cmd[1] = ddb_entry->fw_ddb_index;
978afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = lun << 8;
979afaf5a2dSDavid Somayajulu 	mbox_cmd[5] = 0x01;	/* Immediate Command Enable */
980c0e344c9SDavid C Somayajulu 
981c0e344c9SDavid C Somayajulu 	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]);
982afaf5a2dSDavid Somayajulu 	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
983afaf5a2dSDavid Somayajulu 	    mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
984afaf5a2dSDavid Somayajulu 		status = QLA_ERROR;
985afaf5a2dSDavid Somayajulu 
986afaf5a2dSDavid Somayajulu 	return status;
987afaf5a2dSDavid Somayajulu }
988afaf5a2dSDavid Somayajulu 
989ce545039SMike Christie /**
990ce545039SMike Christie  * qla4xxx_reset_target - issues target Reset
991ce545039SMike Christie  * @ha: Pointer to host adapter structure.
992ce545039SMike Christie  * @db_entry: Pointer to device database entry
993ce545039SMike Christie  * @un_entry: Pointer to lun entry structure
994ce545039SMike Christie  *
995ce545039SMike Christie  * This routine performs a TARGET RESET on the specified target.
996ce545039SMike Christie  * The caller must ensure that the ddb_entry pointers
997ce545039SMike Christie  * are valid before calling this routine.
998ce545039SMike Christie  **/
999ce545039SMike Christie int qla4xxx_reset_target(struct scsi_qla_host *ha,
1000ce545039SMike Christie 			 struct ddb_entry *ddb_entry)
1001ce545039SMike Christie {
1002ce545039SMike Christie 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1003ce545039SMike Christie 	uint32_t mbox_sts[MBOX_REG_COUNT];
1004ce545039SMike Christie 	int status = QLA_SUCCESS;
1005ce545039SMike Christie 
1006ce545039SMike Christie 	DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no,
1007f4f5df23SVikas Chaudhary 		      ddb_entry->fw_ddb_index));
1008ce545039SMike Christie 
1009ce545039SMike Christie 	/*
1010ce545039SMike Christie 	 * Send target reset command to ISP, so that the ISP will return all
1011ce545039SMike Christie 	 * outstanding requests with RESET status
1012ce545039SMike Christie 	 */
1013ce545039SMike Christie 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1014ce545039SMike Christie 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1015ce545039SMike Christie 
1016ce545039SMike Christie 	mbox_cmd[0] = MBOX_CMD_TARGET_WARM_RESET;
1017ce545039SMike Christie 	mbox_cmd[1] = ddb_entry->fw_ddb_index;
1018ce545039SMike Christie 	mbox_cmd[5] = 0x01;	/* Immediate Command Enable */
1019ce545039SMike Christie 
1020ce545039SMike Christie 	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
1021ce545039SMike Christie 				&mbox_sts[0]);
1022ce545039SMike Christie 	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
1023ce545039SMike Christie 	    mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
1024ce545039SMike Christie 		status = QLA_ERROR;
1025ce545039SMike Christie 
1026ce545039SMike Christie 	return status;
1027ce545039SMike Christie }
1028afaf5a2dSDavid Somayajulu 
1029afaf5a2dSDavid Somayajulu int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
1030afaf5a2dSDavid Somayajulu 		      uint32_t offset, uint32_t len)
1031afaf5a2dSDavid Somayajulu {
1032afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1033afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
1034afaf5a2dSDavid Somayajulu 
1035afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1036afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1037c0e344c9SDavid C Somayajulu 
1038afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_READ_FLASH;
1039afaf5a2dSDavid Somayajulu 	mbox_cmd[1] = LSDW(dma_addr);
1040afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = MSDW(dma_addr);
1041afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = offset;
1042afaf5a2dSDavid Somayajulu 	mbox_cmd[4] = len;
1043c0e344c9SDavid C Somayajulu 
1044c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], &mbox_sts[0]) !=
1045afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
1046afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ "
1047afaf5a2dSDavid Somayajulu 		    "status %04X %04X, offset %08x, len %08x\n", ha->host_no,
1048afaf5a2dSDavid Somayajulu 		    __func__, mbox_sts[0], mbox_sts[1], offset, len));
1049afaf5a2dSDavid Somayajulu 		return QLA_ERROR;
1050afaf5a2dSDavid Somayajulu 	}
1051afaf5a2dSDavid Somayajulu 	return QLA_SUCCESS;
1052afaf5a2dSDavid Somayajulu }
1053afaf5a2dSDavid Somayajulu 
1054afaf5a2dSDavid Somayajulu /**
1055afaf5a2dSDavid Somayajulu  * qla4xxx_get_fw_version - gets firmware version
1056afaf5a2dSDavid Somayajulu  * @ha: Pointer to host adapter structure.
1057afaf5a2dSDavid Somayajulu  *
1058afaf5a2dSDavid Somayajulu  * Retrieves the firmware version on HBA. In QLA4010, mailboxes 2 & 3 may
1059afaf5a2dSDavid Somayajulu  * hold an address for data.  Make sure that we write 0 to those mailboxes,
1060afaf5a2dSDavid Somayajulu  * if unused.
1061afaf5a2dSDavid Somayajulu  **/
1062afaf5a2dSDavid Somayajulu int qla4xxx_get_fw_version(struct scsi_qla_host * ha)
1063afaf5a2dSDavid Somayajulu {
1064afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1065afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
1066afaf5a2dSDavid Somayajulu 
1067afaf5a2dSDavid Somayajulu 	/* Get firmware version. */
1068afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1069afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1070c0e344c9SDavid C Somayajulu 
1071afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_ABOUT_FW;
1072c0e344c9SDavid C Somayajulu 
1073c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
1074afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
1075afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_ABOUT_FW failed w/ "
1076afaf5a2dSDavid Somayajulu 		    "status %04X\n", ha->host_no, __func__, mbox_sts[0]));
1077afaf5a2dSDavid Somayajulu 		return QLA_ERROR;
1078afaf5a2dSDavid Somayajulu 	}
1079afaf5a2dSDavid Somayajulu 
1080afaf5a2dSDavid Somayajulu 	/* Save firmware version information. */
1081afaf5a2dSDavid Somayajulu 	ha->firmware_version[0] = mbox_sts[1];
1082afaf5a2dSDavid Somayajulu 	ha->firmware_version[1] = mbox_sts[2];
1083afaf5a2dSDavid Somayajulu 	ha->patch_number = mbox_sts[3];
1084afaf5a2dSDavid Somayajulu 	ha->build_number = mbox_sts[4];
1085afaf5a2dSDavid Somayajulu 
1086afaf5a2dSDavid Somayajulu 	return QLA_SUCCESS;
1087afaf5a2dSDavid Somayajulu }
1088afaf5a2dSDavid Somayajulu 
108947975477SAdrian Bunk static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha,
109047975477SAdrian Bunk 				   dma_addr_t dma_addr)
1091afaf5a2dSDavid Somayajulu {
1092afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1093afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
1094afaf5a2dSDavid Somayajulu 
1095afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1096afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1097afaf5a2dSDavid Somayajulu 
1098afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS;
1099afaf5a2dSDavid Somayajulu 	mbox_cmd[2] = LSDW(dma_addr);
1100afaf5a2dSDavid Somayajulu 	mbox_cmd[3] = MSDW(dma_addr);
1101afaf5a2dSDavid Somayajulu 
1102c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=
1103afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
1104afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
1105afaf5a2dSDavid Somayajulu 		     ha->host_no, __func__, mbox_sts[0]));
1106afaf5a2dSDavid Somayajulu 		return QLA_ERROR;
1107afaf5a2dSDavid Somayajulu 	}
1108afaf5a2dSDavid Somayajulu 	return QLA_SUCCESS;
1109afaf5a2dSDavid Somayajulu }
1110afaf5a2dSDavid Somayajulu 
111147975477SAdrian Bunk static int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index)
1112afaf5a2dSDavid Somayajulu {
1113afaf5a2dSDavid Somayajulu 	uint32_t mbox_cmd[MBOX_REG_COUNT];
1114afaf5a2dSDavid Somayajulu 	uint32_t mbox_sts[MBOX_REG_COUNT];
1115afaf5a2dSDavid Somayajulu 
1116afaf5a2dSDavid Somayajulu 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1117afaf5a2dSDavid Somayajulu 	memset(&mbox_sts, 0, sizeof(mbox_sts));
1118afaf5a2dSDavid Somayajulu 
1119afaf5a2dSDavid Somayajulu 	mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY;
1120afaf5a2dSDavid Somayajulu 	mbox_cmd[1] = MAX_PRST_DEV_DB_ENTRIES;
1121afaf5a2dSDavid Somayajulu 
1122c0e344c9SDavid C Somayajulu 	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) !=
1123afaf5a2dSDavid Somayajulu 	    QLA_SUCCESS) {
1124afaf5a2dSDavid Somayajulu 		if (mbox_sts[0] == MBOX_STS_COMMAND_ERROR) {
1125afaf5a2dSDavid Somayajulu 			*ddb_index = mbox_sts[2];
1126afaf5a2dSDavid Somayajulu 		} else {
1127afaf5a2dSDavid Somayajulu 			DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
1128afaf5a2dSDavid Somayajulu 			     ha->host_no, __func__, mbox_sts[0]));
1129afaf5a2dSDavid Somayajulu 			return QLA_ERROR;
1130afaf5a2dSDavid Somayajulu 		}
1131afaf5a2dSDavid Somayajulu 	} else {
1132afaf5a2dSDavid Somayajulu 		*ddb_index = MAX_PRST_DEV_DB_ENTRIES;
1133afaf5a2dSDavid Somayajulu 	}
1134afaf5a2dSDavid Somayajulu 
1135afaf5a2dSDavid Somayajulu 	return QLA_SUCCESS;
1136afaf5a2dSDavid Somayajulu }
1137afaf5a2dSDavid Somayajulu 
1138afaf5a2dSDavid Somayajulu 
1139afaf5a2dSDavid Somayajulu int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port)
1140afaf5a2dSDavid Somayajulu {
1141afaf5a2dSDavid Somayajulu 	struct dev_db_entry *fw_ddb_entry;
1142afaf5a2dSDavid Somayajulu 	dma_addr_t fw_ddb_entry_dma;
1143afaf5a2dSDavid Somayajulu 	uint32_t ddb_index;
1144afaf5a2dSDavid Somayajulu 	int ret_val = QLA_SUCCESS;
1145afaf5a2dSDavid Somayajulu 
1146afaf5a2dSDavid Somayajulu 
1147afaf5a2dSDavid Somayajulu 	fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
1148afaf5a2dSDavid Somayajulu 					  sizeof(*fw_ddb_entry),
1149afaf5a2dSDavid Somayajulu 					  &fw_ddb_entry_dma, GFP_KERNEL);
1150afaf5a2dSDavid Somayajulu 	if (!fw_ddb_entry) {
1151afaf5a2dSDavid Somayajulu 		DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
1152afaf5a2dSDavid Somayajulu 			      ha->host_no, __func__));
1153afaf5a2dSDavid Somayajulu 		ret_val = QLA_ERROR;
1154beabe7c1SPrasanna Mumbai 		goto exit_send_tgts_no_free;
1155afaf5a2dSDavid Somayajulu 	}
1156afaf5a2dSDavid Somayajulu 
1157afaf5a2dSDavid Somayajulu 	ret_val = qla4xxx_get_default_ddb(ha, fw_ddb_entry_dma);
1158afaf5a2dSDavid Somayajulu 	if (ret_val != QLA_SUCCESS)
1159beabe7c1SPrasanna Mumbai 		goto exit_send_tgts;
1160afaf5a2dSDavid Somayajulu 
1161afaf5a2dSDavid Somayajulu 	ret_val = qla4xxx_req_ddb_entry(ha, &ddb_index);
1162afaf5a2dSDavid Somayajulu 	if (ret_val != QLA_SUCCESS)
1163beabe7c1SPrasanna Mumbai 		goto exit_send_tgts;
1164afaf5a2dSDavid Somayajulu 
1165c0e344c9SDavid C Somayajulu 	memset(fw_ddb_entry->iscsi_alias, 0,
1166c0e344c9SDavid C Somayajulu 	       sizeof(fw_ddb_entry->iscsi_alias));
1167afaf5a2dSDavid Somayajulu 
1168c0e344c9SDavid C Somayajulu 	memset(fw_ddb_entry->iscsi_name, 0,
1169c0e344c9SDavid C Somayajulu 	       sizeof(fw_ddb_entry->iscsi_name));
1170afaf5a2dSDavid Somayajulu 
1171c0e344c9SDavid C Somayajulu 	memset(fw_ddb_entry->ip_addr, 0, sizeof(fw_ddb_entry->ip_addr));
1172c0e344c9SDavid C Somayajulu 	memset(fw_ddb_entry->tgt_addr, 0,
1173c0e344c9SDavid C Somayajulu 	       sizeof(fw_ddb_entry->tgt_addr));
1174afaf5a2dSDavid Somayajulu 
1175afaf5a2dSDavid Somayajulu 	fw_ddb_entry->options = (DDB_OPT_DISC_SESSION | DDB_OPT_TARGET);
1176c0e344c9SDavid C Somayajulu 	fw_ddb_entry->port = cpu_to_le16(ntohs(port));
1177afaf5a2dSDavid Somayajulu 
1178c0e344c9SDavid C Somayajulu 	fw_ddb_entry->ip_addr[0] = *ip;
1179c0e344c9SDavid C Somayajulu 	fw_ddb_entry->ip_addr[1] = *(ip + 1);
1180c0e344c9SDavid C Somayajulu 	fw_ddb_entry->ip_addr[2] = *(ip + 2);
1181c0e344c9SDavid C Somayajulu 	fw_ddb_entry->ip_addr[3] = *(ip + 3);
1182afaf5a2dSDavid Somayajulu 
1183afaf5a2dSDavid Somayajulu 	ret_val = qla4xxx_set_ddb_entry(ha, ddb_index, fw_ddb_entry_dma);
1184afaf5a2dSDavid Somayajulu 
1185beabe7c1SPrasanna Mumbai exit_send_tgts:
1186afaf5a2dSDavid Somayajulu 	dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
1187afaf5a2dSDavid Somayajulu 			  fw_ddb_entry, fw_ddb_entry_dma);
1188beabe7c1SPrasanna Mumbai exit_send_tgts_no_free:
1189afaf5a2dSDavid Somayajulu 	return ret_val;
1190afaf5a2dSDavid Somayajulu }
1191afaf5a2dSDavid Somayajulu 
1192