blob: 0d3d641f891bf8fb44c0c3906dc40eb87951cb23 [file] [log] [blame]
David Somayajuluafaf5a22006-09-19 10:28:00 -07001/*
2 * QLogic iSCSI HBA Driver
Vikas Chaudharyc68cdbf2012-08-22 07:55:09 -04003 * Copyright (c) 2003-2012 QLogic Corporation
David Somayajuluafaf5a22006-09-19 10:28:00 -07004 *
5 * See LICENSE.qla4xxx for copyright and licensing details.
6 */
7
8#include "ql4_def.h"
David C Somayajuluc0e344c2007-05-23 18:03:27 -07009#include "ql4_glbl.h"
10#include "ql4_dbg.h"
11#include "ql4_inline.h"
Manish Dusanecfb27872012-09-20 07:35:01 -040012#include "ql4_version.h"
David Somayajuluafaf5a22006-09-19 10:28:00 -070013
Vikas Chaudhary33693c72012-08-22 07:55:04 -040014void qla4xxx_queue_mbox_cmd(struct scsi_qla_host *ha, uint32_t *mbx_cmd,
15 int in_count)
16{
17 int i;
18
19 /* Load all mailbox registers, except mailbox 0. */
20 for (i = 1; i < in_count; i++)
21 writel(mbx_cmd[i], &ha->reg->mailbox[i]);
22
23 /* Wakeup firmware */
24 writel(mbx_cmd[0], &ha->reg->mailbox[0]);
25 readl(&ha->reg->mailbox[0]);
26 writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status);
27 readl(&ha->reg->ctrl_status);
28}
29
30void qla4xxx_process_mbox_intr(struct scsi_qla_host *ha, int out_count)
31{
32 int intr_status;
33
34 intr_status = readl(&ha->reg->ctrl_status);
35 if (intr_status & INTR_PENDING) {
36 /*
37 * Service the interrupt.
38 * The ISR will save the mailbox status registers
39 * to a temporary storage location in the adapter structure.
40 */
41 ha->mbox_status_count = out_count;
42 ha->isp_ops->interrupt_service_routine(ha, intr_status);
43 }
44}
David Somayajuluafaf5a22006-09-19 10:28:00 -070045
46/**
47 * qla4xxx_mailbox_command - issues mailbox commands
48 * @ha: Pointer to host adapter structure.
49 * @inCount: number of mailbox registers to load.
50 * @outCount: number of mailbox registers to return.
51 * @mbx_cmd: data pointer for mailbox in registers.
52 * @mbx_sts: data pointer for mailbox out registers.
53 *
Justin P. Mattock70f23fd2011-05-10 10:16:21 +020054 * This routine issue mailbox commands and waits for completion.
David Somayajuluafaf5a22006-09-19 10:28:00 -070055 * If outCount is 0, this routine completes successfully WITHOUT waiting
56 * for the mailbox command to complete.
57 **/
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +053058int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
59 uint8_t outCount, uint32_t *mbx_cmd,
60 uint32_t *mbx_sts)
David Somayajuluafaf5a22006-09-19 10:28:00 -070061{
62 int status = QLA_ERROR;
63 uint8_t i;
64 u_long wait_count;
David Somayajuluafaf5a22006-09-19 10:28:00 -070065 unsigned long flags = 0;
Prasanna Mumbai99b53bf2011-03-21 03:34:25 -070066 uint32_t dev_state;
David Somayajuluafaf5a22006-09-19 10:28:00 -070067
68 /* Make sure that pointers are valid */
69 if (!mbx_cmd || !mbx_sts) {
70 DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts "
71 "pointer\n", ha->host_no, __func__));
David C Somayajulu477ffb92007-01-22 12:26:11 -080072 return status;
73 }
Nilesh Javali21033632010-07-30 14:28:07 +053074
Mike Christie13483732011-12-01 21:38:41 -060075 if (is_qla40XX(ha)) {
76 if (test_bit(AF_HA_REMOVAL, &ha->flags)) {
77 DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: "
78 "prematurely completing mbx cmd as "
79 "adapter removal detected\n",
80 ha->host_no, __func__));
81 return status;
82 }
83 }
84
Lalit Chandivade2232be02010-07-30 14:38:47 +053085 if ((is_aer_supported(ha)) &&
86 (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) {
87 DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, "
88 "timeout MBX Exiting.\n", ha->host_no, __func__));
89 return status;
90 }
91
David C Somayajulu477ffb92007-01-22 12:26:11 -080092 /* Mailbox code active */
93 wait_count = MBOX_TOV * 100;
94
95 while (wait_count--) {
96 mutex_lock(&ha->mbox_sem);
97 if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) {
98 set_bit(AF_MBOX_COMMAND, &ha->flags);
99 mutex_unlock(&ha->mbox_sem);
100 break;
101 }
102 mutex_unlock(&ha->mbox_sem);
103 if (!wait_count) {
104 DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n",
105 ha->host_no, __func__));
106 return status;
107 }
108 msleep(10);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700109 }
110
Vikas Chaudhary6e7b4292012-08-22 07:55:08 -0400111 if (is_qla80XX(ha)) {
Lalit Chandivade5f50aa32012-04-23 22:32:32 -0700112 if (test_bit(AF_FW_RECOVERY, &ha->flags)) {
113 DEBUG2(ql4_printk(KERN_WARNING, ha,
114 "scsi%ld: %s: prematurely completing mbx cmd as firmware recovery detected\n",
115 ha->host_no, __func__));
116 goto mbox_exit;
117 }
118 /* Do not send any mbx cmd if h/w is in failed state*/
Vikas Chaudhary33693c72012-08-22 07:55:04 -0400119 ha->isp_ops->idc_lock(ha);
120 dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE);
121 ha->isp_ops->idc_unlock(ha);
Vikas Chaudharyde8c72d2012-08-22 09:14:24 -0400122 if (dev_state == QLA8XXX_DEV_FAILED) {
Lalit Chandivade5f50aa32012-04-23 22:32:32 -0700123 ql4_printk(KERN_WARNING, ha,
124 "scsi%ld: %s: H/W is in failed state, do not send any mailbox commands\n",
125 ha->host_no, __func__);
126 goto mbox_exit;
127 }
128 }
129
David Somayajuluafaf5a22006-09-19 10:28:00 -0700130 spin_lock_irqsave(&ha->hardware_lock, flags);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530131
David Somayajuluafaf5a22006-09-19 10:28:00 -0700132 ha->mbox_status_count = outCount;
133 for (i = 0; i < outCount; i++)
134 ha->mbox_status[i] = 0;
135
Vikas Chaudhary33693c72012-08-22 07:55:04 -0400136 /* Queue the mailbox command to the firmware */
137 ha->isp_ops->queue_mailbox_command(ha, mbx_cmd, inCount);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530138
David Somayajuluafaf5a22006-09-19 10:28:00 -0700139 spin_unlock_irqrestore(&ha->hardware_lock, flags);
140
141 /* Wait for completion */
David Somayajuluafaf5a22006-09-19 10:28:00 -0700142
143 /*
144 * If we don't want status, don't wait for the mailbox command to
145 * complete. For example, MBOX_CMD_RESET_FW doesn't return status,
146 * you must poll the inbound Interrupt Mask for completion.
147 */
148 if (outCount == 0) {
149 status = QLA_SUCCESS;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700150 goto mbox_exit;
151 }
David Somayajuluafaf5a22006-09-19 10:28:00 -0700152
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530153 /*
154 * Wait for completion: Poll or completion queue
155 */
156 if (test_bit(AF_IRQ_ATTACHED, &ha->flags) &&
157 test_bit(AF_INTERRUPTS_ON, &ha->flags) &&
158 test_bit(AF_ONLINE, &ha->flags) &&
Karen Higgins7eece5a2011-03-21 03:34:29 -0700159 !test_bit(AF_HA_REMOVAL, &ha->flags)) {
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530160 /* Do not poll for completion. Use completion queue */
161 set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
162 wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ);
163 clear_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
164 } else {
165 /* Poll for command to complete */
166 wait_count = jiffies + MBOX_TOV * HZ;
167 while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) {
168 if (time_after_eq(jiffies, wait_count))
169 break;
Lalit Chandivade2232be02010-07-30 14:38:47 +0530170
David Somayajuluafaf5a22006-09-19 10:28:00 -0700171 /*
172 * Service the interrupt.
173 * The ISR will save the mailbox status registers
174 * to a temporary storage location in the adapter
175 * structure.
176 */
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530177
178 spin_lock_irqsave(&ha->hardware_lock, flags);
Vikas Chaudhary33693c72012-08-22 07:55:04 -0400179 ha->isp_ops->process_mailbox_interrupt(ha, outCount);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530180 spin_unlock_irqrestore(&ha->hardware_lock, flags);
181 msleep(10);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700182 }
David Somayajuluafaf5a22006-09-19 10:28:00 -0700183 }
David Somayajuluafaf5a22006-09-19 10:28:00 -0700184
185 /* Check for mailbox timeout. */
186 if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) {
Vikas Chaudhary6e7b4292012-08-22 07:55:08 -0400187 if (is_qla80XX(ha) &&
Nilesh Javali21033632010-07-30 14:28:07 +0530188 test_bit(AF_FW_RECOVERY, &ha->flags)) {
189 DEBUG2(ql4_printk(KERN_INFO, ha,
190 "scsi%ld: %s: prematurely completing mbx cmd as "
191 "firmware recovery detected\n",
192 ha->host_no, __func__));
193 goto mbox_exit;
194 }
David Somayajuluafaf5a22006-09-19 10:28:00 -0700195 DEBUG2(printk("scsi%ld: Mailbox Cmd 0x%08X timed out ...,"
196 " Scheduling Adapter Reset\n", ha->host_no,
197 mbx_cmd[0]));
198 ha->mailbox_timeout_count++;
199 mbx_sts[0] = (-1);
200 set_bit(DPC_RESET_HA, &ha->dpc_flags);
Giridhar Malavalie6bd0eb2012-01-11 02:44:16 -0800201 if (is_qla8022(ha)) {
202 ql4_printk(KERN_INFO, ha,
203 "disabling pause transmit on port 0 & 1.\n");
Vikas Chaudharyf8086f42012-08-22 07:54:59 -0400204 qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
Giridhar Malavalie6bd0eb2012-01-11 02:44:16 -0800205 CRB_NIU_XG_PAUSE_CTL_P0 |
206 CRB_NIU_XG_PAUSE_CTL_P1);
207 }
David Somayajuluafaf5a22006-09-19 10:28:00 -0700208 goto mbox_exit;
209 }
210
211 /*
212 * Copy the mailbox out registers to the caller's mailbox in/out
213 * structure.
214 */
215 spin_lock_irqsave(&ha->hardware_lock, flags);
216 for (i = 0; i < outCount; i++)
217 mbx_sts[i] = ha->mbox_status[i];
218
219 /* Set return status and error flags (if applicable). */
220 switch (ha->mbox_status[0]) {
221 case MBOX_STS_COMMAND_COMPLETE:
222 status = QLA_SUCCESS;
223 break;
224
225 case MBOX_STS_INTERMEDIATE_COMPLETION:
226 status = QLA_SUCCESS;
227 break;
228
229 case MBOX_STS_BUSY:
230 DEBUG2( printk("scsi%ld: %s: Cmd = %08X, ISP BUSY\n",
231 ha->host_no, __func__, mbx_cmd[0]));
232 ha->mailbox_timeout_count++;
233 break;
234
235 default:
236 DEBUG2(printk("scsi%ld: %s: **** FAILED, cmd = %08X, "
237 "sts = %08X ****\n", ha->host_no, __func__,
238 mbx_cmd[0], mbx_sts[0]));
239 break;
240 }
241 spin_unlock_irqrestore(&ha->hardware_lock, flags);
242
243mbox_exit:
David C Somayajulu477ffb92007-01-22 12:26:11 -0800244 mutex_lock(&ha->mbox_sem);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700245 clear_bit(AF_MBOX_COMMAND, &ha->flags);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700246 mutex_unlock(&ha->mbox_sem);
David C Somayajulu477ffb92007-01-22 12:26:11 -0800247 clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700248
249 return status;
250}
251
Tej Parkash068237c82012-05-18 04:41:44 -0400252/**
253 * qla4xxx_get_minidump_template - Get the firmware template
254 * @ha: Pointer to host adapter structure.
255 * @phys_addr: dma address for template
256 *
257 * Obtain the minidump template from firmware during initialization
258 * as it may not be available when minidump is desired.
259 **/
260int qla4xxx_get_minidump_template(struct scsi_qla_host *ha,
261 dma_addr_t phys_addr)
262{
263 uint32_t mbox_cmd[MBOX_REG_COUNT];
264 uint32_t mbox_sts[MBOX_REG_COUNT];
265 int status;
266
267 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
268 memset(&mbox_sts, 0, sizeof(mbox_sts));
269
270 mbox_cmd[0] = MBOX_CMD_MINIDUMP;
271 mbox_cmd[1] = MINIDUMP_GET_TMPLT_SUBCOMMAND;
272 mbox_cmd[2] = LSDW(phys_addr);
273 mbox_cmd[3] = MSDW(phys_addr);
274 mbox_cmd[4] = ha->fw_dump_tmplt_size;
275 mbox_cmd[5] = 0;
276
277 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
278 &mbox_sts[0]);
279 if (status != QLA_SUCCESS) {
280 DEBUG2(ql4_printk(KERN_INFO, ha,
281 "scsi%ld: %s: Cmd = %08X, mbx[0] = 0x%04x, mbx[1] = 0x%04x\n",
282 ha->host_no, __func__, mbox_cmd[0],
283 mbox_sts[0], mbox_sts[1]));
284 }
285 return status;
286}
287
288/**
289 * qla4xxx_req_template_size - Get minidump template size from firmware.
290 * @ha: Pointer to host adapter structure.
291 **/
292int qla4xxx_req_template_size(struct scsi_qla_host *ha)
293{
294 uint32_t mbox_cmd[MBOX_REG_COUNT];
295 uint32_t mbox_sts[MBOX_REG_COUNT];
296 int status;
297
298 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
299 memset(&mbox_sts, 0, sizeof(mbox_sts));
300
301 mbox_cmd[0] = MBOX_CMD_MINIDUMP;
302 mbox_cmd[1] = MINIDUMP_GET_SIZE_SUBCOMMAND;
303
304 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0],
305 &mbox_sts[0]);
306 if (status == QLA_SUCCESS) {
307 ha->fw_dump_tmplt_size = mbox_sts[1];
308 DEBUG2(ql4_printk(KERN_INFO, ha,
309 "%s: sts[0]=0x%04x, template size=0x%04x, size_cm_02=0x%04x, size_cm_04=0x%04x, size_cm_08=0x%04x, size_cm_10=0x%04x, size_cm_FF=0x%04x, version=0x%04x\n",
310 __func__, mbox_sts[0], mbox_sts[1],
311 mbox_sts[2], mbox_sts[3], mbox_sts[4],
312 mbox_sts[5], mbox_sts[6], mbox_sts[7]));
313 if (ha->fw_dump_tmplt_size == 0)
314 status = QLA_ERROR;
315 } else {
316 ql4_printk(KERN_WARNING, ha,
317 "%s: Error sts[0]=0x%04x, mbx[1]=0x%04x\n",
318 __func__, mbox_sts[0], mbox_sts[1]);
319 status = QLA_ERROR;
320 }
321
322 return status;
323}
324
Nilesh Javali21033632010-07-30 14:28:07 +0530325void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha)
326{
327 set_bit(AF_FW_RECOVERY, &ha->flags);
328 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: set FW RECOVERY!\n",
329 ha->host_no, __func__);
330
331 if (test_bit(AF_MBOX_COMMAND, &ha->flags)) {
332 if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags)) {
333 complete(&ha->mbx_intr_comp);
334 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw "
335 "recovery, doing premature completion of "
336 "mbx cmd\n", ha->host_no, __func__);
337
338 } else {
339 set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
340 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw "
341 "recovery, doing premature completion of "
342 "polling mbx cmd\n", ha->host_no, __func__);
343 }
344 }
345}
346
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530347static uint8_t
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530348qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
349 uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)
350{
351 memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
352 memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
Shyam Sundar2657c802010-10-06 22:50:29 -0700353
354 if (is_qla8022(ha))
Vikas Chaudharyf8086f42012-08-22 07:54:59 -0400355 qla4_82xx_wr_32(ha, ha->nx_db_wr_ptr, 0);
Shyam Sundar2657c802010-10-06 22:50:29 -0700356
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530357 mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE;
358 mbox_cmd[1] = 0;
359 mbox_cmd[2] = LSDW(init_fw_cb_dma);
360 mbox_cmd[3] = MSDW(init_fw_cb_dma);
361 mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
362 mbox_cmd[5] = (IFCB_VER_MAX << 8) | IFCB_VER_MIN;
363
364 if (qla4xxx_mailbox_command(ha, 6, 6, mbox_cmd, mbox_sts) !=
365 QLA_SUCCESS) {
366 DEBUG2(printk(KERN_WARNING "scsi%ld: %s: "
367 "MBOX_CMD_INITIALIZE_FIRMWARE"
368 " failed w/ status %04X\n",
369 ha->host_no, __func__, mbox_sts[0]));
370 return QLA_ERROR;
371 }
372 return QLA_SUCCESS;
373}
374
Mike Christied00efe32011-07-25 13:48:38 -0500375uint8_t
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530376qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
377 uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)
378{
379 memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
380 memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
381 mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
382 mbox_cmd[2] = LSDW(init_fw_cb_dma);
383 mbox_cmd[3] = MSDW(init_fw_cb_dma);
384 mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
385
386 if (qla4xxx_mailbox_command(ha, 5, 5, mbox_cmd, mbox_sts) !=
387 QLA_SUCCESS) {
388 DEBUG2(printk(KERN_WARNING "scsi%ld: %s: "
389 "MBOX_CMD_GET_INIT_FW_CTRL_BLOCK"
390 " failed w/ status %04X\n",
391 ha->host_no, __func__, mbox_sts[0]));
392 return QLA_ERROR;
393 }
394 return QLA_SUCCESS;
395}
396
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530397static void
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530398qla4xxx_update_local_ip(struct scsi_qla_host *ha,
Vikas Chaudhary2bab08f2011-07-25 13:48:39 -0500399 struct addr_ctrl_blk *init_fw_cb)
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530400{
Vikas Chaudhary2bab08f2011-07-25 13:48:39 -0500401 ha->ip_config.tcp_options = le16_to_cpu(init_fw_cb->ipv4_tcp_opts);
402 ha->ip_config.ipv4_options = le16_to_cpu(init_fw_cb->ipv4_ip_opts);
403 ha->ip_config.ipv4_addr_state =
404 le16_to_cpu(init_fw_cb->ipv4_addr_state);
Vikas Chaudhary943c1572011-08-01 03:26:13 -0700405 ha->ip_config.eth_mtu_size =
406 le16_to_cpu(init_fw_cb->eth_mtu_size);
Vikas Chaudhary2ada7fc2011-08-01 03:26:19 -0700407 ha->ip_config.ipv4_port = le16_to_cpu(init_fw_cb->ipv4_port);
Vikas Chaudhary2bab08f2011-07-25 13:48:39 -0500408
409 if (ha->acb_version == ACB_SUPPORTED) {
410 ha->ip_config.ipv6_options = le16_to_cpu(init_fw_cb->ipv6_opts);
411 ha->ip_config.ipv6_addl_options =
412 le16_to_cpu(init_fw_cb->ipv6_addtl_opts);
413 }
414
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530415 /* Save IPv4 Address Info */
Vikas Chaudhary2bab08f2011-07-25 13:48:39 -0500416 memcpy(ha->ip_config.ip_address, init_fw_cb->ipv4_addr,
417 min(sizeof(ha->ip_config.ip_address),
418 sizeof(init_fw_cb->ipv4_addr)));
419 memcpy(ha->ip_config.subnet_mask, init_fw_cb->ipv4_subnet,
420 min(sizeof(ha->ip_config.subnet_mask),
421 sizeof(init_fw_cb->ipv4_subnet)));
422 memcpy(ha->ip_config.gateway, init_fw_cb->ipv4_gw_addr,
423 min(sizeof(ha->ip_config.gateway),
424 sizeof(init_fw_cb->ipv4_gw_addr)));
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530425
Vikas Chaudhary6ac73e82011-07-25 13:48:49 -0500426 ha->ip_config.ipv4_vlan_tag = be16_to_cpu(init_fw_cb->ipv4_vlan_tag);
427
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530428 if (is_ipv6_enabled(ha)) {
429 /* Save IPv6 Address */
Vikas Chaudhary2bab08f2011-07-25 13:48:39 -0500430 ha->ip_config.ipv6_link_local_state =
431 le16_to_cpu(init_fw_cb->ipv6_lnk_lcl_addr_state);
432 ha->ip_config.ipv6_addr0_state =
433 le16_to_cpu(init_fw_cb->ipv6_addr0_state);
434 ha->ip_config.ipv6_addr1_state =
435 le16_to_cpu(init_fw_cb->ipv6_addr1_state);
436 ha->ip_config.ipv6_default_router_state =
437 le16_to_cpu(init_fw_cb->ipv6_dflt_rtr_state);
438 ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[0] = 0xFE;
439 ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[1] = 0x80;
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530440
Vikas Chaudhary2bab08f2011-07-25 13:48:39 -0500441 memcpy(&ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[8],
442 init_fw_cb->ipv6_if_id,
443 min(sizeof(ha->ip_config.ipv6_link_local_addr)/2,
444 sizeof(init_fw_cb->ipv6_if_id)));
445 memcpy(&ha->ip_config.ipv6_addr0, init_fw_cb->ipv6_addr0,
446 min(sizeof(ha->ip_config.ipv6_addr0),
447 sizeof(init_fw_cb->ipv6_addr0)));
448 memcpy(&ha->ip_config.ipv6_addr1, init_fw_cb->ipv6_addr1,
449 min(sizeof(ha->ip_config.ipv6_addr1),
450 sizeof(init_fw_cb->ipv6_addr1)));
451 memcpy(&ha->ip_config.ipv6_default_router_addr,
452 init_fw_cb->ipv6_dflt_rtr_addr,
453 min(sizeof(ha->ip_config.ipv6_default_router_addr),
454 sizeof(init_fw_cb->ipv6_dflt_rtr_addr)));
Vikas Chaudhary6ac73e82011-07-25 13:48:49 -0500455 ha->ip_config.ipv6_vlan_tag =
456 be16_to_cpu(init_fw_cb->ipv6_vlan_tag);
Vikas Chaudhary2ada7fc2011-08-01 03:26:19 -0700457 ha->ip_config.ipv6_port = le16_to_cpu(init_fw_cb->ipv6_port);
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530458 }
459}
460
Mike Christied00efe32011-07-25 13:48:38 -0500461uint8_t
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530462qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
463 uint32_t *mbox_cmd,
464 uint32_t *mbox_sts,
465 struct addr_ctrl_blk *init_fw_cb,
466 dma_addr_t init_fw_cb_dma)
467{
468 if (qla4xxx_get_ifcb(ha, mbox_cmd, mbox_sts, init_fw_cb_dma)
469 != QLA_SUCCESS) {
470 DEBUG2(printk(KERN_WARNING
471 "scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",
472 ha->host_no, __func__));
473 return QLA_ERROR;
474 }
475
476 DEBUG2(qla4xxx_dump_buffer(init_fw_cb, sizeof(struct addr_ctrl_blk)));
477
478 /* Save some info in adapter structure. */
479 ha->acb_version = init_fw_cb->acb_version;
480 ha->firmware_options = le16_to_cpu(init_fw_cb->fw_options);
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530481 ha->heartbeat_interval = init_fw_cb->hb_interval;
482 memcpy(ha->name_string, init_fw_cb->iscsi_name,
483 min(sizeof(ha->name_string),
484 sizeof(init_fw_cb->iscsi_name)));
Mike Christie13483732011-12-01 21:38:41 -0600485 ha->def_timeout = le16_to_cpu(init_fw_cb->def_timeout);
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530486 /*memcpy(ha->alias, init_fw_cb->Alias,
487 min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/
488
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530489 qla4xxx_update_local_ip(ha, init_fw_cb);
490
491 return QLA_SUCCESS;
492}
493
David Somayajuluafaf5a22006-09-19 10:28:00 -0700494/**
495 * qla4xxx_initialize_fw_cb - initializes firmware control block.
496 * @ha: Pointer to host adapter structure.
497 **/
498int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
499{
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530500 struct addr_ctrl_blk *init_fw_cb;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700501 dma_addr_t init_fw_cb_dma;
502 uint32_t mbox_cmd[MBOX_REG_COUNT];
503 uint32_t mbox_sts[MBOX_REG_COUNT];
504 int status = QLA_ERROR;
505
506 init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530507 sizeof(struct addr_ctrl_blk),
David Somayajuluafaf5a22006-09-19 10:28:00 -0700508 &init_fw_cb_dma, GFP_KERNEL);
509 if (init_fw_cb == NULL) {
510 DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n",
511 ha->host_no, __func__));
Prasanna Mumbaibeabe7c2010-07-10 14:49:38 +0530512 goto exit_init_fw_cb_no_free;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700513 }
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530514 memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
David Somayajuluafaf5a22006-09-19 10:28:00 -0700515
516 /* Get Initialize Firmware Control Block. */
517 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
518 memset(&mbox_sts, 0, sizeof(mbox_sts));
David C Somayajuluc0e344c2007-05-23 18:03:27 -0700519
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530520 if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) !=
David Somayajuluafaf5a22006-09-19 10:28:00 -0700521 QLA_SUCCESS) {
522 dma_free_coherent(&ha->pdev->dev,
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530523 sizeof(struct addr_ctrl_blk),
David Somayajuluafaf5a22006-09-19 10:28:00 -0700524 init_fw_cb, init_fw_cb_dma);
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530525 goto exit_init_fw_cb;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700526 }
527
528 /* Initialize request and response queues. */
529 qla4xxx_init_rings(ha);
530
531 /* Fill in the request and response queue information. */
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530532 init_fw_cb->rqq_consumer_idx = cpu_to_le16(ha->request_out);
533 init_fw_cb->compq_producer_idx = cpu_to_le16(ha->response_in);
534 init_fw_cb->rqq_len = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH);
535 init_fw_cb->compq_len = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH);
536 init_fw_cb->rqq_addr_lo = cpu_to_le32(LSDW(ha->request_dma));
537 init_fw_cb->rqq_addr_hi = cpu_to_le32(MSDW(ha->request_dma));
538 init_fw_cb->compq_addr_lo = cpu_to_le32(LSDW(ha->response_dma));
539 init_fw_cb->compq_addr_hi = cpu_to_le32(MSDW(ha->response_dma));
540 init_fw_cb->shdwreg_addr_lo = cpu_to_le32(LSDW(ha->shadow_regs_dma));
541 init_fw_cb->shdwreg_addr_hi = cpu_to_le32(MSDW(ha->shadow_regs_dma));
David Somayajuluafaf5a22006-09-19 10:28:00 -0700542
543 /* Set up required options. */
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530544 init_fw_cb->fw_options |=
David Somayajuluafaf5a22006-09-19 10:28:00 -0700545 __constant_cpu_to_le16(FWOPT_SESSION_MODE |
546 FWOPT_INITIATOR_MODE);
Shyam Sundar2657c802010-10-06 22:50:29 -0700547
Vikas Chaudhary6e7b4292012-08-22 07:55:08 -0400548 if (is_qla80XX(ha))
Shyam Sundar2657c802010-10-06 22:50:29 -0700549 init_fw_cb->fw_options |=
550 __constant_cpu_to_le16(FWOPT_ENABLE_CRBDB);
551
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530552 init_fw_cb->fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700553
Prasanna Mumbaid32cee32011-03-21 03:34:35 -0700554 init_fw_cb->add_fw_options = 0;
555 init_fw_cb->add_fw_options |=
Manish Rangankarb3a271a2011-07-25 13:48:53 -0500556 __constant_cpu_to_le16(ADFWOPT_SERIALIZE_TASK_MGMT);
557 init_fw_cb->add_fw_options |=
558 __constant_cpu_to_le16(ADFWOPT_AUTOCONN_DISABLE);
Prasanna Mumbaid32cee32011-03-21 03:34:35 -0700559
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530560 if (qla4xxx_set_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)
561 != QLA_SUCCESS) {
562 DEBUG2(printk(KERN_WARNING
563 "scsi%ld: %s: Failed to set init_fw_ctrl_blk\n",
564 ha->host_no, __func__));
565 goto exit_init_fw_cb;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700566 }
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530567
568 if (qla4xxx_update_local_ifcb(ha, &mbox_cmd[0], &mbox_sts[0],
569 init_fw_cb, init_fw_cb_dma) != QLA_SUCCESS) {
570 DEBUG2(printk("scsi%ld: %s: Failed to update local ifcb\n",
571 ha->host_no, __func__));
572 goto exit_init_fw_cb;
573 }
574 status = QLA_SUCCESS;
575
576exit_init_fw_cb:
577 dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
578 init_fw_cb, init_fw_cb_dma);
Prasanna Mumbaibeabe7c2010-07-10 14:49:38 +0530579exit_init_fw_cb_no_free:
David Somayajuluafaf5a22006-09-19 10:28:00 -0700580 return status;
581}
582
583/**
584 * qla4xxx_get_dhcp_ip_address - gets HBA ip address via DHCP
585 * @ha: Pointer to host adapter structure.
586 **/
587int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha)
588{
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530589 struct addr_ctrl_blk *init_fw_cb;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700590 dma_addr_t init_fw_cb_dma;
591 uint32_t mbox_cmd[MBOX_REG_COUNT];
592 uint32_t mbox_sts[MBOX_REG_COUNT];
593
594 init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530595 sizeof(struct addr_ctrl_blk),
David Somayajuluafaf5a22006-09-19 10:28:00 -0700596 &init_fw_cb_dma, GFP_KERNEL);
597 if (init_fw_cb == NULL) {
598 printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no,
599 __func__);
Prasanna Mumbaibeabe7c2010-07-10 14:49:38 +0530600 return QLA_ERROR;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700601 }
602
603 /* Get Initialize Firmware Control Block. */
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530604 memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
605 if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) !=
David Somayajuluafaf5a22006-09-19 10:28:00 -0700606 QLA_SUCCESS) {
607 DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",
608 ha->host_no, __func__));
609 dma_free_coherent(&ha->pdev->dev,
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530610 sizeof(struct addr_ctrl_blk),
David Somayajuluafaf5a22006-09-19 10:28:00 -0700611 init_fw_cb, init_fw_cb_dma);
612 return QLA_ERROR;
613 }
614
615 /* Save IP Address. */
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530616 qla4xxx_update_local_ip(ha, init_fw_cb);
617 dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
618 init_fw_cb, init_fw_cb_dma);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700619
620 return QLA_SUCCESS;
621}
622
623/**
624 * qla4xxx_get_firmware_state - gets firmware state of HBA
625 * @ha: Pointer to host adapter structure.
626 **/
627int qla4xxx_get_firmware_state(struct scsi_qla_host * ha)
628{
629 uint32_t mbox_cmd[MBOX_REG_COUNT];
630 uint32_t mbox_sts[MBOX_REG_COUNT];
631
632 /* Get firmware version */
633 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
634 memset(&mbox_sts, 0, sizeof(mbox_sts));
David C Somayajuluc0e344c2007-05-23 18:03:27 -0700635
David Somayajuluafaf5a22006-09-19 10:28:00 -0700636 mbox_cmd[0] = MBOX_CMD_GET_FW_STATE;
David C Somayajuluc0e344c2007-05-23 18:03:27 -0700637
638 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 4, &mbox_cmd[0], &mbox_sts[0]) !=
David Somayajuluafaf5a22006-09-19 10:28:00 -0700639 QLA_SUCCESS) {
640 DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ "
641 "status %04X\n", ha->host_no, __func__,
642 mbox_sts[0]));
643 return QLA_ERROR;
644 }
645 ha->firmware_state = mbox_sts[1];
646 ha->board_id = mbox_sts[2];
647 ha->addl_fw_state = mbox_sts[3];
648 DEBUG2(printk("scsi%ld: %s firmware_state=0x%x\n",
649 ha->host_no, __func__, ha->firmware_state);)
650
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530651 return QLA_SUCCESS;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700652}
653
654/**
655 * qla4xxx_get_firmware_status - retrieves firmware status
656 * @ha: Pointer to host adapter structure.
657 **/
658int qla4xxx_get_firmware_status(struct scsi_qla_host * ha)
659{
660 uint32_t mbox_cmd[MBOX_REG_COUNT];
661 uint32_t mbox_sts[MBOX_REG_COUNT];
662
663 /* Get firmware version */
664 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
665 memset(&mbox_sts, 0, sizeof(mbox_sts));
David C Somayajuluc0e344c2007-05-23 18:03:27 -0700666
David Somayajuluafaf5a22006-09-19 10:28:00 -0700667 mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS;
David C Somayajuluc0e344c2007-05-23 18:03:27 -0700668
669 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) !=
David Somayajuluafaf5a22006-09-19 10:28:00 -0700670 QLA_SUCCESS) {
671 DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ "
672 "status %04X\n", ha->host_no, __func__,
673 mbox_sts[0]));
674 return QLA_ERROR;
675 }
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530676
Vikas Chaudhary3573bfb2012-02-27 03:08:57 -0800677 ql4_printk(KERN_INFO, ha, "%ld firmware IOCBs available (%d).\n",
Vikas Chaudharyf581a3f2010-10-06 22:47:48 -0700678 ha->host_no, mbox_sts[2]);
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530679
David Somayajuluafaf5a22006-09-19 10:28:00 -0700680 return QLA_SUCCESS;
681}
682
683/**
684 * qla4xxx_get_fwddb_entry - retrieves firmware ddb entry
685 * @ha: Pointer to host adapter structure.
686 * @fw_ddb_index: Firmware's device database index
687 * @fw_ddb_entry: Pointer to firmware's device database entry structure
688 * @num_valid_ddb_entries: Pointer to number of valid ddb entries
689 * @next_ddb_index: Pointer to next valid device database index
690 * @fw_ddb_device_state: Pointer to device state
691 **/
692int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
693 uint16_t fw_ddb_index,
694 struct dev_db_entry *fw_ddb_entry,
695 dma_addr_t fw_ddb_entry_dma,
696 uint32_t *num_valid_ddb_entries,
697 uint32_t *next_ddb_index,
698 uint32_t *fw_ddb_device_state,
699 uint32_t *conn_err_detail,
700 uint16_t *tcp_source_port_num,
701 uint16_t *connection_id)
702{
703 int status = QLA_ERROR;
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530704 uint16_t options;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700705 uint32_t mbox_cmd[MBOX_REG_COUNT];
706 uint32_t mbox_sts[MBOX_REG_COUNT];
707
708 /* Make sure the device index is valid */
709 if (fw_ddb_index >= MAX_DDB_ENTRIES) {
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530710 DEBUG2(printk("scsi%ld: %s: ddb [%d] out of range.\n",
David Somayajuluafaf5a22006-09-19 10:28:00 -0700711 ha->host_no, __func__, fw_ddb_index));
712 goto exit_get_fwddb;
713 }
714 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
715 memset(&mbox_sts, 0, sizeof(mbox_sts));
Lalit Chandivade981c9822012-02-13 18:30:41 +0530716 if (fw_ddb_entry)
717 memset(fw_ddb_entry, 0, sizeof(struct dev_db_entry));
David C Somayajuluc0e344c2007-05-23 18:03:27 -0700718
David Somayajuluafaf5a22006-09-19 10:28:00 -0700719 mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY;
720 mbox_cmd[1] = (uint32_t) fw_ddb_index;
721 mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
722 mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
David C Somayajuluc0e344c2007-05-23 18:03:27 -0700723 mbox_cmd[4] = sizeof(struct dev_db_entry);
724
725 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 7, &mbox_cmd[0], &mbox_sts[0]) ==
David Somayajuluafaf5a22006-09-19 10:28:00 -0700726 QLA_ERROR) {
727 DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed"
728 " with status 0x%04X\n", ha->host_no, __func__,
729 mbox_sts[0]));
730 goto exit_get_fwddb;
731 }
732 if (fw_ddb_index != mbox_sts[1]) {
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530733 DEBUG2(printk("scsi%ld: %s: ddb mismatch [%d] != [%d].\n",
David Somayajuluafaf5a22006-09-19 10:28:00 -0700734 ha->host_no, __func__, fw_ddb_index,
735 mbox_sts[1]));
736 goto exit_get_fwddb;
737 }
738 if (fw_ddb_entry) {
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530739 options = le16_to_cpu(fw_ddb_entry->options);
740 if (options & DDB_OPT_IPV6_DEVICE) {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +0530741 ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d "
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530742 "Next %d State %04x ConnErr %08x %pI6 "
743 ":%04d \"%s\"\n", __func__, fw_ddb_index,
744 mbox_sts[0], mbox_sts[2], mbox_sts[3],
745 mbox_sts[4], mbox_sts[5],
746 fw_ddb_entry->ip_addr,
747 le16_to_cpu(fw_ddb_entry->port),
748 fw_ddb_entry->iscsi_name);
749 } else {
Vikas Chaudharyc2660df2010-07-10 14:51:02 +0530750 ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d "
Vikas Chaudhary2a49a782010-04-28 11:37:07 +0530751 "Next %d State %04x ConnErr %08x %pI4 "
752 ":%04d \"%s\"\n", __func__, fw_ddb_index,
753 mbox_sts[0], mbox_sts[2], mbox_sts[3],
754 mbox_sts[4], mbox_sts[5],
755 fw_ddb_entry->ip_addr,
756 le16_to_cpu(fw_ddb_entry->port),
757 fw_ddb_entry->iscsi_name);
758 }
David Somayajuluafaf5a22006-09-19 10:28:00 -0700759 }
760 if (num_valid_ddb_entries)
761 *num_valid_ddb_entries = mbox_sts[2];
762 if (next_ddb_index)
763 *next_ddb_index = mbox_sts[3];
764 if (fw_ddb_device_state)
765 *fw_ddb_device_state = mbox_sts[4];
766
767 /*
768 * RA: This mailbox has been changed to pass connection error and
769 * details. Its true for ISP4010 as per Version E - Not sure when it
770 * was changed. Get the time2wait from the fw_dd_entry field :
771 * default_time2wait which we call it as minTime2Wait DEV_DB_ENTRY
772 * struct.
773 */
774 if (conn_err_detail)
775 *conn_err_detail = mbox_sts[5];
776 if (tcp_source_port_num)
Randy Dunlap14823382010-04-22 11:02:14 -0700777 *tcp_source_port_num = (uint16_t) (mbox_sts[6] >> 16);
David Somayajuluafaf5a22006-09-19 10:28:00 -0700778 if (connection_id)
779 *connection_id = (uint16_t) mbox_sts[6] & 0x00FF;
780 status = QLA_SUCCESS;
781
782exit_get_fwddb:
783 return status;
784}
785
Manish Rangankarb3a271a2011-07-25 13:48:53 -0500786int qla4xxx_conn_open(struct scsi_qla_host *ha, uint16_t fw_ddb_index)
787{
788 uint32_t mbox_cmd[MBOX_REG_COUNT];
789 uint32_t mbox_sts[MBOX_REG_COUNT];
790 int status;
791
792 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
793 memset(&mbox_sts, 0, sizeof(mbox_sts));
794
795 mbox_cmd[0] = MBOX_CMD_CONN_OPEN;
796 mbox_cmd[1] = fw_ddb_index;
797
798 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
799 &mbox_sts[0]);
800 DEBUG2(ql4_printk(KERN_INFO, ha,
801 "%s: status = %d mbx0 = 0x%x mbx1 = 0x%x\n",
802 __func__, status, mbox_sts[0], mbox_sts[1]));
803 return status;
804}
805
David Somayajuluafaf5a22006-09-19 10:28:00 -0700806/**
807 * qla4xxx_set_fwddb_entry - sets a ddb entry.
808 * @ha: Pointer to host adapter structure.
809 * @fw_ddb_index: Firmware's device database index
Manish Rangankarb3a271a2011-07-25 13:48:53 -0500810 * @fw_ddb_entry_dma: dma address of ddb entry
811 * @mbx_sts: mailbox 0 to be returned or NULL
David Somayajuluafaf5a22006-09-19 10:28:00 -0700812 *
813 * This routine initializes or updates the adapter's device database
Manish Rangankarb3a271a2011-07-25 13:48:53 -0500814 * entry for the specified device.
David Somayajuluafaf5a22006-09-19 10:28:00 -0700815 **/
816int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
Manish Rangankarb3a271a2011-07-25 13:48:53 -0500817 dma_addr_t fw_ddb_entry_dma, uint32_t *mbx_sts)
David Somayajuluafaf5a22006-09-19 10:28:00 -0700818{
819 uint32_t mbox_cmd[MBOX_REG_COUNT];
820 uint32_t mbox_sts[MBOX_REG_COUNT];
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530821 int status;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700822
823 /* Do not wait for completion. The firmware will send us an
824 * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status.
825 */
826 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
827 memset(&mbox_sts, 0, sizeof(mbox_sts));
828
829 mbox_cmd[0] = MBOX_CMD_SET_DATABASE_ENTRY;
830 mbox_cmd[1] = (uint32_t) fw_ddb_index;
831 mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
832 mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
David C Somayajuluc0e344c2007-05-23 18:03:27 -0700833 mbox_cmd[4] = sizeof(struct dev_db_entry);
834
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530835 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0],
Manish Rangankarb3a271a2011-07-25 13:48:53 -0500836 &mbox_sts[0]);
837 if (mbx_sts)
838 *mbx_sts = mbox_sts[0];
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +0530839 DEBUG2(printk("scsi%ld: %s: status=%d mbx0=0x%x mbx4=0x%x\n",
840 ha->host_no, __func__, status, mbox_sts[0], mbox_sts[4]);)
841
842 return status;
David Somayajuluafaf5a22006-09-19 10:28:00 -0700843}
844
Manish Rangankarb3a271a2011-07-25 13:48:53 -0500845int qla4xxx_session_logout_ddb(struct scsi_qla_host *ha,
846 struct ddb_entry *ddb_entry, int options)
847{
848 int status;
849 uint32_t mbox_cmd[MBOX_REG_COUNT];
850 uint32_t mbox_sts[MBOX_REG_COUNT];
851
852 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
853 memset(&mbox_sts, 0, sizeof(mbox_sts));
854
855 mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
856 mbox_cmd[1] = ddb_entry->fw_ddb_index;
857 mbox_cmd[3] = options;
858
859 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
860 &mbox_sts[0]);
861 if (status != QLA_SUCCESS) {
862 DEBUG2(ql4_printk(KERN_INFO, ha,
863 "%s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
864 "failed sts %04X %04X", __func__,
865 mbox_sts[0], mbox_sts[1]));
866 }
867
868 return status;
869}
870
David Somayajuluafaf5a22006-09-19 10:28:00 -0700871/**
872 * qla4xxx_get_crash_record - retrieves crash record.
873 * @ha: Pointer to host adapter structure.
874 *
875 * This routine retrieves a crash record from the QLA4010 after an 8002h aen.
876 **/
877void qla4xxx_get_crash_record(struct scsi_qla_host * ha)
878{
879 uint32_t mbox_cmd[MBOX_REG_COUNT];
880 uint32_t mbox_sts[MBOX_REG_COUNT];
881 struct crash_record *crash_record = NULL;
882 dma_addr_t crash_record_dma = 0;
883 uint32_t crash_record_size = 0;
David C Somayajuluc0e344c2007-05-23 18:03:27 -0700884
David Somayajuluafaf5a22006-09-19 10:28:00 -0700885 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
886 memset(&mbox_sts, 0, sizeof(mbox_cmd));
887
888 /* Get size of crash record. */
889 mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
David C Somayajuluc0e344c2007-05-23 18:03:27 -0700890
891 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
David Somayajuluafaf5a22006-09-19 10:28:00 -0700892 QLA_SUCCESS) {
893 DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n",
894 ha->host_no, __func__));
895 goto exit_get_crash_record;
896 }
897 crash_record_size = mbox_sts[4];
898 if (crash_record_size == 0) {
899 DEBUG2(printk("scsi%ld: %s: ERROR: Crash record size is 0!\n",
900 ha->host_no, __func__));
901 goto exit_get_crash_record;
902 }
903
904 /* Alloc Memory for Crash Record. */
905 crash_record = dma_alloc_coherent(&ha->pdev->dev, crash_record_size,
906 &crash_record_dma, GFP_KERNEL);
907 if (crash_record == NULL)
908 goto exit_get_crash_record;
909
910 /* Get Crash Record. */
David C Somayajuluc0e344c2007-05-23 18:03:27 -0700911 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
912 memset(&mbox_sts, 0, sizeof(mbox_cmd));
913
David Somayajuluafaf5a22006-09-19 10:28:00 -0700914 mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
915 mbox_cmd[2] = LSDW(crash_record_dma);
916 mbox_cmd[3] = MSDW(crash_record_dma);
917 mbox_cmd[4] = crash_record_size;
David C Somayajuluc0e344c2007-05-23 18:03:27 -0700918
919 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
David Somayajuluafaf5a22006-09-19 10:28:00 -0700920 QLA_SUCCESS)
921 goto exit_get_crash_record;
922
923 /* Dump Crash Record. */
924
925exit_get_crash_record:
926 if (crash_record)
927 dma_free_coherent(&ha->pdev->dev, crash_record_size,
928 crash_record, crash_record_dma);
929}
930
931/**
932 * qla4xxx_get_conn_event_log - retrieves connection event log
933 * @ha: Pointer to host adapter structure.
934 **/
935void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha)
936{
937 uint32_t mbox_cmd[MBOX_REG_COUNT];
938 uint32_t mbox_sts[MBOX_REG_COUNT];
939 struct conn_event_log_entry *event_log = NULL;
940 dma_addr_t event_log_dma = 0;
941 uint32_t event_log_size = 0;
942 uint32_t num_valid_entries;
943 uint32_t oldest_entry = 0;
944 uint32_t max_event_log_entries;
945 uint8_t i;
946
David Somayajuluafaf5a22006-09-19 10:28:00 -0700947 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
948 memset(&mbox_sts, 0, sizeof(mbox_cmd));
949
950 /* Get size of crash record. */
951 mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
David C Somayajuluc0e344c2007-05-23 18:03:27 -0700952
953 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
David Somayajuluafaf5a22006-09-19 10:28:00 -0700954 QLA_SUCCESS)
955 goto exit_get_event_log;
956
957 event_log_size = mbox_sts[4];
958 if (event_log_size == 0)
959 goto exit_get_event_log;
960
961 /* Alloc Memory for Crash Record. */
962 event_log = dma_alloc_coherent(&ha->pdev->dev, event_log_size,
963 &event_log_dma, GFP_KERNEL);
964 if (event_log == NULL)
965 goto exit_get_event_log;
966
967 /* Get Crash Record. */
David C Somayajuluc0e344c2007-05-23 18:03:27 -0700968 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
969 memset(&mbox_sts, 0, sizeof(mbox_cmd));
970
David Somayajuluafaf5a22006-09-19 10:28:00 -0700971 mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
972 mbox_cmd[2] = LSDW(event_log_dma);
973 mbox_cmd[3] = MSDW(event_log_dma);
David C Somayajuluc0e344c2007-05-23 18:03:27 -0700974
975 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
David Somayajuluafaf5a22006-09-19 10:28:00 -0700976 QLA_SUCCESS) {
977 DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event "
978 "log!\n", ha->host_no, __func__));
979 goto exit_get_event_log;
980 }
981
982 /* Dump Event Log. */
983 num_valid_entries = mbox_sts[1];
984
985 max_event_log_entries = event_log_size /
986 sizeof(struct conn_event_log_entry);
987
988 if (num_valid_entries > max_event_log_entries)
989 oldest_entry = num_valid_entries % max_event_log_entries;
990
991 DEBUG3(printk("scsi%ld: Connection Event Log Dump (%d entries):\n",
992 ha->host_no, num_valid_entries));
993
Andrew Vasquez11010fe2006-10-06 09:54:59 -0700994 if (ql4xextended_error_logging == 3) {
David Somayajuluafaf5a22006-09-19 10:28:00 -0700995 if (oldest_entry == 0) {
996 /* Circular Buffer has not wrapped around */
997 for (i=0; i < num_valid_entries; i++) {
998 qla4xxx_dump_buffer((uint8_t *)event_log+
999 (i*sizeof(*event_log)),
1000 sizeof(*event_log));
1001 }
1002 }
1003 else {
1004 /* Circular Buffer has wrapped around -
1005 * display accordingly*/
1006 for (i=oldest_entry; i < max_event_log_entries; i++) {
1007 qla4xxx_dump_buffer((uint8_t *)event_log+
1008 (i*sizeof(*event_log)),
1009 sizeof(*event_log));
1010 }
1011 for (i=0; i < oldest_entry; i++) {
1012 qla4xxx_dump_buffer((uint8_t *)event_log+
1013 (i*sizeof(*event_log)),
1014 sizeof(*event_log));
1015 }
1016 }
1017 }
1018
1019exit_get_event_log:
1020 if (event_log)
1021 dma_free_coherent(&ha->pdev->dev, event_log_size, event_log,
1022 event_log_dma);
1023}
1024
1025/**
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05301026 * qla4xxx_abort_task - issues Abort Task
1027 * @ha: Pointer to host adapter structure.
1028 * @srb: Pointer to srb entry
1029 *
1030 * This routine performs a LUN RESET on the specified target/lun.
1031 * The caller must ensure that the ddb_entry and lun_entry pointers
1032 * are valid before calling this routine.
1033 **/
1034int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb)
1035{
1036 uint32_t mbox_cmd[MBOX_REG_COUNT];
1037 uint32_t mbox_sts[MBOX_REG_COUNT];
1038 struct scsi_cmnd *cmd = srb->cmd;
1039 int status = QLA_SUCCESS;
1040 unsigned long flags = 0;
1041 uint32_t index;
1042
1043 /*
1044 * Send abort task command to ISP, so that the ISP will return
1045 * request with ABORT status
1046 */
1047 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1048 memset(&mbox_sts, 0, sizeof(mbox_sts));
1049
1050 spin_lock_irqsave(&ha->hardware_lock, flags);
1051 index = (unsigned long)(unsigned char *)cmd->host_scribble;
1052 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1053
1054 /* Firmware already posted completion on response queue */
1055 if (index == MAX_SRBS)
1056 return status;
1057
1058 mbox_cmd[0] = MBOX_CMD_ABORT_TASK;
Karen Higgins6790d4f2010-12-02 22:12:22 -08001059 mbox_cmd[1] = srb->ddb->fw_ddb_index;
Vikas Chaudhary09a0f712010-04-28 11:42:24 +05301060 mbox_cmd[2] = index;
1061 /* Immediate Command Enable */
1062 mbox_cmd[5] = 0x01;
1063
1064 qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0],
1065 &mbox_sts[0]);
1066 if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE) {
1067 status = QLA_ERROR;
1068
1069 DEBUG2(printk(KERN_WARNING "scsi%ld:%d:%d: abort task FAILED: "
1070 "mbx0=%04X, mb1=%04X, mb2=%04X, mb3=%04X, mb4=%04X\n",
1071 ha->host_no, cmd->device->id, cmd->device->lun, mbox_sts[0],
1072 mbox_sts[1], mbox_sts[2], mbox_sts[3], mbox_sts[4]));
1073 }
1074
1075 return status;
1076}
1077
1078/**
David Somayajuluafaf5a22006-09-19 10:28:00 -07001079 * qla4xxx_reset_lun - issues LUN Reset
1080 * @ha: Pointer to host adapter structure.
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301081 * @ddb_entry: Pointer to device database entry
1082 * @lun: lun number
David Somayajuluafaf5a22006-09-19 10:28:00 -07001083 *
1084 * This routine performs a LUN RESET on the specified target/lun.
1085 * The caller must ensure that the ddb_entry and lun_entry pointers
1086 * are valid before calling this routine.
1087 **/
1088int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
1089 int lun)
1090{
1091 uint32_t mbox_cmd[MBOX_REG_COUNT];
1092 uint32_t mbox_sts[MBOX_REG_COUNT];
1093 int status = QLA_SUCCESS;
1094
1095 DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no,
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301096 ddb_entry->fw_ddb_index, lun));
David Somayajuluafaf5a22006-09-19 10:28:00 -07001097
1098 /*
1099 * Send lun reset command to ISP, so that the ISP will return all
1100 * outstanding requests with RESET status
1101 */
1102 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1103 memset(&mbox_sts, 0, sizeof(mbox_sts));
David C Somayajuluc0e344c2007-05-23 18:03:27 -07001104
David Somayajuluafaf5a22006-09-19 10:28:00 -07001105 mbox_cmd[0] = MBOX_CMD_LUN_RESET;
1106 mbox_cmd[1] = ddb_entry->fw_ddb_index;
1107 mbox_cmd[2] = lun << 8;
1108 mbox_cmd[5] = 0x01; /* Immediate Command Enable */
David C Somayajuluc0e344c2007-05-23 18:03:27 -07001109
1110 qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]);
David Somayajuluafaf5a22006-09-19 10:28:00 -07001111 if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
1112 mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
1113 status = QLA_ERROR;
1114
1115 return status;
1116}
1117
Mike Christiece545032008-02-29 18:25:20 -06001118/**
1119 * qla4xxx_reset_target - issues target Reset
1120 * @ha: Pointer to host adapter structure.
1121 * @db_entry: Pointer to device database entry
1122 * @un_entry: Pointer to lun entry structure
1123 *
1124 * This routine performs a TARGET RESET on the specified target.
1125 * The caller must ensure that the ddb_entry pointers
1126 * are valid before calling this routine.
1127 **/
1128int qla4xxx_reset_target(struct scsi_qla_host *ha,
1129 struct ddb_entry *ddb_entry)
1130{
1131 uint32_t mbox_cmd[MBOX_REG_COUNT];
1132 uint32_t mbox_sts[MBOX_REG_COUNT];
1133 int status = QLA_SUCCESS;
1134
1135 DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no,
Vikas Chaudharyf4f5df22010-07-28 15:53:44 +05301136 ddb_entry->fw_ddb_index));
Mike Christiece545032008-02-29 18:25:20 -06001137
1138 /*
1139 * Send target reset command to ISP, so that the ISP will return all
1140 * outstanding requests with RESET status
1141 */
1142 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1143 memset(&mbox_sts, 0, sizeof(mbox_sts));
1144
1145 mbox_cmd[0] = MBOX_CMD_TARGET_WARM_RESET;
1146 mbox_cmd[1] = ddb_entry->fw_ddb_index;
1147 mbox_cmd[5] = 0x01; /* Immediate Command Enable */
1148
1149 qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
1150 &mbox_sts[0]);
1151 if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
1152 mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
1153 status = QLA_ERROR;
1154
1155 return status;
1156}
David Somayajuluafaf5a22006-09-19 10:28:00 -07001157
1158int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
1159 uint32_t offset, uint32_t len)
1160{
1161 uint32_t mbox_cmd[MBOX_REG_COUNT];
1162 uint32_t mbox_sts[MBOX_REG_COUNT];
1163
1164 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1165 memset(&mbox_sts, 0, sizeof(mbox_sts));
David C Somayajuluc0e344c2007-05-23 18:03:27 -07001166
David Somayajuluafaf5a22006-09-19 10:28:00 -07001167 mbox_cmd[0] = MBOX_CMD_READ_FLASH;
1168 mbox_cmd[1] = LSDW(dma_addr);
1169 mbox_cmd[2] = MSDW(dma_addr);
1170 mbox_cmd[3] = offset;
1171 mbox_cmd[4] = len;
David C Somayajuluc0e344c2007-05-23 18:03:27 -07001172
1173 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], &mbox_sts[0]) !=
David Somayajuluafaf5a22006-09-19 10:28:00 -07001174 QLA_SUCCESS) {
1175 DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ "
1176 "status %04X %04X, offset %08x, len %08x\n", ha->host_no,
1177 __func__, mbox_sts[0], mbox_sts[1], offset, len));
1178 return QLA_ERROR;
1179 }
1180 return QLA_SUCCESS;
1181}
1182
1183/**
Harish Zunjarrao7ad633c2011-05-17 23:17:11 -07001184 * qla4xxx_about_firmware - gets FW, iscsi draft and boot loader version
David Somayajuluafaf5a22006-09-19 10:28:00 -07001185 * @ha: Pointer to host adapter structure.
1186 *
Harish Zunjarrao7ad633c2011-05-17 23:17:11 -07001187 * Retrieves the FW version, iSCSI draft version & bootloader version of HBA.
1188 * Mailboxes 2 & 3 may hold an address for data. Make sure that we write 0 to
1189 * those mailboxes, if unused.
David Somayajuluafaf5a22006-09-19 10:28:00 -07001190 **/
Harish Zunjarrao7ad633c2011-05-17 23:17:11 -07001191int qla4xxx_about_firmware(struct scsi_qla_host *ha)
David Somayajuluafaf5a22006-09-19 10:28:00 -07001192{
Harish Zunjarrao7ad633c2011-05-17 23:17:11 -07001193 struct about_fw_info *about_fw = NULL;
1194 dma_addr_t about_fw_dma;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001195 uint32_t mbox_cmd[MBOX_REG_COUNT];
1196 uint32_t mbox_sts[MBOX_REG_COUNT];
Harish Zunjarrao7ad633c2011-05-17 23:17:11 -07001197 int status = QLA_ERROR;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001198
Harish Zunjarrao7ad633c2011-05-17 23:17:11 -07001199 about_fw = dma_alloc_coherent(&ha->pdev->dev,
1200 sizeof(struct about_fw_info),
1201 &about_fw_dma, GFP_KERNEL);
1202 if (!about_fw) {
1203 DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Unable to alloc memory "
1204 "for about_fw\n", __func__));
1205 return status;
1206 }
1207
1208 memset(about_fw, 0, sizeof(struct about_fw_info));
David Somayajuluafaf5a22006-09-19 10:28:00 -07001209 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1210 memset(&mbox_sts, 0, sizeof(mbox_sts));
David C Somayajuluc0e344c2007-05-23 18:03:27 -07001211
David Somayajuluafaf5a22006-09-19 10:28:00 -07001212 mbox_cmd[0] = MBOX_CMD_ABOUT_FW;
Harish Zunjarrao7ad633c2011-05-17 23:17:11 -07001213 mbox_cmd[2] = LSDW(about_fw_dma);
1214 mbox_cmd[3] = MSDW(about_fw_dma);
1215 mbox_cmd[4] = sizeof(struct about_fw_info);
David C Somayajuluc0e344c2007-05-23 18:03:27 -07001216
Harish Zunjarrao7ad633c2011-05-17 23:17:11 -07001217 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT,
1218 &mbox_cmd[0], &mbox_sts[0]);
1219 if (status != QLA_SUCCESS) {
1220 DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_ABOUT_FW "
1221 "failed w/ status %04X\n", __func__,
1222 mbox_sts[0]));
1223 goto exit_about_fw;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001224 }
1225
Harish Zunjarrao7ad633c2011-05-17 23:17:11 -07001226 /* Save version information. */
1227 ha->firmware_version[0] = le16_to_cpu(about_fw->fw_major);
1228 ha->firmware_version[1] = le16_to_cpu(about_fw->fw_minor);
1229 ha->patch_number = le16_to_cpu(about_fw->fw_patch);
1230 ha->build_number = le16_to_cpu(about_fw->fw_build);
1231 ha->iscsi_major = le16_to_cpu(about_fw->iscsi_major);
1232 ha->iscsi_minor = le16_to_cpu(about_fw->iscsi_minor);
1233 ha->bootload_major = le16_to_cpu(about_fw->bootload_major);
1234 ha->bootload_minor = le16_to_cpu(about_fw->bootload_minor);
1235 ha->bootload_patch = le16_to_cpu(about_fw->bootload_patch);
1236 ha->bootload_build = le16_to_cpu(about_fw->bootload_build);
1237 status = QLA_SUCCESS;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001238
Harish Zunjarrao7ad633c2011-05-17 23:17:11 -07001239exit_about_fw:
1240 dma_free_coherent(&ha->pdev->dev, sizeof(struct about_fw_info),
1241 about_fw, about_fw_dma);
1242 return status;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001243}
1244
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001245static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options,
Adrian Bunk47975472007-04-26 00:35:16 -07001246 dma_addr_t dma_addr)
David Somayajuluafaf5a22006-09-19 10:28:00 -07001247{
1248 uint32_t mbox_cmd[MBOX_REG_COUNT];
1249 uint32_t mbox_sts[MBOX_REG_COUNT];
1250
1251 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1252 memset(&mbox_sts, 0, sizeof(mbox_sts));
1253
1254 mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001255 mbox_cmd[1] = options;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001256 mbox_cmd[2] = LSDW(dma_addr);
1257 mbox_cmd[3] = MSDW(dma_addr);
1258
David C Somayajuluc0e344c2007-05-23 18:03:27 -07001259 if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=
David Somayajuluafaf5a22006-09-19 10:28:00 -07001260 QLA_SUCCESS) {
1261 DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
1262 ha->host_no, __func__, mbox_sts[0]));
1263 return QLA_ERROR;
1264 }
1265 return QLA_SUCCESS;
1266}
1267
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001268int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index,
1269 uint32_t *mbx_sts)
David Somayajuluafaf5a22006-09-19 10:28:00 -07001270{
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001271 int status;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001272 uint32_t mbox_cmd[MBOX_REG_COUNT];
1273 uint32_t mbox_sts[MBOX_REG_COUNT];
1274
1275 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1276 memset(&mbox_sts, 0, sizeof(mbox_sts));
1277
1278 mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001279 mbox_cmd[1] = ddb_index;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001280
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001281 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
1282 &mbox_sts[0]);
1283 if (status != QLA_SUCCESS) {
1284 DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",
1285 __func__, mbox_sts[0]));
David Somayajuluafaf5a22006-09-19 10:28:00 -07001286 }
1287
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001288 *mbx_sts = mbox_sts[0];
1289 return status;
David Somayajuluafaf5a22006-09-19 10:28:00 -07001290}
1291
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001292int qla4xxx_clear_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index)
1293{
1294 int status;
1295 uint32_t mbox_cmd[MBOX_REG_COUNT];
1296 uint32_t mbox_sts[MBOX_REG_COUNT];
1297
1298 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1299 memset(&mbox_sts, 0, sizeof(mbox_sts));
1300
1301 mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY;
1302 mbox_cmd[1] = ddb_index;
1303
1304 status = qla4xxx_mailbox_command(ha, 2, 1, &mbox_cmd[0],
1305 &mbox_sts[0]);
1306 if (status != QLA_SUCCESS) {
1307 DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",
1308 __func__, mbox_sts[0]));
1309 }
1310
1311 return status;
1312}
1313
Mike Christied00efe32011-07-25 13:48:38 -05001314int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
1315 uint32_t offset, uint32_t length, uint32_t options)
1316{
1317 uint32_t mbox_cmd[MBOX_REG_COUNT];
1318 uint32_t mbox_sts[MBOX_REG_COUNT];
1319 int status = QLA_SUCCESS;
1320
1321 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1322 memset(&mbox_sts, 0, sizeof(mbox_sts));
1323
1324 mbox_cmd[0] = MBOX_CMD_WRITE_FLASH;
1325 mbox_cmd[1] = LSDW(dma_addr);
1326 mbox_cmd[2] = MSDW(dma_addr);
1327 mbox_cmd[3] = offset;
1328 mbox_cmd[4] = length;
1329 mbox_cmd[5] = options;
1330
1331 status = qla4xxx_mailbox_command(ha, 6, 2, &mbox_cmd[0], &mbox_sts[0]);
1332 if (status != QLA_SUCCESS) {
1333 DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_WRITE_FLASH "
1334 "failed w/ status %04X, mbx1 %04X\n",
1335 __func__, mbox_sts[0], mbox_sts[1]));
1336 }
1337 return status;
1338}
1339
Manish Rangankar2a991c22011-07-25 13:48:55 -05001340int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha,
1341 struct dev_db_entry *fw_ddb_entry,
1342 dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index)
1343{
1344 uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO;
1345 uint32_t dev_db_end_offset;
1346 int status = QLA_ERROR;
1347
1348 memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry));
1349
1350 dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry));
1351 dev_db_end_offset = FLASH_OFFSET_DB_END;
1352
1353 if (dev_db_start_offset > dev_db_end_offset) {
1354 DEBUG2(ql4_printk(KERN_ERR, ha,
1355 "%s:Invalid DDB index %d", __func__,
1356 ddb_index));
1357 goto exit_bootdb_failed;
1358 }
1359
1360 if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset,
1361 sizeof(*fw_ddb_entry)) != QLA_SUCCESS) {
1362 ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash"
1363 "failed\n", ha->host_no, __func__);
1364 goto exit_bootdb_failed;
1365 }
1366
1367 if (fw_ddb_entry->cookie == DDB_VALID_COOKIE)
1368 status = QLA_SUCCESS;
1369
1370exit_bootdb_failed:
1371 return status;
1372}
1373
1374int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,
1375 uint16_t idx)
1376{
1377 int ret = 0;
1378 int rval = QLA_ERROR;
Lalit Chandivade45494152011-10-07 16:55:42 -07001379 uint32_t offset = 0, chap_size;
Manish Rangankar2a991c22011-07-25 13:48:55 -05001380 struct ql4_chap_table *chap_table;
1381 dma_addr_t chap_dma;
1382
1383 chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);
1384 if (chap_table == NULL) {
1385 ret = -ENOMEM;
1386 goto exit_get_chap;
1387 }
1388
Lalit Chandivade45494152011-10-07 16:55:42 -07001389 chap_size = sizeof(struct ql4_chap_table);
1390 memset(chap_table, 0, chap_size);
Manish Rangankar2a991c22011-07-25 13:48:55 -05001391
Lalit Chandivade45494152011-10-07 16:55:42 -07001392 if (is_qla40XX(ha))
1393 offset = FLASH_CHAP_OFFSET | (idx * chap_size);
1394 else {
1395 offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);
1396 /* flt_chap_size is CHAP table size for both ports
1397 * so divide it by 2 to calculate the offset for second port
1398 */
1399 if (ha->port_num == 1)
1400 offset += (ha->hw.flt_chap_size / 2);
1401 offset += (idx * chap_size);
1402 }
Manish Rangankar2a991c22011-07-25 13:48:55 -05001403
Lalit Chandivade45494152011-10-07 16:55:42 -07001404 rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size);
Manish Rangankar2a991c22011-07-25 13:48:55 -05001405 if (rval != QLA_SUCCESS) {
1406 ret = -EINVAL;
1407 goto exit_get_chap;
1408 }
1409
1410 DEBUG2(ql4_printk(KERN_INFO, ha, "Chap Cookie: x%x\n",
1411 __le16_to_cpu(chap_table->cookie)));
1412
1413 if (__le16_to_cpu(chap_table->cookie) != CHAP_VALID_COOKIE) {
1414 ql4_printk(KERN_ERR, ha, "No valid chap entry found\n");
1415 goto exit_get_chap;
1416 }
1417
1418 strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
1419 strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
1420 chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE);
1421
1422exit_get_chap:
1423 dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
1424 return ret;
1425}
1426
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001427static int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username,
1428 char *password, uint16_t idx, int bidi)
1429{
1430 int ret = 0;
1431 int rval = QLA_ERROR;
1432 uint32_t offset = 0;
1433 struct ql4_chap_table *chap_table;
1434 dma_addr_t chap_dma;
1435
1436 chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);
1437 if (chap_table == NULL) {
1438 ret = -ENOMEM;
1439 goto exit_set_chap;
1440 }
1441
1442 memset(chap_table, 0, sizeof(struct ql4_chap_table));
1443 if (bidi)
1444 chap_table->flags |= BIT_6; /* peer */
1445 else
1446 chap_table->flags |= BIT_7; /* local */
1447 chap_table->secret_len = strlen(password);
1448 strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN);
1449 strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN);
1450 chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE);
Lalit Chandivade45494152011-10-07 16:55:42 -07001451 offset = FLASH_CHAP_OFFSET | (idx * sizeof(struct ql4_chap_table));
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001452 rval = qla4xxx_set_flash(ha, chap_dma, offset,
1453 sizeof(struct ql4_chap_table),
1454 FLASH_OPT_RMW_COMMIT);
Lalit Chandivade45494152011-10-07 16:55:42 -07001455
1456 if (rval == QLA_SUCCESS && ha->chap_list) {
1457 /* Update ha chap_list cache */
1458 memcpy((struct ql4_chap_table *)ha->chap_list + idx,
1459 chap_table, sizeof(struct ql4_chap_table));
1460 }
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001461 dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
1462 if (rval != QLA_SUCCESS)
1463 ret = -EINVAL;
1464
1465exit_set_chap:
1466 return ret;
1467}
1468
Lalit Chandivade45494152011-10-07 16:55:42 -07001469/**
1470 * qla4xxx_get_chap_index - Get chap index given username and secret
1471 * @ha: pointer to adapter structure
1472 * @username: CHAP username to be searched
1473 * @password: CHAP password to be searched
1474 * @bidi: Is this a BIDI CHAP
1475 * @chap_index: CHAP index to be returned
1476 *
1477 * Match the username and password in the chap_list, return the index if a
1478 * match is found. If a match is not found then add the entry in FLASH and
1479 * return the index at which entry is written in the FLASH.
1480 **/
Mike Christiefca9f042012-02-27 03:08:54 -08001481int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username,
1482 char *password, int bidi, uint16_t *chap_index)
Lalit Chandivade45494152011-10-07 16:55:42 -07001483{
1484 int i, rval;
1485 int free_index = -1;
1486 int found_index = 0;
1487 int max_chap_entries = 0;
1488 struct ql4_chap_table *chap_table;
1489
1490 if (is_qla8022(ha))
1491 max_chap_entries = (ha->hw.flt_chap_size / 2) /
1492 sizeof(struct ql4_chap_table);
1493 else
1494 max_chap_entries = MAX_CHAP_ENTRIES_40XX;
1495
1496 if (!ha->chap_list) {
1497 ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");
1498 return QLA_ERROR;
1499 }
1500
Mike Christiefca9f042012-02-27 03:08:54 -08001501 if (!username || !password) {
1502 ql4_printk(KERN_ERR, ha, "Do not have username and psw\n");
1503 return QLA_ERROR;
1504 }
1505
Lalit Chandivade45494152011-10-07 16:55:42 -07001506 mutex_lock(&ha->chap_sem);
1507 for (i = 0; i < max_chap_entries; i++) {
1508 chap_table = (struct ql4_chap_table *)ha->chap_list + i;
1509 if (chap_table->cookie !=
1510 __constant_cpu_to_le16(CHAP_VALID_COOKIE)) {
1511 if (i > MAX_RESRV_CHAP_IDX && free_index == -1)
1512 free_index = i;
1513 continue;
1514 }
1515 if (bidi) {
1516 if (chap_table->flags & BIT_7)
1517 continue;
1518 } else {
1519 if (chap_table->flags & BIT_6)
1520 continue;
1521 }
1522 if (!strncmp(chap_table->secret, password,
1523 MAX_CHAP_SECRET_LEN) &&
1524 !strncmp(chap_table->name, username,
1525 MAX_CHAP_NAME_LEN)) {
1526 *chap_index = i;
1527 found_index = 1;
1528 break;
1529 }
1530 }
1531
1532 /* If chap entry is not present and a free index is available then
1533 * write the entry in flash
1534 */
1535 if (!found_index && free_index != -1) {
1536 rval = qla4xxx_set_chap(ha, username, password,
1537 free_index, bidi);
1538 if (!rval) {
1539 *chap_index = free_index;
1540 found_index = 1;
1541 }
1542 }
1543
1544 mutex_unlock(&ha->chap_sem);
1545
1546 if (found_index)
1547 return QLA_SUCCESS;
1548 return QLA_ERROR;
1549}
1550
Mike Christied00efe32011-07-25 13:48:38 -05001551int qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha,
1552 uint16_t fw_ddb_index,
1553 uint16_t connection_id,
1554 uint16_t option)
1555{
1556 uint32_t mbox_cmd[MBOX_REG_COUNT];
1557 uint32_t mbox_sts[MBOX_REG_COUNT];
1558 int status = QLA_SUCCESS;
1559
1560 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1561 memset(&mbox_sts, 0, sizeof(mbox_sts));
1562
1563 mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
1564 mbox_cmd[1] = fw_ddb_index;
1565 mbox_cmd[2] = connection_id;
1566 mbox_cmd[3] = option;
1567
1568 status = qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]);
1569 if (status != QLA_SUCCESS) {
1570 DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_CONN_CLOSE "
1571 "option %04x failed w/ status %04X %04X\n",
1572 __func__, option, mbox_sts[0], mbox_sts[1]));
1573 }
1574 return status;
1575}
1576
1577int qla4xxx_disable_acb(struct scsi_qla_host *ha)
1578{
1579 uint32_t mbox_cmd[MBOX_REG_COUNT];
1580 uint32_t mbox_sts[MBOX_REG_COUNT];
1581 int status = QLA_SUCCESS;
1582
1583 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1584 memset(&mbox_sts, 0, sizeof(mbox_sts));
1585
1586 mbox_cmd[0] = MBOX_CMD_DISABLE_ACB;
1587
1588 status = qla4xxx_mailbox_command(ha, 8, 5, &mbox_cmd[0], &mbox_sts[0]);
1589 if (status != QLA_SUCCESS) {
1590 DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_DISABLE_ACB "
1591 "failed w/ status %04X %04X %04X", __func__,
1592 mbox_sts[0], mbox_sts[1], mbox_sts[2]));
1593 }
1594 return status;
1595}
1596
Harish Zunjarrao60854912011-08-12 02:51:27 -07001597int qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma,
1598 uint32_t acb_type, uint32_t len)
Mike Christied00efe32011-07-25 13:48:38 -05001599{
Harish Zunjarrao60854912011-08-12 02:51:27 -07001600 uint32_t mbox_cmd[MBOX_REG_COUNT];
1601 uint32_t mbox_sts[MBOX_REG_COUNT];
Mike Christied00efe32011-07-25 13:48:38 -05001602 int status = QLA_SUCCESS;
1603
Harish Zunjarrao60854912011-08-12 02:51:27 -07001604 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1605 memset(&mbox_sts, 0, sizeof(mbox_sts));
1606
Mike Christied00efe32011-07-25 13:48:38 -05001607 mbox_cmd[0] = MBOX_CMD_GET_ACB;
Harish Zunjarrao60854912011-08-12 02:51:27 -07001608 mbox_cmd[1] = acb_type;
Mike Christied00efe32011-07-25 13:48:38 -05001609 mbox_cmd[2] = LSDW(acb_dma);
1610 mbox_cmd[3] = MSDW(acb_dma);
Harish Zunjarrao60854912011-08-12 02:51:27 -07001611 mbox_cmd[4] = len;
Mike Christied00efe32011-07-25 13:48:38 -05001612
1613 status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);
1614 if (status != QLA_SUCCESS) {
1615 DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_GET_ACB "
1616 "failed w/ status %04X\n", __func__,
1617 mbox_sts[0]));
1618 }
1619 return status;
1620}
1621
1622int qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
1623 uint32_t *mbox_sts, dma_addr_t acb_dma)
1624{
1625 int status = QLA_SUCCESS;
1626
1627 memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
1628 memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
1629 mbox_cmd[0] = MBOX_CMD_SET_ACB;
1630 mbox_cmd[1] = 0; /* Primary ACB */
1631 mbox_cmd[2] = LSDW(acb_dma);
1632 mbox_cmd[3] = MSDW(acb_dma);
1633 mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
1634
1635 status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);
1636 if (status != QLA_SUCCESS) {
1637 DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_SET_ACB "
1638 "failed w/ status %04X\n", __func__,
1639 mbox_sts[0]));
1640 }
1641 return status;
1642}
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001643
1644int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
1645 struct ddb_entry *ddb_entry,
1646 struct iscsi_cls_conn *cls_conn,
1647 uint32_t *mbx_sts)
1648{
1649 struct dev_db_entry *fw_ddb_entry;
1650 struct iscsi_conn *conn;
1651 struct iscsi_session *sess;
1652 struct qla_conn *qla_conn;
1653 struct sockaddr *dst_addr;
1654 dma_addr_t fw_ddb_entry_dma;
1655 int status = QLA_SUCCESS;
1656 int rval = 0;
1657 struct sockaddr_in *addr;
1658 struct sockaddr_in6 *addr6;
1659 char *ip;
1660 uint16_t iscsi_opts = 0;
1661 uint32_t options = 0;
Manish Rangankar173269e2012-02-27 03:08:55 -08001662 uint16_t idx, *ptid;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001663
1664 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
1665 &fw_ddb_entry_dma, GFP_KERNEL);
1666 if (!fw_ddb_entry) {
1667 DEBUG2(ql4_printk(KERN_ERR, ha,
1668 "%s: Unable to allocate dma buffer.\n",
1669 __func__));
1670 rval = -ENOMEM;
1671 goto exit_set_param_no_free;
1672 }
1673
1674 conn = cls_conn->dd_data;
1675 qla_conn = conn->dd_data;
1676 sess = conn->session;
Manish Rangankard46bdeb2012-08-07 07:57:13 -04001677 dst_addr = (struct sockaddr *)&qla_conn->qla_ep->dst_addr;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001678
1679 if (dst_addr->sa_family == AF_INET6)
1680 options |= IPV6_DEFAULT_DDB_ENTRY;
1681
1682 status = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma);
1683 if (status == QLA_ERROR) {
1684 rval = -EINVAL;
1685 goto exit_set_param;
1686 }
1687
Manish Rangankar173269e2012-02-27 03:08:55 -08001688 ptid = (uint16_t *)&fw_ddb_entry->isid[1];
1689 *ptid = cpu_to_le16((uint16_t)ddb_entry->sess->target_id);
1690
1691 DEBUG2(ql4_printk(KERN_INFO, ha, "ISID [%02x%02x%02x%02x%02x%02x]\n",
1692 fw_ddb_entry->isid[5], fw_ddb_entry->isid[4],
1693 fw_ddb_entry->isid[3], fw_ddb_entry->isid[2],
1694 fw_ddb_entry->isid[1], fw_ddb_entry->isid[0]));
1695
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001696 iscsi_opts = le16_to_cpu(fw_ddb_entry->iscsi_options);
1697 memset(fw_ddb_entry->iscsi_alias, 0, sizeof(fw_ddb_entry->iscsi_alias));
1698
1699 memset(fw_ddb_entry->iscsi_name, 0, sizeof(fw_ddb_entry->iscsi_name));
1700
1701 if (sess->targetname != NULL) {
1702 memcpy(fw_ddb_entry->iscsi_name, sess->targetname,
1703 min(strlen(sess->targetname),
1704 sizeof(fw_ddb_entry->iscsi_name)));
1705 }
1706
1707 memset(fw_ddb_entry->ip_addr, 0, sizeof(fw_ddb_entry->ip_addr));
1708 memset(fw_ddb_entry->tgt_addr, 0, sizeof(fw_ddb_entry->tgt_addr));
1709
1710 fw_ddb_entry->options = DDB_OPT_TARGET | DDB_OPT_AUTO_SENDTGTS_DISABLE;
1711
1712 if (dst_addr->sa_family == AF_INET) {
1713 addr = (struct sockaddr_in *)dst_addr;
1714 ip = (char *)&addr->sin_addr;
1715 memcpy(fw_ddb_entry->ip_addr, ip, IP_ADDR_LEN);
1716 fw_ddb_entry->port = cpu_to_le16(ntohs(addr->sin_port));
1717 DEBUG2(ql4_printk(KERN_INFO, ha,
1718 "%s: Destination Address [%pI4]: index [%d]\n",
1719 __func__, fw_ddb_entry->ip_addr,
1720 ddb_entry->fw_ddb_index));
1721 } else if (dst_addr->sa_family == AF_INET6) {
1722 addr6 = (struct sockaddr_in6 *)dst_addr;
1723 ip = (char *)&addr6->sin6_addr;
1724 memcpy(fw_ddb_entry->ip_addr, ip, IPv6_ADDR_LEN);
1725 fw_ddb_entry->port = cpu_to_le16(ntohs(addr6->sin6_port));
1726 fw_ddb_entry->options |= DDB_OPT_IPV6_DEVICE;
1727 DEBUG2(ql4_printk(KERN_INFO, ha,
1728 "%s: Destination Address [%pI6]: index [%d]\n",
1729 __func__, fw_ddb_entry->ip_addr,
1730 ddb_entry->fw_ddb_index));
1731 } else {
1732 ql4_printk(KERN_ERR, ha,
1733 "%s: Failed to get IP Address\n",
1734 __func__);
1735 rval = -EINVAL;
1736 goto exit_set_param;
1737 }
1738
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001739 /* CHAP */
1740 if (sess->username != NULL && sess->password != NULL) {
1741 if (strlen(sess->username) && strlen(sess->password)) {
1742 iscsi_opts |= BIT_7;
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001743
Lalit Chandivade45494152011-10-07 16:55:42 -07001744 rval = qla4xxx_get_chap_index(ha, sess->username,
1745 sess->password,
1746 LOCAL_CHAP, &idx);
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001747 if (rval)
1748 goto exit_set_param;
1749
1750 fw_ddb_entry->chap_tbl_idx = cpu_to_le16(idx);
1751 }
1752 }
1753
1754 if (sess->username_in != NULL && sess->password_in != NULL) {
1755 /* Check if BIDI CHAP */
1756 if (strlen(sess->username_in) && strlen(sess->password_in)) {
1757 iscsi_opts |= BIT_4;
Lalit Chandivade45494152011-10-07 16:55:42 -07001758
1759 rval = qla4xxx_get_chap_index(ha, sess->username_in,
1760 sess->password_in,
1761 BIDI_CHAP, &idx);
Manish Rangankarb3a271a2011-07-25 13:48:53 -05001762 if (rval)
1763 goto exit_set_param;
1764 }
1765 }
1766
1767 if (sess->initial_r2t_en)
1768 iscsi_opts |= BIT_10;
1769
1770 if (sess->imm_data_en)
1771 iscsi_opts |= BIT_11;
1772
1773 fw_ddb_entry->iscsi_options = cpu_to_le16(iscsi_opts);
1774
1775 if (conn->max_recv_dlength)
1776 fw_ddb_entry->iscsi_max_rcv_data_seg_len =
1777 __constant_cpu_to_le16((conn->max_recv_dlength / BYTE_UNITS));
1778
1779 if (sess->max_r2t)
1780 fw_ddb_entry->iscsi_max_outsnd_r2t = cpu_to_le16(sess->max_r2t);
1781
1782 if (sess->first_burst)
1783 fw_ddb_entry->iscsi_first_burst_len =
1784 __constant_cpu_to_le16((sess->first_burst / BYTE_UNITS));
1785
1786 if (sess->max_burst)
1787 fw_ddb_entry->iscsi_max_burst_len =
1788 __constant_cpu_to_le16((sess->max_burst / BYTE_UNITS));
1789
1790 if (sess->time2wait)
1791 fw_ddb_entry->iscsi_def_time2wait =
1792 cpu_to_le16(sess->time2wait);
1793
1794 if (sess->time2retain)
1795 fw_ddb_entry->iscsi_def_time2retain =
1796 cpu_to_le16(sess->time2retain);
1797
1798 status = qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index,
1799 fw_ddb_entry_dma, mbx_sts);
1800
1801 if (status != QLA_SUCCESS)
1802 rval = -EINVAL;
1803exit_set_param:
1804 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
1805 fw_ddb_entry, fw_ddb_entry_dma);
1806exit_set_param_no_free:
1807 return rval;
1808}
1809
1810int qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index,
1811 uint16_t stats_size, dma_addr_t stats_dma)
1812{
1813 int status = QLA_SUCCESS;
1814 uint32_t mbox_cmd[MBOX_REG_COUNT];
1815 uint32_t mbox_sts[MBOX_REG_COUNT];
1816
1817 memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
1818 memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
1819 mbox_cmd[0] = MBOX_CMD_GET_MANAGEMENT_DATA;
1820 mbox_cmd[1] = fw_ddb_index;
1821 mbox_cmd[2] = LSDW(stats_dma);
1822 mbox_cmd[3] = MSDW(stats_dma);
1823 mbox_cmd[4] = stats_size;
1824
1825 status = qla4xxx_mailbox_command(ha, 5, 1, &mbox_cmd[0], &mbox_sts[0]);
1826 if (status != QLA_SUCCESS) {
1827 DEBUG2(ql4_printk(KERN_WARNING, ha,
1828 "%s: MBOX_CMD_GET_MANAGEMENT_DATA "
1829 "failed w/ status %04X\n", __func__,
1830 mbox_sts[0]));
1831 }
1832 return status;
1833}
Harish Zunjarrao8b0402e2011-08-01 03:26:15 -07001834
1835int qla4xxx_get_ip_state(struct scsi_qla_host *ha, uint32_t acb_idx,
1836 uint32_t ip_idx, uint32_t *sts)
1837{
1838 uint32_t mbox_cmd[MBOX_REG_COUNT];
1839 uint32_t mbox_sts[MBOX_REG_COUNT];
1840 int status = QLA_SUCCESS;
1841
1842 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1843 memset(&mbox_sts, 0, sizeof(mbox_sts));
1844 mbox_cmd[0] = MBOX_CMD_GET_IP_ADDR_STATE;
1845 mbox_cmd[1] = acb_idx;
1846 mbox_cmd[2] = ip_idx;
1847
1848 status = qla4xxx_mailbox_command(ha, 3, 8, &mbox_cmd[0], &mbox_sts[0]);
1849 if (status != QLA_SUCCESS) {
1850 DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: "
1851 "MBOX_CMD_GET_IP_ADDR_STATE failed w/ "
1852 "status %04X\n", __func__, mbox_sts[0]));
1853 }
1854 memcpy(sts, mbox_sts, sizeof(mbox_sts));
1855 return status;
1856}
Harish Zunjarrao7c07d132011-08-01 03:26:16 -07001857
1858int qla4xxx_get_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,
1859 uint32_t offset, uint32_t size)
1860{
1861 int status = QLA_SUCCESS;
1862 uint32_t mbox_cmd[MBOX_REG_COUNT];
1863 uint32_t mbox_sts[MBOX_REG_COUNT];
1864
1865 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1866 memset(&mbox_sts, 0, sizeof(mbox_sts));
1867
1868 mbox_cmd[0] = MBOX_CMD_GET_NVRAM;
1869 mbox_cmd[1] = LSDW(nvram_dma);
1870 mbox_cmd[2] = MSDW(nvram_dma);
1871 mbox_cmd[3] = offset;
1872 mbox_cmd[4] = size;
1873
1874 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
1875 &mbox_sts[0]);
1876 if (status != QLA_SUCCESS) {
1877 DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
1878 "status %04X\n", ha->host_no, __func__,
1879 mbox_sts[0]));
1880 }
1881 return status;
1882}
1883
1884int qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,
1885 uint32_t offset, uint32_t size)
1886{
1887 int status = QLA_SUCCESS;
1888 uint32_t mbox_cmd[MBOX_REG_COUNT];
1889 uint32_t mbox_sts[MBOX_REG_COUNT];
1890
1891 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1892 memset(&mbox_sts, 0, sizeof(mbox_sts));
1893
1894 mbox_cmd[0] = MBOX_CMD_SET_NVRAM;
1895 mbox_cmd[1] = LSDW(nvram_dma);
1896 mbox_cmd[2] = MSDW(nvram_dma);
1897 mbox_cmd[3] = offset;
1898 mbox_cmd[4] = size;
1899
1900 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
1901 &mbox_sts[0]);
1902 if (status != QLA_SUCCESS) {
1903 DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
1904 "status %04X\n", ha->host_no, __func__,
1905 mbox_sts[0]));
1906 }
1907 return status;
1908}
Harish Zunjarrao5232f802011-08-12 02:51:26 -07001909
1910int qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha,
1911 uint32_t region, uint32_t field0,
1912 uint32_t field1)
1913{
1914 int status = QLA_SUCCESS;
1915 uint32_t mbox_cmd[MBOX_REG_COUNT];
1916 uint32_t mbox_sts[MBOX_REG_COUNT];
1917
1918 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1919 memset(&mbox_sts, 0, sizeof(mbox_sts));
1920
1921 mbox_cmd[0] = MBOX_CMD_RESTORE_FACTORY_DEFAULTS;
1922 mbox_cmd[3] = region;
1923 mbox_cmd[4] = field0;
1924 mbox_cmd[5] = field1;
1925
1926 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0],
1927 &mbox_sts[0]);
1928 if (status != QLA_SUCCESS) {
1929 DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
1930 "status %04X\n", ha->host_no, __func__,
1931 mbox_sts[0]));
1932 }
1933 return status;
1934}
Manish Dusanecfb27872012-09-20 07:35:01 -04001935
1936/**
1937 * qla4_8xxx_set_param - set driver version in firmware.
1938 * @ha: Pointer to host adapter structure.
1939 * @param: Parameter to set i.e driver version
1940 **/
1941int qla4_8xxx_set_param(struct scsi_qla_host *ha, int param)
1942{
1943 uint32_t mbox_cmd[MBOX_REG_COUNT];
1944 uint32_t mbox_sts[MBOX_REG_COUNT];
1945 uint32_t status;
1946
1947 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1948 memset(&mbox_sts, 0, sizeof(mbox_sts));
1949
1950 mbox_cmd[0] = MBOX_CMD_SET_PARAM;
1951 if (param == SET_DRVR_VERSION) {
1952 mbox_cmd[1] = SET_DRVR_VERSION;
1953 strncpy((char *)&mbox_cmd[2], QLA4XXX_DRIVER_VERSION,
1954 MAX_DRVR_VER_LEN);
1955 } else {
1956 ql4_printk(KERN_ERR, ha, "%s: invalid parameter 0x%x\n",
1957 __func__, param);
1958 status = QLA_ERROR;
1959 goto exit_set_param;
1960 }
1961
1962 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, mbox_cmd,
1963 mbox_sts);
1964 if (status == QLA_ERROR)
1965 ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",
1966 __func__, mbox_sts[0]);
1967
1968exit_set_param:
1969 return status;
1970}
Nilesh Javali320a61d2012-09-20 07:35:10 -04001971
1972/**
1973 * qla4_83xx_post_idc_ack - post IDC ACK
1974 * @ha: Pointer to host adapter structure.
1975 *
1976 * Posts IDC ACK for IDC Request Notification AEN.
1977 **/
1978int qla4_83xx_post_idc_ack(struct scsi_qla_host *ha)
1979{
1980 uint32_t mbox_cmd[MBOX_REG_COUNT];
1981 uint32_t mbox_sts[MBOX_REG_COUNT];
1982 int status;
1983
1984 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
1985 memset(&mbox_sts, 0, sizeof(mbox_sts));
1986
1987 mbox_cmd[0] = MBOX_CMD_IDC_ACK;
1988 mbox_cmd[1] = ha->idc_info.request_desc;
1989 mbox_cmd[2] = ha->idc_info.info1;
1990 mbox_cmd[3] = ha->idc_info.info2;
1991 mbox_cmd[4] = ha->idc_info.info3;
1992
1993 status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT,
1994 mbox_cmd, mbox_sts);
1995 if (status == QLA_ERROR)
1996 ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__,
1997 mbox_sts[0]);
1998 else
1999 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: IDC ACK posted\n",
2000 __func__));
2001
2002 return status;
2003}