scsi: qla2xxx: Fix system panic due to pointer access problem
[linux-2.6-block.git] / drivers / scsi / qla2xxx / qla_mbx.c
CommitLineData
1da177e4 1/*
fa90c54f 2 * QLogic Fibre Channel HBA Driver
bd21eaf9 3 * Copyright (c) 2003-2014 QLogic Corporation
1da177e4 4 *
fa90c54f 5 * See LICENSE.qla2xxx for copyright and licensing details.
1da177e4
LT
6 */
7#include "qla_def.h"
2d70c103 8#include "qla_target.h"
1da177e4
LT
9
10#include <linux/delay.h>
5a0e3ad6 11#include <linux/gfp.h>
1da177e4 12
15f30a57
QT
13static struct mb_cmd_name {
14 uint16_t cmd;
15 const char *str;
16} mb_str[] = {
17 {MBC_GET_PORT_DATABASE, "GPDB"},
18 {MBC_GET_ID_LIST, "GIDList"},
19 {MBC_GET_LINK_PRIV_STATS, "Stats"},
20};
21
22static const char *mb_to_str(uint16_t cmd)
23{
24 int i;
25 struct mb_cmd_name *e;
26
27 for (i = 0; i < ARRAY_SIZE(mb_str); i++) {
28 e = mb_str + i;
29 if (cmd == e->cmd)
30 return e->str;
31 }
32 return "unknown";
33}
34
ca825828 35static struct rom_cmd {
77ddb94a 36 uint16_t cmd;
37} rom_cmds[] = {
38 { MBC_LOAD_RAM },
39 { MBC_EXECUTE_FIRMWARE },
40 { MBC_READ_RAM_WORD },
41 { MBC_MAILBOX_REGISTER_TEST },
42 { MBC_VERIFY_CHECKSUM },
43 { MBC_GET_FIRMWARE_VERSION },
44 { MBC_LOAD_RISC_RAM },
45 { MBC_DUMP_RISC_RAM },
46 { MBC_LOAD_RISC_RAM_EXTENDED },
47 { MBC_DUMP_RISC_RAM_EXTENDED },
48 { MBC_WRITE_RAM_WORD_EXTENDED },
49 { MBC_READ_RAM_EXTENDED },
50 { MBC_GET_RESOURCE_COUNTS },
51 { MBC_SET_FIRMWARE_OPTION },
52 { MBC_MID_INITIALIZE_FIRMWARE },
53 { MBC_GET_FIRMWARE_STATE },
54 { MBC_GET_MEM_OFFLOAD_CNTRL_STAT },
55 { MBC_GET_RETRY_COUNT },
56 { MBC_TRACE_CONTROL },
b7edfa23 57 { MBC_INITIALIZE_MULTIQ },
77ddb94a 58};
59
60static int is_rom_cmd(uint16_t cmd)
61{
62 int i;
63 struct rom_cmd *wc;
64
65 for (i = 0; i < ARRAY_SIZE(rom_cmds); i++) {
66 wc = rom_cmds + i;
67 if (wc->cmd == cmd)
68 return 1;
69 }
70
71 return 0;
72}
1da177e4
LT
73
74/*
75 * qla2x00_mailbox_command
76 * Issue mailbox command and waits for completion.
77 *
78 * Input:
79 * ha = adapter block pointer.
80 * mcp = driver internal mbx struct pointer.
81 *
82 * Output:
83 * mb[MAX_MAILBOX_REGISTER_COUNT] = returned mailbox data.
84 *
85 * Returns:
86 * 0 : QLA_SUCCESS = cmd performed success
87 * 1 : QLA_FUNCTION_FAILED (error encountered)
88 * 6 : QLA_FUNCTION_TIMEOUT (timeout condition encountered)
89 *
90 * Context:
91 * Kernel context.
92 */
93static int
7b867cf7 94qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
1da177e4 95{
d14e72fb 96 int rval, i;
1da177e4 97 unsigned long flags = 0;
f73cb695 98 device_reg_t *reg;
1c7c6357 99 uint8_t abort_active;
2c3dfe3f 100 uint8_t io_lock_on;
cdbb0a4f 101 uint16_t command = 0;
1da177e4
LT
102 uint16_t *iptr;
103 uint16_t __iomem *optr;
104 uint32_t cnt;
105 uint32_t mboxes;
d14e72fb 106 uint16_t __iomem *mbx_reg;
1da177e4 107 unsigned long wait_time;
7b867cf7
AC
108 struct qla_hw_data *ha = vha->hw;
109 scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
2c3dfe3f 110
d14e72fb 111
5e19ed90 112 ql_dbg(ql_dbg_mbx, vha, 0x1000, "Entered %s.\n", __func__);
7c3df132
SK
113
114 if (ha->pdev->error_state > pci_channel_io_frozen) {
5e19ed90 115 ql_log(ql_log_warn, vha, 0x1001,
7c3df132
SK
116 "error_state is greater than pci_channel_io_frozen, "
117 "exiting.\n");
b9b12f73 118 return QLA_FUNCTION_TIMEOUT;
7c3df132 119 }
b9b12f73 120
a9083016 121 if (vha->device_flags & DFLG_DEV_FAILED) {
5e19ed90 122 ql_log(ql_log_warn, vha, 0x1002,
7c3df132 123 "Device in failed state, exiting.\n");
a9083016
GM
124 return QLA_FUNCTION_TIMEOUT;
125 }
126
c2a5d94f 127 /* if PCI error, then avoid mbx processing.*/
ba175891
SC
128 if (test_bit(PFLG_DISCONNECTED, &base_vha->dpc_flags) &&
129 test_bit(UNLOADING, &base_vha->dpc_flags)) {
83548fe2 130 ql_log(ql_log_warn, vha, 0xd04e,
783e0dc4
SC
131 "PCI error, exiting.\n");
132 return QLA_FUNCTION_TIMEOUT;
c2a5d94f 133 }
783e0dc4 134
2c3dfe3f 135 reg = ha->iobase;
7b867cf7 136 io_lock_on = base_vha->flags.init_done;
1da177e4
LT
137
138 rval = QLA_SUCCESS;
7b867cf7 139 abort_active = test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
1c7c6357 140
1da177e4 141
85880801 142 if (ha->flags.pci_channel_io_perm_failure) {
5e19ed90 143 ql_log(ql_log_warn, vha, 0x1003,
7c3df132 144 "Perm failure on EEH timeout MBX, exiting.\n");
85880801
AV
145 return QLA_FUNCTION_TIMEOUT;
146 }
147
7ec0effd 148 if (IS_P3P_TYPE(ha) && ha->flags.isp82xx_fw_hung) {
862cd01e
GM
149 /* Setting Link-Down error */
150 mcp->mb[0] = MBS_LINK_DOWN_ERROR;
5e19ed90 151 ql_log(ql_log_warn, vha, 0x1004,
7c3df132 152 "FW hung = %d.\n", ha->flags.isp82xx_fw_hung);
1806fcd5 153 return QLA_FUNCTION_TIMEOUT;
862cd01e
GM
154 }
155
77ddb94a 156 /* check if ISP abort is active and return cmd with timeout */
157 if ((test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
158 test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
159 test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) &&
160 !is_rom_cmd(mcp->mb[0])) {
161 ql_log(ql_log_info, vha, 0x1005,
162 "Cmd 0x%x aborted with timeout since ISP Abort is pending\n",
163 mcp->mb[0]);
164 return QLA_FUNCTION_TIMEOUT;
165 }
166
1da177e4 167 /*
1c7c6357
AV
168 * Wait for active mailbox commands to finish by waiting at most tov
169 * seconds. This is to serialize actual issuing of mailbox cmds during
170 * non ISP abort time.
1da177e4 171 */
8eca3f39
AV
172 if (!wait_for_completion_timeout(&ha->mbx_cmd_comp, mcp->tov * HZ)) {
173 /* Timeout occurred. Return error. */
83548fe2 174 ql_log(ql_log_warn, vha, 0xd035,
d8c0d546
CD
175 "Cmd access timeout, cmd=0x%x, Exiting.\n",
176 mcp->mb[0]);
8eca3f39 177 return QLA_FUNCTION_TIMEOUT;
1da177e4
LT
178 }
179
180 ha->flags.mbox_busy = 1;
181 /* Save mailbox command for debug */
182 ha->mcp = mcp;
183
5e19ed90 184 ql_dbg(ql_dbg_mbx, vha, 0x1006,
7c3df132 185 "Prepare to issue mbox cmd=0x%x.\n", mcp->mb[0]);
1da177e4
LT
186
187 spin_lock_irqsave(&ha->hardware_lock, flags);
188
189 /* Load mailbox registers. */
7ec0effd 190 if (IS_P3P_TYPE(ha))
a9083016 191 optr = (uint16_t __iomem *)&reg->isp82.mailbox_in[0];
7ec0effd 192 else if (IS_FWI2_CAPABLE(ha) && !(IS_P3P_TYPE(ha)))
1c7c6357
AV
193 optr = (uint16_t __iomem *)&reg->isp24.mailbox0;
194 else
195 optr = (uint16_t __iomem *)MAILBOX_REG(ha, &reg->isp, 0);
1da177e4
LT
196
197 iptr = mcp->mb;
198 command = mcp->mb[0];
199 mboxes = mcp->out_mb;
200
7b711623 201 ql_dbg(ql_dbg_mbx, vha, 0x1111,
0e31a2c8 202 "Mailbox registers (OUT):\n");
1da177e4
LT
203 for (cnt = 0; cnt < ha->mbx_count; cnt++) {
204 if (IS_QLA2200(ha) && cnt == 8)
1c7c6357
AV
205 optr =
206 (uint16_t __iomem *)MAILBOX_REG(ha, &reg->isp, 8);
0e31a2c8
JC
207 if (mboxes & BIT_0) {
208 ql_dbg(ql_dbg_mbx, vha, 0x1112,
209 "mbox[%d]<-0x%04x\n", cnt, *iptr);
1da177e4 210 WRT_REG_WORD(optr, *iptr);
0e31a2c8 211 }
1da177e4
LT
212
213 mboxes >>= 1;
214 optr++;
215 iptr++;
216 }
217
5e19ed90 218 ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1117,
7c3df132 219 "I/O Address = %p.\n", optr);
1da177e4
LT
220
221 /* Issue set host interrupt command to send cmd out. */
222 ha->flags.mbox_int = 0;
223 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
224
225 /* Unlock mbx registers and wait for interrupt */
5e19ed90 226 ql_dbg(ql_dbg_mbx, vha, 0x100f,
7c3df132
SK
227 "Going to unlock irq & waiting for interrupts. "
228 "jiffies=%lx.\n", jiffies);
1da177e4
LT
229
230 /* Wait for mbx cmd completion until timeout */
231
124f85e6 232 if ((!abort_active && io_lock_on) || IS_NOPOLLING_TYPE(ha)) {
1da177e4
LT
233 set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
234
7ec0effd 235 if (IS_P3P_TYPE(ha)) {
a9083016
GM
236 if (RD_REG_DWORD(&reg->isp82.hint) &
237 HINT_MBX_INT_PENDING) {
238 spin_unlock_irqrestore(&ha->hardware_lock,
239 flags);
8937f2f1 240 ha->flags.mbox_busy = 0;
5e19ed90 241 ql_dbg(ql_dbg_mbx, vha, 0x1010,
7c3df132 242 "Pending mailbox timeout, exiting.\n");
cdbb0a4f
SV
243 rval = QLA_FUNCTION_TIMEOUT;
244 goto premature_exit;
a9083016
GM
245 }
246 WRT_REG_DWORD(&reg->isp82.hint, HINT_MBX_INT_PENDING);
247 } else if (IS_FWI2_CAPABLE(ha))
1c7c6357
AV
248 WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT);
249 else
250 WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
1da177e4
LT
251 spin_unlock_irqrestore(&ha->hardware_lock, flags);
252
77ddb94a 253 wait_time = jiffies;
754d1243
GM
254 if (!wait_for_completion_timeout(&ha->mbx_intr_comp,
255 mcp->tov * HZ)) {
256 ql_dbg(ql_dbg_mbx, vha, 0x117a,
257 "cmd=%x Timeout.\n", command);
258 spin_lock_irqsave(&ha->hardware_lock, flags);
259 clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
260 spin_unlock_irqrestore(&ha->hardware_lock, flags);
261 }
77ddb94a 262 if (time_after(jiffies, wait_time + 5 * HZ))
263 ql_log(ql_log_warn, vha, 0x1015, "cmd=0x%x, waited %d msecs\n",
264 command, jiffies_to_msecs(jiffies - wait_time));
1da177e4 265 } else {
5e19ed90 266 ql_dbg(ql_dbg_mbx, vha, 0x1011,
7c3df132 267 "Cmd=%x Polling Mode.\n", command);
1da177e4 268
7ec0effd 269 if (IS_P3P_TYPE(ha)) {
a9083016
GM
270 if (RD_REG_DWORD(&reg->isp82.hint) &
271 HINT_MBX_INT_PENDING) {
272 spin_unlock_irqrestore(&ha->hardware_lock,
273 flags);
8937f2f1 274 ha->flags.mbox_busy = 0;
5e19ed90 275 ql_dbg(ql_dbg_mbx, vha, 0x1012,
7c3df132 276 "Pending mailbox timeout, exiting.\n");
cdbb0a4f
SV
277 rval = QLA_FUNCTION_TIMEOUT;
278 goto premature_exit;
a9083016
GM
279 }
280 WRT_REG_DWORD(&reg->isp82.hint, HINT_MBX_INT_PENDING);
281 } else if (IS_FWI2_CAPABLE(ha))
1c7c6357
AV
282 WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT);
283 else
284 WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
1da177e4 285 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1da177e4
LT
286
287 wait_time = jiffies + mcp->tov * HZ; /* wait at most tov secs */
288 while (!ha->flags.mbox_int) {
289 if (time_after(jiffies, wait_time))
290 break;
291
292 /* Check for pending interrupts. */
73208dfd 293 qla2x00_poll(ha->rsp_q_map[0]);
1da177e4 294
85880801
AV
295 if (!ha->flags.mbox_int &&
296 !(IS_QLA2200(ha) &&
297 command == MBC_LOAD_RISC_RAM_EXTENDED))
59989831 298 msleep(10);
1da177e4 299 } /* while */
5e19ed90 300 ql_dbg(ql_dbg_mbx, vha, 0x1013,
7c3df132
SK
301 "Waited %d sec.\n",
302 (uint)((jiffies - (wait_time - (mcp->tov * HZ)))/HZ));
1da177e4
LT
303 }
304
1da177e4
LT
305 /* Check whether we timed out */
306 if (ha->flags.mbox_int) {
307 uint16_t *iptr2;
308
5e19ed90 309 ql_dbg(ql_dbg_mbx, vha, 0x1014,
7c3df132 310 "Cmd=%x completed.\n", command);
1da177e4
LT
311
312 /* Got interrupt. Clear the flag. */
313 ha->flags.mbox_int = 0;
314 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
315
7ec0effd 316 if (IS_P3P_TYPE(ha) && ha->flags.isp82xx_fw_hung) {
cdbb0a4f
SV
317 ha->flags.mbox_busy = 0;
318 /* Setting Link-Down error */
319 mcp->mb[0] = MBS_LINK_DOWN_ERROR;
320 ha->mcp = NULL;
321 rval = QLA_FUNCTION_FAILED;
83548fe2 322 ql_log(ql_log_warn, vha, 0xd048,
7c3df132 323 "FW hung = %d.\n", ha->flags.isp82xx_fw_hung);
cdbb0a4f
SV
324 goto premature_exit;
325 }
326
354d6b21 327 if (ha->mailbox_out[0] != MBS_COMMAND_COMPLETE)
1da177e4 328 rval = QLA_FUNCTION_FAILED;
1da177e4
LT
329
330 /* Load return mailbox registers. */
331 iptr2 = mcp->mb;
332 iptr = (uint16_t *)&ha->mailbox_out[0];
333 mboxes = mcp->in_mb;
0e31a2c8
JC
334
335 ql_dbg(ql_dbg_mbx, vha, 0x1113,
336 "Mailbox registers (IN):\n");
1da177e4 337 for (cnt = 0; cnt < ha->mbx_count; cnt++) {
0e31a2c8 338 if (mboxes & BIT_0) {
1da177e4 339 *iptr2 = *iptr;
0e31a2c8
JC
340 ql_dbg(ql_dbg_mbx, vha, 0x1114,
341 "mbox[%d]->0x%04x\n", cnt, *iptr2);
342 }
1da177e4
LT
343
344 mboxes >>= 1;
345 iptr2++;
346 iptr++;
347 }
348 } else {
349
8d3c9c23
QT
350 uint16_t mb[8];
351 uint32_t ictrl, host_status, hccr;
783e0dc4 352 uint16_t w;
1c7c6357 353
e428924c 354 if (IS_FWI2_CAPABLE(ha)) {
8d3c9c23
QT
355 mb[0] = RD_REG_WORD(&reg->isp24.mailbox0);
356 mb[1] = RD_REG_WORD(&reg->isp24.mailbox1);
357 mb[2] = RD_REG_WORD(&reg->isp24.mailbox2);
358 mb[3] = RD_REG_WORD(&reg->isp24.mailbox3);
359 mb[7] = RD_REG_WORD(&reg->isp24.mailbox7);
1c7c6357 360 ictrl = RD_REG_DWORD(&reg->isp24.ictrl);
8d3c9c23
QT
361 host_status = RD_REG_DWORD(&reg->isp24.host_status);
362 hccr = RD_REG_DWORD(&reg->isp24.hccr);
363
83548fe2 364 ql_log(ql_log_warn, vha, 0xd04c,
8d3c9c23
QT
365 "MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx "
366 "mb[0-3]=[0x%x 0x%x 0x%x 0x%x] mb7 0x%x host_status 0x%x hccr 0x%x\n",
367 command, ictrl, jiffies, mb[0], mb[1], mb[2], mb[3],
368 mb[7], host_status, hccr);
369
1c7c6357 370 } else {
8d3c9c23 371 mb[0] = RD_MAILBOX_REG(ha, &reg->isp, 0);
1c7c6357 372 ictrl = RD_REG_WORD(&reg->isp.ictrl);
8d3c9c23
QT
373 ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1119,
374 "MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx "
375 "mb[0]=0x%x\n", command, ictrl, jiffies, mb[0]);
1c7c6357 376 }
5e19ed90 377 ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1019);
1da177e4 378
783e0dc4
SC
379 /* Capture FW dump only, if PCI device active */
380 if (!pci_channel_offline(vha->hw->pdev)) {
381 pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
382 if (w == 0xffff || ictrl == 0xffffffff) {
383 /* This is special case if there is unload
384 * of driver happening and if PCI device go
385 * into bad state due to PCI error condition
386 * then only PCI ERR flag would be set.
387 * we will do premature exit for above case.
388 */
783e0dc4
SC
389 ha->flags.mbox_busy = 0;
390 rval = QLA_FUNCTION_TIMEOUT;
391 goto premature_exit;
392 }
f55bfc88 393
783e0dc4
SC
394 /* Attempt to capture firmware dump for further
395 * anallysis of the current formware state. we do not
396 * need to do this if we are intentionally generating
397 * a dump
398 */
399 if (mcp->mb[0] != MBC_GEN_SYSTEM_ERROR)
400 ha->isp_ops->fw_dump(vha, 0);
401 rval = QLA_FUNCTION_TIMEOUT;
402 }
1da177e4
LT
403 }
404
1da177e4
LT
405 ha->flags.mbox_busy = 0;
406
407 /* Clean up */
408 ha->mcp = NULL;
409
124f85e6 410 if ((abort_active || !io_lock_on) && !IS_NOPOLLING_TYPE(ha)) {
5e19ed90 411 ql_dbg(ql_dbg_mbx, vha, 0x101a,
7c3df132 412 "Checking for additional resp interrupt.\n");
1da177e4
LT
413
414 /* polling mode for non isp_abort commands. */
73208dfd 415 qla2x00_poll(ha->rsp_q_map[0]);
1da177e4
LT
416 }
417
1c7c6357
AV
418 if (rval == QLA_FUNCTION_TIMEOUT &&
419 mcp->mb[0] != MBC_GEN_SYSTEM_ERROR) {
85880801
AV
420 if (!io_lock_on || (mcp->flags & IOCTL_CMD) ||
421 ha->flags.eeh_busy) {
1da177e4 422 /* not in dpc. schedule it for dpc to take over. */
5e19ed90 423 ql_dbg(ql_dbg_mbx, vha, 0x101b,
7c3df132 424 "Timeout, schedule isp_abort_needed.\n");
cdbb0a4f
SV
425
426 if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) &&
427 !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
428 !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
63154916
GM
429 if (IS_QLA82XX(ha)) {
430 ql_dbg(ql_dbg_mbx, vha, 0x112a,
431 "disabling pause transmit on port "
432 "0 & 1.\n");
433 qla82xx_wr_32(ha,
434 QLA82XX_CRB_NIU + 0x98,
435 CRB_NIU_XG_PAUSE_CTL_P0|
436 CRB_NIU_XG_PAUSE_CTL_P1);
437 }
7c3df132 438 ql_log(ql_log_info, base_vha, 0x101c,
24d9ee85 439 "Mailbox cmd timeout occurred, cmd=0x%x, "
d8c0d546
CD
440 "mb[0]=0x%x, eeh_busy=0x%x. Scheduling ISP "
441 "abort.\n", command, mcp->mb[0],
442 ha->flags.eeh_busy);
cdbb0a4f
SV
443 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
444 qla2xxx_wake_dpc(vha);
445 }
1da177e4 446 } else if (!abort_active) {
1da177e4 447 /* call abort directly since we are in the DPC thread */
5e19ed90 448 ql_dbg(ql_dbg_mbx, vha, 0x101d,
7c3df132 449 "Timeout, calling abort_isp.\n");
cdbb0a4f
SV
450
451 if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) &&
452 !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
453 !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
63154916
GM
454 if (IS_QLA82XX(ha)) {
455 ql_dbg(ql_dbg_mbx, vha, 0x112b,
456 "disabling pause transmit on port "
457 "0 & 1.\n");
458 qla82xx_wr_32(ha,
459 QLA82XX_CRB_NIU + 0x98,
460 CRB_NIU_XG_PAUSE_CTL_P0|
461 CRB_NIU_XG_PAUSE_CTL_P1);
462 }
7c3df132 463 ql_log(ql_log_info, base_vha, 0x101e,
24d9ee85 464 "Mailbox cmd timeout occurred, cmd=0x%x, "
d8c0d546
CD
465 "mb[0]=0x%x. Scheduling ISP abort ",
466 command, mcp->mb[0]);
cdbb0a4f
SV
467 set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
468 clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
d3360960
GM
469 /* Allow next mbx cmd to come in. */
470 complete(&ha->mbx_cmd_comp);
cdbb0a4f
SV
471 if (ha->isp_ops->abort_isp(vha)) {
472 /* Failed. retry later. */
473 set_bit(ISP_ABORT_NEEDED,
474 &vha->dpc_flags);
475 }
476 clear_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
5e19ed90 477 ql_dbg(ql_dbg_mbx, vha, 0x101f,
7c3df132 478 "Finished abort_isp.\n");
d3360960 479 goto mbx_done;
1da177e4 480 }
1da177e4
LT
481 }
482 }
483
cdbb0a4f 484premature_exit:
1da177e4 485 /* Allow next mbx cmd to come in. */
8eca3f39 486 complete(&ha->mbx_cmd_comp);
1da177e4 487
d3360960 488mbx_done:
1da177e4 489 if (rval) {
34c5801d 490 ql_dbg(ql_dbg_disc, base_vha, 0x1020,
6246b8a1
GM
491 "**** Failed mbx[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x, cmd=%x ****.\n",
492 mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], command);
d14e72fb 493
75d560e0 494 ql_dbg(ql_dbg_mbx, vha, 0x1198,
d14e72fb
HM
495 "host status: 0x%x, flags:0x%lx, intr ctrl reg:0x%x, intr status:0x%x\n",
496 RD_REG_DWORD(&reg->isp24.host_status),
497 ha->fw_dump_cap_flags,
498 RD_REG_DWORD(&reg->isp24.ictrl),
499 RD_REG_DWORD(&reg->isp24.istatus));
500
501 mbx_reg = &reg->isp24.mailbox0;
502 for (i = 0; i < 6; i++)
75d560e0 503 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1199,
d14e72fb 504 "mbox[%d] 0x%04x\n", i, RD_REG_WORD(mbx_reg++));
1da177e4 505 } else {
7c3df132 506 ql_dbg(ql_dbg_mbx, base_vha, 0x1021, "Done %s.\n", __func__);
1da177e4
LT
507 }
508
1da177e4
LT
509 return rval;
510}
511
1da177e4 512int
7b867cf7 513qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr,
590f98e5 514 uint32_t risc_code_size)
1da177e4
LT
515{
516 int rval;
7b867cf7 517 struct qla_hw_data *ha = vha->hw;
1da177e4
LT
518 mbx_cmd_t mc;
519 mbx_cmd_t *mcp = &mc;
1da177e4 520
5f28d2d7
SK
521 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1022,
522 "Entered %s.\n", __func__);
1da177e4 523
e428924c 524 if (MSW(risc_addr) || IS_FWI2_CAPABLE(ha)) {
590f98e5 525 mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
526 mcp->mb[8] = MSW(risc_addr);
527 mcp->out_mb = MBX_8|MBX_0;
1da177e4 528 } else {
590f98e5 529 mcp->mb[0] = MBC_LOAD_RISC_RAM;
530 mcp->out_mb = MBX_0;
1da177e4 531 }
1da177e4
LT
532 mcp->mb[1] = LSW(risc_addr);
533 mcp->mb[2] = MSW(req_dma);
534 mcp->mb[3] = LSW(req_dma);
1da177e4
LT
535 mcp->mb[6] = MSW(MSD(req_dma));
536 mcp->mb[7] = LSW(MSD(req_dma));
590f98e5 537 mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1;
e428924c 538 if (IS_FWI2_CAPABLE(ha)) {
1c7c6357
AV
539 mcp->mb[4] = MSW(risc_code_size);
540 mcp->mb[5] = LSW(risc_code_size);
541 mcp->out_mb |= MBX_5|MBX_4;
542 } else {
543 mcp->mb[4] = LSW(risc_code_size);
544 mcp->out_mb |= MBX_4;
545 }
546
1da177e4 547 mcp->in_mb = MBX_0;
b93480e3 548 mcp->tov = MBX_TOV_SECONDS;
1da177e4 549 mcp->flags = 0;
7b867cf7 550 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4 551
1da177e4 552 if (rval != QLA_SUCCESS) {
7c3df132
SK
553 ql_dbg(ql_dbg_mbx, vha, 0x1023,
554 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
1da177e4 555 } else {
5f28d2d7
SK
556 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1024,
557 "Done %s.\n", __func__);
1da177e4
LT
558 }
559
560 return rval;
561}
562
cad454b1 563#define EXTENDED_BB_CREDITS BIT_0
e84067d7
DG
564#define NVME_ENABLE_FLAG BIT_3
565
1da177e4
LT
566/*
567 * qla2x00_execute_fw
1c7c6357 568 * Start adapter firmware.
1da177e4
LT
569 *
570 * Input:
1c7c6357
AV
571 * ha = adapter block pointer.
572 * TARGET_QUEUE_LOCK must be released.
573 * ADAPTER_STATE_LOCK must be released.
1da177e4
LT
574 *
575 * Returns:
1c7c6357 576 * qla2x00 local function return status code.
1da177e4
LT
577 *
578 * Context:
1c7c6357 579 * Kernel context.
1da177e4
LT
580 */
581int
7b867cf7 582qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
1da177e4
LT
583{
584 int rval;
7b867cf7 585 struct qla_hw_data *ha = vha->hw;
1da177e4
LT
586 mbx_cmd_t mc;
587 mbx_cmd_t *mcp = &mc;
588
5f28d2d7
SK
589 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1025,
590 "Entered %s.\n", __func__);
1da177e4
LT
591
592 mcp->mb[0] = MBC_EXECUTE_FIRMWARE;
1c7c6357
AV
593 mcp->out_mb = MBX_0;
594 mcp->in_mb = MBX_0;
e428924c 595 if (IS_FWI2_CAPABLE(ha)) {
1c7c6357
AV
596 mcp->mb[1] = MSW(risc_addr);
597 mcp->mb[2] = LSW(risc_addr);
598 mcp->mb[3] = 0;
f73cb695
CD
599 if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
600 IS_QLA27XX(ha)) {
cad454b1
SV
601 struct nvram_81xx *nv = ha->nvram;
602 mcp->mb[4] = (nv->enhanced_features &
603 EXTENDED_BB_CREDITS);
604 } else
605 mcp->mb[4] = 0;
b0d6cabd 606
e84067d7
DG
607 if (ql2xnvmeenable && IS_QLA27XX(ha))
608 mcp->mb[4] |= NVME_ENABLE_FLAG;
609
b0d6cabd
HM
610 if (ha->flags.exlogins_enabled)
611 mcp->mb[4] |= ENABLE_EXTENDED_LOGIN;
612
2f56a7f1
HM
613 if (ha->flags.exchoffld_enabled)
614 mcp->mb[4] |= ENABLE_EXCHANGE_OFFLD;
615
8b3253d1 616 mcp->out_mb |= MBX_4|MBX_3|MBX_2|MBX_1;
1c7c6357
AV
617 mcp->in_mb |= MBX_1;
618 } else {
619 mcp->mb[1] = LSW(risc_addr);
620 mcp->out_mb |= MBX_1;
621 if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
622 mcp->mb[2] = 0;
623 mcp->out_mb |= MBX_2;
624 }
1da177e4
LT
625 }
626
b93480e3 627 mcp->tov = MBX_TOV_SECONDS;
1da177e4 628 mcp->flags = 0;
7b867cf7 629 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4 630
1c7c6357 631 if (rval != QLA_SUCCESS) {
7c3df132
SK
632 ql_dbg(ql_dbg_mbx, vha, 0x1026,
633 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
1c7c6357 634 } else {
e428924c 635 if (IS_FWI2_CAPABLE(ha)) {
5f28d2d7 636 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1027,
7c3df132 637 "Done exchanges=%x.\n", mcp->mb[1]);
1c7c6357 638 } else {
5f28d2d7
SK
639 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1028,
640 "Done %s.\n", __func__);
1c7c6357
AV
641 }
642 }
1da177e4
LT
643
644 return rval;
645}
646
b0d6cabd
HM
647/*
648 * qla_get_exlogin_status
649 * Get extended login status
650 * uses the memory offload control/status Mailbox
651 *
652 * Input:
653 * ha: adapter state pointer.
654 * fwopt: firmware options
655 *
656 * Returns:
657 * qla2x00 local function status
658 *
659 * Context:
660 * Kernel context.
661 */
662#define FETCH_XLOGINS_STAT 0x8
663int
664qla_get_exlogin_status(scsi_qla_host_t *vha, uint16_t *buf_sz,
665 uint16_t *ex_logins_cnt)
666{
667 int rval;
668 mbx_cmd_t mc;
669 mbx_cmd_t *mcp = &mc;
670
671 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118f,
672 "Entered %s\n", __func__);
673
674 memset(mcp->mb, 0 , sizeof(mcp->mb));
675 mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT;
676 mcp->mb[1] = FETCH_XLOGINS_STAT;
677 mcp->out_mb = MBX_1|MBX_0;
678 mcp->in_mb = MBX_10|MBX_4|MBX_0;
679 mcp->tov = MBX_TOV_SECONDS;
680 mcp->flags = 0;
681
682 rval = qla2x00_mailbox_command(vha, mcp);
683 if (rval != QLA_SUCCESS) {
684 ql_dbg(ql_dbg_mbx, vha, 0x1115, "Failed=%x.\n", rval);
685 } else {
686 *buf_sz = mcp->mb[4];
687 *ex_logins_cnt = mcp->mb[10];
688
689 ql_log(ql_log_info, vha, 0x1190,
690 "buffer size 0x%x, exchange login count=%d\n",
691 mcp->mb[4], mcp->mb[10]);
692
693 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1116,
694 "Done %s.\n", __func__);
695 }
696
697 return rval;
698}
699
700/*
701 * qla_set_exlogin_mem_cfg
702 * set extended login memory configuration
703 * Mbx needs to be issues before init_cb is set
704 *
705 * Input:
706 * ha: adapter state pointer.
707 * buffer: buffer pointer
708 * phys_addr: physical address of buffer
709 * size: size of buffer
710 * TARGET_QUEUE_LOCK must be released
711 * ADAPTER_STATE_LOCK must be release
712 *
713 * Returns:
714 * qla2x00 local funxtion status code.
715 *
716 * Context:
717 * Kernel context.
718 */
719#define CONFIG_XLOGINS_MEM 0x3
720int
721qla_set_exlogin_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr)
722{
723 int rval;
724 mbx_cmd_t mc;
725 mbx_cmd_t *mcp = &mc;
726 struct qla_hw_data *ha = vha->hw;
b0d6cabd
HM
727
728 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x111a,
729 "Entered %s.\n", __func__);
730
731 memset(mcp->mb, 0 , sizeof(mcp->mb));
732 mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT;
733 mcp->mb[1] = CONFIG_XLOGINS_MEM;
734 mcp->mb[2] = MSW(phys_addr);
735 mcp->mb[3] = LSW(phys_addr);
736 mcp->mb[6] = MSW(MSD(phys_addr));
737 mcp->mb[7] = LSW(MSD(phys_addr));
738 mcp->mb[8] = MSW(ha->exlogin_size);
739 mcp->mb[9] = LSW(ha->exlogin_size);
740 mcp->out_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
741 mcp->in_mb = MBX_11|MBX_0;
742 mcp->tov = MBX_TOV_SECONDS;
743 mcp->flags = 0;
744 rval = qla2x00_mailbox_command(vha, mcp);
745 if (rval != QLA_SUCCESS) {
746 /*EMPTY*/
747 ql_dbg(ql_dbg_mbx, vha, 0x111b, "Failed=%x.\n", rval);
748 } else {
b0d6cabd
HM
749 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118c,
750 "Done %s.\n", __func__);
751 }
752
753 return rval;
754}
755
2f56a7f1
HM
756/*
757 * qla_get_exchoffld_status
758 * Get exchange offload status
759 * uses the memory offload control/status Mailbox
760 *
761 * Input:
762 * ha: adapter state pointer.
763 * fwopt: firmware options
764 *
765 * Returns:
766 * qla2x00 local function status
767 *
768 * Context:
769 * Kernel context.
770 */
771#define FETCH_XCHOFFLD_STAT 0x2
772int
773qla_get_exchoffld_status(scsi_qla_host_t *vha, uint16_t *buf_sz,
774 uint16_t *ex_logins_cnt)
775{
776 int rval;
777 mbx_cmd_t mc;
778 mbx_cmd_t *mcp = &mc;
779
780 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1019,
781 "Entered %s\n", __func__);
782
783 memset(mcp->mb, 0 , sizeof(mcp->mb));
784 mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT;
785 mcp->mb[1] = FETCH_XCHOFFLD_STAT;
786 mcp->out_mb = MBX_1|MBX_0;
787 mcp->in_mb = MBX_10|MBX_4|MBX_0;
788 mcp->tov = MBX_TOV_SECONDS;
789 mcp->flags = 0;
790
791 rval = qla2x00_mailbox_command(vha, mcp);
792 if (rval != QLA_SUCCESS) {
793 ql_dbg(ql_dbg_mbx, vha, 0x1155, "Failed=%x.\n", rval);
794 } else {
795 *buf_sz = mcp->mb[4];
796 *ex_logins_cnt = mcp->mb[10];
797
798 ql_log(ql_log_info, vha, 0x118e,
799 "buffer size 0x%x, exchange offload count=%d\n",
800 mcp->mb[4], mcp->mb[10]);
801
802 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1156,
803 "Done %s.\n", __func__);
804 }
805
806 return rval;
807}
808
809/*
810 * qla_set_exchoffld_mem_cfg
811 * Set exchange offload memory configuration
812 * Mbx needs to be issues before init_cb is set
813 *
814 * Input:
815 * ha: adapter state pointer.
816 * buffer: buffer pointer
817 * phys_addr: physical address of buffer
818 * size: size of buffer
819 * TARGET_QUEUE_LOCK must be released
820 * ADAPTER_STATE_LOCK must be release
821 *
822 * Returns:
823 * qla2x00 local funxtion status code.
824 *
825 * Context:
826 * Kernel context.
827 */
828#define CONFIG_XCHOFFLD_MEM 0x3
829int
99e1b683 830qla_set_exchoffld_mem_cfg(scsi_qla_host_t *vha)
2f56a7f1
HM
831{
832 int rval;
833 mbx_cmd_t mc;
834 mbx_cmd_t *mcp = &mc;
835 struct qla_hw_data *ha = vha->hw;
836
837 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1157,
838 "Entered %s.\n", __func__);
839
840 memset(mcp->mb, 0 , sizeof(mcp->mb));
841 mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT;
842 mcp->mb[1] = CONFIG_XCHOFFLD_MEM;
99e1b683
QT
843 mcp->mb[2] = MSW(ha->exchoffld_buf_dma);
844 mcp->mb[3] = LSW(ha->exchoffld_buf_dma);
845 mcp->mb[6] = MSW(MSD(ha->exchoffld_buf_dma));
846 mcp->mb[7] = LSW(MSD(ha->exchoffld_buf_dma));
847 mcp->mb[8] = MSW(ha->exchoffld_size);
848 mcp->mb[9] = LSW(ha->exchoffld_size);
2f56a7f1
HM
849 mcp->out_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
850 mcp->in_mb = MBX_11|MBX_0;
851 mcp->tov = MBX_TOV_SECONDS;
852 mcp->flags = 0;
853 rval = qla2x00_mailbox_command(vha, mcp);
854 if (rval != QLA_SUCCESS) {
855 /*EMPTY*/
856 ql_dbg(ql_dbg_mbx, vha, 0x1158, "Failed=%x.\n", rval);
857 } else {
858 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1192,
859 "Done %s.\n", __func__);
860 }
861
862 return rval;
863}
864
1da177e4
LT
865/*
866 * qla2x00_get_fw_version
867 * Get firmware version.
868 *
869 * Input:
870 * ha: adapter state pointer.
871 * major: pointer for major number.
872 * minor: pointer for minor number.
873 * subminor: pointer for subminor number.
874 *
875 * Returns:
876 * qla2x00 local function return status code.
877 *
878 * Context:
879 * Kernel context.
880 */
ca9e9c3e 881int
6246b8a1 882qla2x00_get_fw_version(scsi_qla_host_t *vha)
1da177e4
LT
883{
884 int rval;
885 mbx_cmd_t mc;
886 mbx_cmd_t *mcp = &mc;
6246b8a1 887 struct qla_hw_data *ha = vha->hw;
1da177e4 888
5f28d2d7
SK
889 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1029,
890 "Entered %s.\n", __func__);
1da177e4
LT
891
892 mcp->mb[0] = MBC_GET_FIRMWARE_VERSION;
893 mcp->out_mb = MBX_0;
894 mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
7ec0effd 895 if (IS_QLA81XX(vha->hw) || IS_QLA8031(ha) || IS_QLA8044(ha))
55a96158 896 mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8;
fb0effee 897 if (IS_FWI2_CAPABLE(ha))
6246b8a1 898 mcp->in_mb |= MBX_17|MBX_16|MBX_15;
f73cb695 899 if (IS_QLA27XX(ha))
ad1ef177
JC
900 mcp->in_mb |=
901 MBX_25|MBX_24|MBX_23|MBX_22|MBX_21|MBX_20|MBX_19|MBX_18|
902 MBX_14|MBX_13|MBX_11|MBX_10|MBX_9|MBX_8;
03aa868c 903
1da177e4 904 mcp->flags = 0;
b93480e3 905 mcp->tov = MBX_TOV_SECONDS;
7b867cf7 906 rval = qla2x00_mailbox_command(vha, mcp);
ca9e9c3e
AV
907 if (rval != QLA_SUCCESS)
908 goto failed;
1da177e4
LT
909
910 /* Return mailbox data. */
6246b8a1
GM
911 ha->fw_major_version = mcp->mb[1];
912 ha->fw_minor_version = mcp->mb[2];
913 ha->fw_subminor_version = mcp->mb[3];
914 ha->fw_attributes = mcp->mb[6];
7b867cf7 915 if (IS_QLA2100(vha->hw) || IS_QLA2200(vha->hw))
6246b8a1 916 ha->fw_memory_size = 0x1FFFF; /* Defaults to 128KB. */
1da177e4 917 else
6246b8a1 918 ha->fw_memory_size = (mcp->mb[5] << 16) | mcp->mb[4];
03aa868c 919
7ec0effd 920 if (IS_QLA81XX(vha->hw) || IS_QLA8031(vha->hw) || IS_QLA8044(ha)) {
6246b8a1
GM
921 ha->mpi_version[0] = mcp->mb[10] & 0xff;
922 ha->mpi_version[1] = mcp->mb[11] >> 8;
923 ha->mpi_version[2] = mcp->mb[11] & 0xff;
924 ha->mpi_capabilities = (mcp->mb[12] << 16) | mcp->mb[13];
925 ha->phy_version[0] = mcp->mb[8] & 0xff;
926 ha->phy_version[1] = mcp->mb[9] >> 8;
927 ha->phy_version[2] = mcp->mb[9] & 0xff;
928 }
03aa868c 929
81178772
SK
930 if (IS_FWI2_CAPABLE(ha)) {
931 ha->fw_attributes_h = mcp->mb[15];
932 ha->fw_attributes_ext[0] = mcp->mb[16];
933 ha->fw_attributes_ext[1] = mcp->mb[17];
934 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1139,
935 "%s: FW_attributes Upper: 0x%x, Lower: 0x%x.\n",
936 __func__, mcp->mb[15], mcp->mb[6]);
937 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x112f,
938 "%s: Ext_FwAttributes Upper: 0x%x, Lower: 0x%x.\n",
939 __func__, mcp->mb[17], mcp->mb[16]);
2f56a7f1 940
b0d6cabd
HM
941 if (ha->fw_attributes_h & 0x4)
942 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118d,
943 "%s: Firmware supports Extended Login 0x%x\n",
944 __func__, ha->fw_attributes_h);
2f56a7f1
HM
945
946 if (ha->fw_attributes_h & 0x8)
947 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1191,
948 "%s: Firmware supports Exchange Offload 0x%x\n",
949 __func__, ha->fw_attributes_h);
e84067d7 950
deeae7a6
DG
951 /*
952 * FW supports nvme and driver load parameter requested nvme.
953 * BIT 26 of fw_attributes indicates NVMe support.
954 */
955 if ((ha->fw_attributes_h & 0x400) && ql2xnvmeenable)
e84067d7 956 vha->flags.nvme_enabled = 1;
e84067d7 957
3a03eb79 958 }
03aa868c 959
f73cb695 960 if (IS_QLA27XX(ha)) {
03aa868c
SC
961 ha->mpi_version[0] = mcp->mb[10] & 0xff;
962 ha->mpi_version[1] = mcp->mb[11] >> 8;
963 ha->mpi_version[2] = mcp->mb[11] & 0xff;
964 ha->pep_version[0] = mcp->mb[13] & 0xff;
965 ha->pep_version[1] = mcp->mb[14] >> 8;
966 ha->pep_version[2] = mcp->mb[14] & 0xff;
f73cb695
CD
967 ha->fw_shared_ram_start = (mcp->mb[19] << 16) | mcp->mb[18];
968 ha->fw_shared_ram_end = (mcp->mb[21] << 16) | mcp->mb[20];
ad1ef177
JC
969 ha->fw_ddr_ram_start = (mcp->mb[23] << 16) | mcp->mb[22];
970 ha->fw_ddr_ram_end = (mcp->mb[25] << 16) | mcp->mb[24];
f73cb695 971 }
6246b8a1 972
ca9e9c3e 973failed:
1da177e4
LT
974 if (rval != QLA_SUCCESS) {
975 /*EMPTY*/
7c3df132 976 ql_dbg(ql_dbg_mbx, vha, 0x102a, "Failed=%x.\n", rval);
1da177e4
LT
977 } else {
978 /*EMPTY*/
5f28d2d7
SK
979 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102b,
980 "Done %s.\n", __func__);
1da177e4 981 }
ca9e9c3e 982 return rval;
1da177e4
LT
983}
984
985/*
986 * qla2x00_get_fw_options
987 * Set firmware options.
988 *
989 * Input:
990 * ha = adapter block pointer.
991 * fwopt = pointer for firmware options.
992 *
993 * Returns:
994 * qla2x00 local function return status code.
995 *
996 * Context:
997 * Kernel context.
998 */
999int
7b867cf7 1000qla2x00_get_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts)
1da177e4
LT
1001{
1002 int rval;
1003 mbx_cmd_t mc;
1004 mbx_cmd_t *mcp = &mc;
1005
5f28d2d7
SK
1006 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102c,
1007 "Entered %s.\n", __func__);
1da177e4
LT
1008
1009 mcp->mb[0] = MBC_GET_FIRMWARE_OPTION;
1010 mcp->out_mb = MBX_0;
1011 mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
b93480e3 1012 mcp->tov = MBX_TOV_SECONDS;
1da177e4 1013 mcp->flags = 0;
7b867cf7 1014 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
1015
1016 if (rval != QLA_SUCCESS) {
1017 /*EMPTY*/
7c3df132 1018 ql_dbg(ql_dbg_mbx, vha, 0x102d, "Failed=%x.\n", rval);
1da177e4 1019 } else {
1c7c6357 1020 fwopts[0] = mcp->mb[0];
1da177e4
LT
1021 fwopts[1] = mcp->mb[1];
1022 fwopts[2] = mcp->mb[2];
1023 fwopts[3] = mcp->mb[3];
1024
5f28d2d7
SK
1025 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102e,
1026 "Done %s.\n", __func__);
1da177e4
LT
1027 }
1028
1029 return rval;
1030}
1031
1032
1033/*
1034 * qla2x00_set_fw_options
1035 * Set firmware options.
1036 *
1037 * Input:
1038 * ha = adapter block pointer.
1039 * fwopt = pointer for firmware options.
1040 *
1041 * Returns:
1042 * qla2x00 local function return status code.
1043 *
1044 * Context:
1045 * Kernel context.
1046 */
1047int
7b867cf7 1048qla2x00_set_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts)
1da177e4
LT
1049{
1050 int rval;
1051 mbx_cmd_t mc;
1052 mbx_cmd_t *mcp = &mc;
1053
5f28d2d7
SK
1054 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102f,
1055 "Entered %s.\n", __func__);
1da177e4
LT
1056
1057 mcp->mb[0] = MBC_SET_FIRMWARE_OPTION;
1058 mcp->mb[1] = fwopts[1];
1059 mcp->mb[2] = fwopts[2];
1060 mcp->mb[3] = fwopts[3];
1c7c6357 1061 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
1da177e4 1062 mcp->in_mb = MBX_0;
7b867cf7 1063 if (IS_FWI2_CAPABLE(vha->hw)) {
1c7c6357 1064 mcp->in_mb |= MBX_1;
2da52737
QT
1065 mcp->mb[10] = fwopts[10];
1066 mcp->out_mb |= MBX_10;
1c7c6357
AV
1067 } else {
1068 mcp->mb[10] = fwopts[10];
1069 mcp->mb[11] = fwopts[11];
1070 mcp->mb[12] = 0; /* Undocumented, but used */
1071 mcp->out_mb |= MBX_12|MBX_11|MBX_10;
1072 }
b93480e3 1073 mcp->tov = MBX_TOV_SECONDS;
1da177e4 1074 mcp->flags = 0;
7b867cf7 1075 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4 1076
1c7c6357
AV
1077 fwopts[0] = mcp->mb[0];
1078
1da177e4
LT
1079 if (rval != QLA_SUCCESS) {
1080 /*EMPTY*/
7c3df132
SK
1081 ql_dbg(ql_dbg_mbx, vha, 0x1030,
1082 "Failed=%x (%x/%x).\n", rval, mcp->mb[0], mcp->mb[1]);
1da177e4
LT
1083 } else {
1084 /*EMPTY*/
5f28d2d7
SK
1085 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1031,
1086 "Done %s.\n", __func__);
1da177e4
LT
1087 }
1088
1089 return rval;
1090}
1091
1092/*
1093 * qla2x00_mbx_reg_test
1094 * Mailbox register wrap test.
1095 *
1096 * Input:
1097 * ha = adapter block pointer.
1098 * TARGET_QUEUE_LOCK must be released.
1099 * ADAPTER_STATE_LOCK must be released.
1100 *
1101 * Returns:
1102 * qla2x00 local function return status code.
1103 *
1104 * Context:
1105 * Kernel context.
1106 */
1107int
7b867cf7 1108qla2x00_mbx_reg_test(scsi_qla_host_t *vha)
1da177e4
LT
1109{
1110 int rval;
1111 mbx_cmd_t mc;
1112 mbx_cmd_t *mcp = &mc;
1113
5f28d2d7
SK
1114 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1032,
1115 "Entered %s.\n", __func__);
1da177e4
LT
1116
1117 mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST;
1118 mcp->mb[1] = 0xAAAA;
1119 mcp->mb[2] = 0x5555;
1120 mcp->mb[3] = 0xAA55;
1121 mcp->mb[4] = 0x55AA;
1122 mcp->mb[5] = 0xA5A5;
1123 mcp->mb[6] = 0x5A5A;
1124 mcp->mb[7] = 0x2525;
1125 mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
1126 mcp->in_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
b93480e3 1127 mcp->tov = MBX_TOV_SECONDS;
1da177e4 1128 mcp->flags = 0;
7b867cf7 1129 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
1130
1131 if (rval == QLA_SUCCESS) {
1132 if (mcp->mb[1] != 0xAAAA || mcp->mb[2] != 0x5555 ||
1133 mcp->mb[3] != 0xAA55 || mcp->mb[4] != 0x55AA)
1134 rval = QLA_FUNCTION_FAILED;
1135 if (mcp->mb[5] != 0xA5A5 || mcp->mb[6] != 0x5A5A ||
1136 mcp->mb[7] != 0x2525)
1137 rval = QLA_FUNCTION_FAILED;
1138 }
1139
1140 if (rval != QLA_SUCCESS) {
1141 /*EMPTY*/
7c3df132 1142 ql_dbg(ql_dbg_mbx, vha, 0x1033, "Failed=%x.\n", rval);
1da177e4
LT
1143 } else {
1144 /*EMPTY*/
5f28d2d7
SK
1145 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1034,
1146 "Done %s.\n", __func__);
1da177e4
LT
1147 }
1148
1149 return rval;
1150}
1151
1152/*
1153 * qla2x00_verify_checksum
1154 * Verify firmware checksum.
1155 *
1156 * Input:
1157 * ha = adapter block pointer.
1158 * TARGET_QUEUE_LOCK must be released.
1159 * ADAPTER_STATE_LOCK must be released.
1160 *
1161 * Returns:
1162 * qla2x00 local function return status code.
1163 *
1164 * Context:
1165 * Kernel context.
1166 */
1167int
7b867cf7 1168qla2x00_verify_checksum(scsi_qla_host_t *vha, uint32_t risc_addr)
1da177e4
LT
1169{
1170 int rval;
1171 mbx_cmd_t mc;
1172 mbx_cmd_t *mcp = &mc;
1173
5f28d2d7
SK
1174 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1035,
1175 "Entered %s.\n", __func__);
1da177e4
LT
1176
1177 mcp->mb[0] = MBC_VERIFY_CHECKSUM;
1c7c6357
AV
1178 mcp->out_mb = MBX_0;
1179 mcp->in_mb = MBX_0;
7b867cf7 1180 if (IS_FWI2_CAPABLE(vha->hw)) {
1c7c6357
AV
1181 mcp->mb[1] = MSW(risc_addr);
1182 mcp->mb[2] = LSW(risc_addr);
1183 mcp->out_mb |= MBX_2|MBX_1;
1184 mcp->in_mb |= MBX_2|MBX_1;
1185 } else {
1186 mcp->mb[1] = LSW(risc_addr);
1187 mcp->out_mb |= MBX_1;
1188 mcp->in_mb |= MBX_1;
1189 }
1190
b93480e3 1191 mcp->tov = MBX_TOV_SECONDS;
1da177e4 1192 mcp->flags = 0;
7b867cf7 1193 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
1194
1195 if (rval != QLA_SUCCESS) {
7c3df132
SK
1196 ql_dbg(ql_dbg_mbx, vha, 0x1036,
1197 "Failed=%x chm sum=%x.\n", rval, IS_FWI2_CAPABLE(vha->hw) ?
1198 (mcp->mb[2] << 16) | mcp->mb[1] : mcp->mb[1]);
1da177e4 1199 } else {
5f28d2d7
SK
1200 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1037,
1201 "Done %s.\n", __func__);
1da177e4
LT
1202 }
1203
1204 return rval;
1205}
1206
1207/*
1208 * qla2x00_issue_iocb
1209 * Issue IOCB using mailbox command
1210 *
1211 * Input:
1212 * ha = adapter state pointer.
1213 * buffer = buffer pointer.
1214 * phys_addr = physical address of buffer.
1215 * size = size of buffer.
1216 * TARGET_QUEUE_LOCK must be released.
1217 * ADAPTER_STATE_LOCK must be released.
1218 *
1219 * Returns:
1220 * qla2x00 local function return status code.
1221 *
1222 * Context:
1223 * Kernel context.
1224 */
6e98016c 1225int
7b867cf7 1226qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer,
4d4df193 1227 dma_addr_t phys_addr, size_t size, uint32_t tov)
1da177e4
LT
1228{
1229 int rval;
1230 mbx_cmd_t mc;
1231 mbx_cmd_t *mcp = &mc;
1232
5f28d2d7
SK
1233 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1038,
1234 "Entered %s.\n", __func__);
7c3df132 1235
1da177e4
LT
1236 mcp->mb[0] = MBC_IOCB_COMMAND_A64;
1237 mcp->mb[1] = 0;
1238 mcp->mb[2] = MSW(phys_addr);
1239 mcp->mb[3] = LSW(phys_addr);
1240 mcp->mb[6] = MSW(MSD(phys_addr));
1241 mcp->mb[7] = LSW(MSD(phys_addr));
1242 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
1243 mcp->in_mb = MBX_2|MBX_0;
4d4df193 1244 mcp->tov = tov;
1da177e4 1245 mcp->flags = 0;
7b867cf7 1246 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
1247
1248 if (rval != QLA_SUCCESS) {
1249 /*EMPTY*/
7c3df132 1250 ql_dbg(ql_dbg_mbx, vha, 0x1039, "Failed=%x.\n", rval);
1da177e4 1251 } else {
8c958a99
AV
1252 sts_entry_t *sts_entry = (sts_entry_t *) buffer;
1253
1254 /* Mask reserved bits. */
1255 sts_entry->entry_status &=
7b867cf7 1256 IS_FWI2_CAPABLE(vha->hw) ? RF_MASK_24XX : RF_MASK;
5f28d2d7
SK
1257 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103a,
1258 "Done %s.\n", __func__);
1da177e4
LT
1259 }
1260
1261 return rval;
1262}
1263
4d4df193 1264int
7b867cf7 1265qla2x00_issue_iocb(scsi_qla_host_t *vha, void *buffer, dma_addr_t phys_addr,
4d4df193
HK
1266 size_t size)
1267{
7b867cf7 1268 return qla2x00_issue_iocb_timeout(vha, buffer, phys_addr, size,
4d4df193
HK
1269 MBX_TOV_SECONDS);
1270}
1271
1da177e4
LT
1272/*
1273 * qla2x00_abort_command
1274 * Abort command aborts a specified IOCB.
1275 *
1276 * Input:
1277 * ha = adapter block pointer.
1278 * sp = SB structure pointer.
1279 *
1280 * Returns:
1281 * qla2x00 local function return status code.
1282 *
1283 * Context:
1284 * Kernel context.
1285 */
1286int
2afa19a9 1287qla2x00_abort_command(srb_t *sp)
1da177e4
LT
1288{
1289 unsigned long flags = 0;
1da177e4 1290 int rval;
73208dfd 1291 uint32_t handle = 0;
1da177e4
LT
1292 mbx_cmd_t mc;
1293 mbx_cmd_t *mcp = &mc;
2afa19a9
AC
1294 fc_port_t *fcport = sp->fcport;
1295 scsi_qla_host_t *vha = fcport->vha;
7b867cf7 1296 struct qla_hw_data *ha = vha->hw;
d7459527 1297 struct req_que *req;
9ba56b95 1298 struct scsi_cmnd *cmd = GET_CMD_SP(sp);
1da177e4 1299
5f28d2d7
SK
1300 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103b,
1301 "Entered %s.\n", __func__);
1da177e4 1302
d7459527
MH
1303 if (vha->flags.qpairs_available && sp->qpair)
1304 req = sp->qpair->req;
1305 else
1306 req = vha->req;
1307
c9c5ced9 1308 spin_lock_irqsave(&ha->hardware_lock, flags);
8d93f550 1309 for (handle = 1; handle < req->num_outstanding_cmds; handle++) {
7b867cf7 1310 if (req->outstanding_cmds[handle] == sp)
1da177e4
LT
1311 break;
1312 }
c9c5ced9 1313 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1da177e4 1314
8d93f550 1315 if (handle == req->num_outstanding_cmds) {
1da177e4
LT
1316 /* command not found */
1317 return QLA_FUNCTION_FAILED;
1318 }
1319
1320 mcp->mb[0] = MBC_ABORT_COMMAND;
1321 if (HAS_EXTENDED_IDS(ha))
1322 mcp->mb[1] = fcport->loop_id;
1323 else
1324 mcp->mb[1] = fcport->loop_id << 8;
1325 mcp->mb[2] = (uint16_t)handle;
1326 mcp->mb[3] = (uint16_t)(handle >> 16);
9ba56b95 1327 mcp->mb[6] = (uint16_t)cmd->device->lun;
1da177e4
LT
1328 mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
1329 mcp->in_mb = MBX_0;
b93480e3 1330 mcp->tov = MBX_TOV_SECONDS;
1da177e4 1331 mcp->flags = 0;
7b867cf7 1332 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
1333
1334 if (rval != QLA_SUCCESS) {
7c3df132 1335 ql_dbg(ql_dbg_mbx, vha, 0x103c, "Failed=%x.\n", rval);
1da177e4 1336 } else {
5f28d2d7
SK
1337 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103d,
1338 "Done %s.\n", __func__);
1da177e4
LT
1339 }
1340
1341 return rval;
1342}
1343
1da177e4 1344int
9cb78c16 1345qla2x00_abort_target(struct fc_port *fcport, uint64_t l, int tag)
1da177e4 1346{
523ec773 1347 int rval, rval2;
1da177e4
LT
1348 mbx_cmd_t mc;
1349 mbx_cmd_t *mcp = &mc;
7b867cf7 1350 scsi_qla_host_t *vha;
73208dfd
AC
1351 struct req_que *req;
1352 struct rsp_que *rsp;
1da177e4 1353
523ec773 1354 l = l;
7b867cf7 1355 vha = fcport->vha;
7c3df132 1356
5f28d2d7
SK
1357 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103e,
1358 "Entered %s.\n", __func__);
7c3df132 1359
7e2b895b
GM
1360 req = vha->hw->req_q_map[0];
1361 rsp = req->rsp;
1da177e4 1362 mcp->mb[0] = MBC_ABORT_TARGET;
523ec773 1363 mcp->out_mb = MBX_9|MBX_2|MBX_1|MBX_0;
7b867cf7 1364 if (HAS_EXTENDED_IDS(vha->hw)) {
1da177e4
LT
1365 mcp->mb[1] = fcport->loop_id;
1366 mcp->mb[10] = 0;
1367 mcp->out_mb |= MBX_10;
1368 } else {
1369 mcp->mb[1] = fcport->loop_id << 8;
1370 }
7b867cf7
AC
1371 mcp->mb[2] = vha->hw->loop_reset_delay;
1372 mcp->mb[9] = vha->vp_idx;
1da177e4
LT
1373
1374 mcp->in_mb = MBX_0;
b93480e3 1375 mcp->tov = MBX_TOV_SECONDS;
1da177e4 1376 mcp->flags = 0;
7b867cf7 1377 rval = qla2x00_mailbox_command(vha, mcp);
523ec773 1378 if (rval != QLA_SUCCESS) {
5f28d2d7
SK
1379 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103f,
1380 "Failed=%x.\n", rval);
523ec773
AV
1381 }
1382
1383 /* Issue marker IOCB. */
73208dfd
AC
1384 rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, 0,
1385 MK_SYNC_ID);
523ec773 1386 if (rval2 != QLA_SUCCESS) {
7c3df132
SK
1387 ql_dbg(ql_dbg_mbx, vha, 0x1040,
1388 "Failed to issue marker IOCB (%x).\n", rval2);
523ec773 1389 } else {
5f28d2d7
SK
1390 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1041,
1391 "Done %s.\n", __func__);
523ec773
AV
1392 }
1393
1394 return rval;
1395}
1396
1397int
9cb78c16 1398qla2x00_lun_reset(struct fc_port *fcport, uint64_t l, int tag)
523ec773
AV
1399{
1400 int rval, rval2;
1401 mbx_cmd_t mc;
1402 mbx_cmd_t *mcp = &mc;
7b867cf7 1403 scsi_qla_host_t *vha;
73208dfd
AC
1404 struct req_que *req;
1405 struct rsp_que *rsp;
523ec773 1406
7b867cf7 1407 vha = fcport->vha;
7c3df132 1408
5f28d2d7
SK
1409 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1042,
1410 "Entered %s.\n", __func__);
7c3df132 1411
7e2b895b
GM
1412 req = vha->hw->req_q_map[0];
1413 rsp = req->rsp;
523ec773
AV
1414 mcp->mb[0] = MBC_LUN_RESET;
1415 mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0;
7b867cf7 1416 if (HAS_EXTENDED_IDS(vha->hw))
523ec773
AV
1417 mcp->mb[1] = fcport->loop_id;
1418 else
1419 mcp->mb[1] = fcport->loop_id << 8;
9cb78c16 1420 mcp->mb[2] = (u32)l;
523ec773 1421 mcp->mb[3] = 0;
7b867cf7 1422 mcp->mb[9] = vha->vp_idx;
1da177e4 1423
523ec773 1424 mcp->in_mb = MBX_0;
b93480e3 1425 mcp->tov = MBX_TOV_SECONDS;
523ec773 1426 mcp->flags = 0;
7b867cf7 1427 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4 1428 if (rval != QLA_SUCCESS) {
7c3df132 1429 ql_dbg(ql_dbg_mbx, vha, 0x1043, "Failed=%x.\n", rval);
523ec773
AV
1430 }
1431
1432 /* Issue marker IOCB. */
73208dfd
AC
1433 rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, l,
1434 MK_SYNC_ID_LUN);
523ec773 1435 if (rval2 != QLA_SUCCESS) {
7c3df132
SK
1436 ql_dbg(ql_dbg_mbx, vha, 0x1044,
1437 "Failed to issue marker IOCB (%x).\n", rval2);
1da177e4 1438 } else {
5f28d2d7
SK
1439 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1045,
1440 "Done %s.\n", __func__);
1da177e4
LT
1441 }
1442
1443 return rval;
1444}
1da177e4 1445
1da177e4
LT
1446/*
1447 * qla2x00_get_adapter_id
1448 * Get adapter ID and topology.
1449 *
1450 * Input:
1451 * ha = adapter block pointer.
1452 * id = pointer for loop ID.
1453 * al_pa = pointer for AL_PA.
1454 * area = pointer for area.
1455 * domain = pointer for domain.
1456 * top = pointer for topology.
1457 * TARGET_QUEUE_LOCK must be released.
1458 * ADAPTER_STATE_LOCK must be released.
1459 *
1460 * Returns:
1461 * qla2x00 local function return status code.
1462 *
1463 * Context:
1464 * Kernel context.
1465 */
1466int
7b867cf7 1467qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
2c3dfe3f 1468 uint8_t *area, uint8_t *domain, uint16_t *top, uint16_t *sw_cap)
1da177e4
LT
1469{
1470 int rval;
1471 mbx_cmd_t mc;
1472 mbx_cmd_t *mcp = &mc;
1473
5f28d2d7
SK
1474 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1046,
1475 "Entered %s.\n", __func__);
1da177e4
LT
1476
1477 mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID;
7b867cf7 1478 mcp->mb[9] = vha->vp_idx;
eb66dc60 1479 mcp->out_mb = MBX_9|MBX_0;
2c3dfe3f 1480 mcp->in_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
6246b8a1 1481 if (IS_CNA_CAPABLE(vha->hw))
bad7001c 1482 mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10;
7c9c4766
JC
1483 if (IS_FWI2_CAPABLE(vha->hw))
1484 mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16;
969a6199
SC
1485 if (IS_QLA27XX(vha->hw))
1486 mcp->in_mb |= MBX_15;
b93480e3 1487 mcp->tov = MBX_TOV_SECONDS;
1da177e4 1488 mcp->flags = 0;
7b867cf7 1489 rval = qla2x00_mailbox_command(vha, mcp);
33135aa2
RA
1490 if (mcp->mb[0] == MBS_COMMAND_ERROR)
1491 rval = QLA_COMMAND_ERROR;
42e421b1
AV
1492 else if (mcp->mb[0] == MBS_INVALID_COMMAND)
1493 rval = QLA_INVALID_COMMAND;
1da177e4
LT
1494
1495 /* Return data. */
1496 *id = mcp->mb[1];
1497 *al_pa = LSB(mcp->mb[2]);
1498 *area = MSB(mcp->mb[2]);
1499 *domain = LSB(mcp->mb[3]);
1500 *top = mcp->mb[6];
2c3dfe3f 1501 *sw_cap = mcp->mb[7];
1da177e4
LT
1502
1503 if (rval != QLA_SUCCESS) {
1504 /*EMPTY*/
7c3df132 1505 ql_dbg(ql_dbg_mbx, vha, 0x1047, "Failed=%x.\n", rval);
1da177e4 1506 } else {
5f28d2d7
SK
1507 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1048,
1508 "Done %s.\n", __func__);
bad7001c 1509
6246b8a1 1510 if (IS_CNA_CAPABLE(vha->hw)) {
bad7001c
AV
1511 vha->fcoe_vlan_id = mcp->mb[9] & 0xfff;
1512 vha->fcoe_fcf_idx = mcp->mb[10];
1513 vha->fcoe_vn_port_mac[5] = mcp->mb[11] >> 8;
1514 vha->fcoe_vn_port_mac[4] = mcp->mb[11] & 0xff;
1515 vha->fcoe_vn_port_mac[3] = mcp->mb[12] >> 8;
1516 vha->fcoe_vn_port_mac[2] = mcp->mb[12] & 0xff;
1517 vha->fcoe_vn_port_mac[1] = mcp->mb[13] >> 8;
1518 vha->fcoe_vn_port_mac[0] = mcp->mb[13] & 0xff;
1519 }
7c9c4766 1520 /* If FA-WWN supported */
d6b9b42b
SK
1521 if (IS_FAWWN_CAPABLE(vha->hw)) {
1522 if (mcp->mb[7] & BIT_14) {
1523 vha->port_name[0] = MSB(mcp->mb[16]);
1524 vha->port_name[1] = LSB(mcp->mb[16]);
1525 vha->port_name[2] = MSB(mcp->mb[17]);
1526 vha->port_name[3] = LSB(mcp->mb[17]);
1527 vha->port_name[4] = MSB(mcp->mb[18]);
1528 vha->port_name[5] = LSB(mcp->mb[18]);
1529 vha->port_name[6] = MSB(mcp->mb[19]);
1530 vha->port_name[7] = LSB(mcp->mb[19]);
1531 fc_host_port_name(vha->host) =
1532 wwn_to_u64(vha->port_name);
1533 ql_dbg(ql_dbg_mbx, vha, 0x10ca,
1534 "FA-WWN acquired %016llx\n",
1535 wwn_to_u64(vha->port_name));
1536 }
7c9c4766 1537 }
969a6199
SC
1538
1539 if (IS_QLA27XX(vha->hw))
1540 vha->bbcr = mcp->mb[15];
1da177e4
LT
1541 }
1542
1543 return rval;
1544}
1545
1546/*
1547 * qla2x00_get_retry_cnt
1548 * Get current firmware login retry count and delay.
1549 *
1550 * Input:
1551 * ha = adapter block pointer.
1552 * retry_cnt = pointer to login retry count.
1553 * tov = pointer to login timeout value.
1554 *
1555 * Returns:
1556 * qla2x00 local function return status code.
1557 *
1558 * Context:
1559 * Kernel context.
1560 */
1561int
7b867cf7 1562qla2x00_get_retry_cnt(scsi_qla_host_t *vha, uint8_t *retry_cnt, uint8_t *tov,
1da177e4
LT
1563 uint16_t *r_a_tov)
1564{
1565 int rval;
1566 uint16_t ratov;
1567 mbx_cmd_t mc;
1568 mbx_cmd_t *mcp = &mc;
1569
5f28d2d7
SK
1570 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1049,
1571 "Entered %s.\n", __func__);
1da177e4
LT
1572
1573 mcp->mb[0] = MBC_GET_RETRY_COUNT;
1574 mcp->out_mb = MBX_0;
1575 mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
b93480e3 1576 mcp->tov = MBX_TOV_SECONDS;
1da177e4 1577 mcp->flags = 0;
7b867cf7 1578 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
1579
1580 if (rval != QLA_SUCCESS) {
1581 /*EMPTY*/
7c3df132
SK
1582 ql_dbg(ql_dbg_mbx, vha, 0x104a,
1583 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
1da177e4
LT
1584 } else {
1585 /* Convert returned data and check our values. */
1586 *r_a_tov = mcp->mb[3] / 2;
1587 ratov = (mcp->mb[3]/2) / 10; /* mb[3] value is in 100ms */
1588 if (mcp->mb[1] * ratov > (*retry_cnt) * (*tov)) {
1589 /* Update to the larger values */
1590 *retry_cnt = (uint8_t)mcp->mb[1];
1591 *tov = ratov;
1592 }
1593
5f28d2d7 1594 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104b,
7c3df132 1595 "Done %s mb3=%d ratov=%d.\n", __func__, mcp->mb[3], ratov);
1da177e4
LT
1596 }
1597
1598 return rval;
1599}
1600
1601/*
1602 * qla2x00_init_firmware
1603 * Initialize adapter firmware.
1604 *
1605 * Input:
1606 * ha = adapter block pointer.
1607 * dptr = Initialization control block pointer.
1608 * size = size of initialization control block.
1609 * TARGET_QUEUE_LOCK must be released.
1610 * ADAPTER_STATE_LOCK must be released.
1611 *
1612 * Returns:
1613 * qla2x00 local function return status code.
1614 *
1615 * Context:
1616 * Kernel context.
1617 */
1618int
7b867cf7 1619qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
1da177e4
LT
1620{
1621 int rval;
1622 mbx_cmd_t mc;
1623 mbx_cmd_t *mcp = &mc;
7b867cf7 1624 struct qla_hw_data *ha = vha->hw;
1da177e4 1625
5f28d2d7
SK
1626 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104c,
1627 "Entered %s.\n", __func__);
1da177e4 1628
7ec0effd 1629 if (IS_P3P_TYPE(ha) && ql2xdbwr)
8dfa4b5a 1630 qla82xx_wr_32(ha, (uintptr_t __force)ha->nxdb_wr_ptr,
a9083016
GM
1631 (0x04 | (ha->portnum << 5) | (0 << 8) | (0 << 16)));
1632
e6e074f1 1633 if (ha->flags.npiv_supported)
2c3dfe3f
SJ
1634 mcp->mb[0] = MBC_MID_INITIALIZE_FIRMWARE;
1635 else
1636 mcp->mb[0] = MBC_INITIALIZE_FIRMWARE;
1637
b64b0e8f 1638 mcp->mb[1] = 0;
1da177e4
LT
1639 mcp->mb[2] = MSW(ha->init_cb_dma);
1640 mcp->mb[3] = LSW(ha->init_cb_dma);
1da177e4
LT
1641 mcp->mb[6] = MSW(MSD(ha->init_cb_dma));
1642 mcp->mb[7] = LSW(MSD(ha->init_cb_dma));
b64b0e8f 1643 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
4ef21bd4 1644 if (ha->ex_init_cb && ha->ex_init_cb->ex_version) {
b64b0e8f
AV
1645 mcp->mb[1] = BIT_0;
1646 mcp->mb[10] = MSW(ha->ex_init_cb_dma);
1647 mcp->mb[11] = LSW(ha->ex_init_cb_dma);
1648 mcp->mb[12] = MSW(MSD(ha->ex_init_cb_dma));
1649 mcp->mb[13] = LSW(MSD(ha->ex_init_cb_dma));
1650 mcp->mb[14] = sizeof(*ha->ex_init_cb);
1651 mcp->out_mb |= MBX_14|MBX_13|MBX_12|MBX_11|MBX_10;
1652 }
6246b8a1
GM
1653 /* 1 and 2 should normally be captured. */
1654 mcp->in_mb = MBX_2|MBX_1|MBX_0;
f73cb695 1655 if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
6246b8a1
GM
1656 /* mb3 is additional info about the installed SFP. */
1657 mcp->in_mb |= MBX_3;
1da177e4
LT
1658 mcp->buf_size = size;
1659 mcp->flags = MBX_DMA_OUT;
b93480e3 1660 mcp->tov = MBX_TOV_SECONDS;
7b867cf7 1661 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
1662
1663 if (rval != QLA_SUCCESS) {
1664 /*EMPTY*/
7c3df132 1665 ql_dbg(ql_dbg_mbx, vha, 0x104d,
6246b8a1
GM
1666 "Failed=%x mb[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x,.\n",
1667 rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3]);
1da177e4
LT
1668 } else {
1669 /*EMPTY*/
5f28d2d7
SK
1670 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104e,
1671 "Done %s.\n", __func__);
1da177e4
LT
1672 }
1673
1674 return rval;
1675}
1676
2d70c103 1677
1da177e4
LT
1678/*
1679 * qla2x00_get_port_database
1680 * Issue normal/enhanced get port database mailbox command
1681 * and copy device name as necessary.
1682 *
1683 * Input:
1684 * ha = adapter state pointer.
1685 * dev = structure pointer.
1686 * opt = enhanced cmd option byte.
1687 *
1688 * Returns:
1689 * qla2x00 local function return status code.
1690 *
1691 * Context:
1692 * Kernel context.
1693 */
1694int
7b867cf7 1695qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
1da177e4
LT
1696{
1697 int rval;
1698 mbx_cmd_t mc;
1699 mbx_cmd_t *mcp = &mc;
1700 port_database_t *pd;
1c7c6357 1701 struct port_database_24xx *pd24;
1da177e4 1702 dma_addr_t pd_dma;
7b867cf7 1703 struct qla_hw_data *ha = vha->hw;
1da177e4 1704
5f28d2d7
SK
1705 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104f,
1706 "Entered %s.\n", __func__);
1da177e4 1707
1c7c6357
AV
1708 pd24 = NULL;
1709 pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
1da177e4 1710 if (pd == NULL) {
7c3df132
SK
1711 ql_log(ql_log_warn, vha, 0x1050,
1712 "Failed to allocate port database structure.\n");
1da177e4
LT
1713 return QLA_MEMORY_ALLOC_FAILED;
1714 }
1c7c6357 1715 memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE));
1da177e4 1716
1c7c6357 1717 mcp->mb[0] = MBC_GET_PORT_DATABASE;
e428924c 1718 if (opt != 0 && !IS_FWI2_CAPABLE(ha))
1da177e4 1719 mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE;
1da177e4
LT
1720 mcp->mb[2] = MSW(pd_dma);
1721 mcp->mb[3] = LSW(pd_dma);
1722 mcp->mb[6] = MSW(MSD(pd_dma));
1723 mcp->mb[7] = LSW(MSD(pd_dma));
7b867cf7 1724 mcp->mb[9] = vha->vp_idx;
2c3dfe3f 1725 mcp->out_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
1da177e4 1726 mcp->in_mb = MBX_0;
e428924c 1727 if (IS_FWI2_CAPABLE(ha)) {
1c7c6357
AV
1728 mcp->mb[1] = fcport->loop_id;
1729 mcp->mb[10] = opt;
1730 mcp->out_mb |= MBX_10|MBX_1;
1731 mcp->in_mb |= MBX_1;
1732 } else if (HAS_EXTENDED_IDS(ha)) {
1733 mcp->mb[1] = fcport->loop_id;
1734 mcp->mb[10] = opt;
1735 mcp->out_mb |= MBX_10|MBX_1;
1736 } else {
1737 mcp->mb[1] = fcport->loop_id << 8 | opt;
1738 mcp->out_mb |= MBX_1;
1739 }
e428924c
AV
1740 mcp->buf_size = IS_FWI2_CAPABLE(ha) ?
1741 PORT_DATABASE_24XX_SIZE : PORT_DATABASE_SIZE;
1da177e4
LT
1742 mcp->flags = MBX_DMA_IN;
1743 mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
7b867cf7 1744 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
1745 if (rval != QLA_SUCCESS)
1746 goto gpd_error_out;
1747
e428924c 1748 if (IS_FWI2_CAPABLE(ha)) {
0eba25df 1749 uint64_t zero = 0;
1c7c6357
AV
1750 pd24 = (struct port_database_24xx *) pd;
1751
1752 /* Check for logged in state. */
1753 if (pd24->current_login_state != PDS_PRLI_COMPLETE &&
1754 pd24->last_login_state != PDS_PRLI_COMPLETE) {
7c3df132
SK
1755 ql_dbg(ql_dbg_mbx, vha, 0x1051,
1756 "Unable to verify login-state (%x/%x) for "
1757 "loop_id %x.\n", pd24->current_login_state,
1758 pd24->last_login_state, fcport->loop_id);
1c7c6357
AV
1759 rval = QLA_FUNCTION_FAILED;
1760 goto gpd_error_out;
1761 }
1da177e4 1762
0eba25df
AE
1763 if (fcport->loop_id == FC_NO_LOOP_ID ||
1764 (memcmp(fcport->port_name, (uint8_t *)&zero, 8) &&
1765 memcmp(fcport->port_name, pd24->port_name, 8))) {
1766 /* We lost the device mid way. */
1767 rval = QLA_NOT_LOGGED_IN;
1768 goto gpd_error_out;
1769 }
1770
1c7c6357
AV
1771 /* Names are little-endian. */
1772 memcpy(fcport->node_name, pd24->node_name, WWN_SIZE);
1773 memcpy(fcport->port_name, pd24->port_name, WWN_SIZE);
1774
1775 /* Get port_id of device. */
1776 fcport->d_id.b.domain = pd24->port_id[0];
1777 fcport->d_id.b.area = pd24->port_id[1];
1778 fcport->d_id.b.al_pa = pd24->port_id[2];
1779 fcport->d_id.b.rsvd_1 = 0;
1780
1781 /* If not target must be initiator or unknown type. */
1782 if ((pd24->prli_svc_param_word_3[0] & BIT_4) == 0)
1783 fcport->port_type = FCT_INITIATOR;
1784 else
1785 fcport->port_type = FCT_TARGET;
2d70c103
NB
1786
1787 /* Passback COS information. */
1788 fcport->supported_classes = (pd24->flags & PDF_CLASS_2) ?
1789 FC_COS_CLASS2 : FC_COS_CLASS3;
1790
1791 if (pd24->prli_svc_param_word_3[0] & BIT_7)
1792 fcport->flags |= FCF_CONF_COMP_SUPPORTED;
1c7c6357 1793 } else {
0eba25df
AE
1794 uint64_t zero = 0;
1795
1c7c6357
AV
1796 /* Check for logged in state. */
1797 if (pd->master_state != PD_STATE_PORT_LOGGED_IN &&
1798 pd->slave_state != PD_STATE_PORT_LOGGED_IN) {
7c3df132
SK
1799 ql_dbg(ql_dbg_mbx, vha, 0x100a,
1800 "Unable to verify login-state (%x/%x) - "
1801 "portid=%02x%02x%02x.\n", pd->master_state,
1802 pd->slave_state, fcport->d_id.b.domain,
1803 fcport->d_id.b.area, fcport->d_id.b.al_pa);
1c7c6357
AV
1804 rval = QLA_FUNCTION_FAILED;
1805 goto gpd_error_out;
1806 }
1da177e4 1807
0eba25df
AE
1808 if (fcport->loop_id == FC_NO_LOOP_ID ||
1809 (memcmp(fcport->port_name, (uint8_t *)&zero, 8) &&
1810 memcmp(fcport->port_name, pd->port_name, 8))) {
1811 /* We lost the device mid way. */
1812 rval = QLA_NOT_LOGGED_IN;
1813 goto gpd_error_out;
1814 }
1815
1c7c6357
AV
1816 /* Names are little-endian. */
1817 memcpy(fcport->node_name, pd->node_name, WWN_SIZE);
1818 memcpy(fcport->port_name, pd->port_name, WWN_SIZE);
1819
1820 /* Get port_id of device. */
1821 fcport->d_id.b.domain = pd->port_id[0];
1822 fcport->d_id.b.area = pd->port_id[3];
1823 fcport->d_id.b.al_pa = pd->port_id[2];
1824 fcport->d_id.b.rsvd_1 = 0;
1825
1c7c6357
AV
1826 /* If not target must be initiator or unknown type. */
1827 if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
1828 fcport->port_type = FCT_INITIATOR;
1829 else
1830 fcport->port_type = FCT_TARGET;
ad3e0eda
AV
1831
1832 /* Passback COS information. */
1833 fcport->supported_classes = (pd->options & BIT_4) ?
1834 FC_COS_CLASS2: FC_COS_CLASS3;
1c7c6357 1835 }
1da177e4
LT
1836
1837gpd_error_out:
1838 dma_pool_free(ha->s_dma_pool, pd, pd_dma);
1839
1840 if (rval != QLA_SUCCESS) {
7c3df132
SK
1841 ql_dbg(ql_dbg_mbx, vha, 0x1052,
1842 "Failed=%x mb[0]=%x mb[1]=%x.\n", rval,
1843 mcp->mb[0], mcp->mb[1]);
1da177e4 1844 } else {
5f28d2d7
SK
1845 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1053,
1846 "Done %s.\n", __func__);
1da177e4
LT
1847 }
1848
1849 return rval;
1850}
1851
1852/*
1853 * qla2x00_get_firmware_state
1854 * Get adapter firmware state.
1855 *
1856 * Input:
1857 * ha = adapter block pointer.
1858 * dptr = pointer for firmware state.
1859 * TARGET_QUEUE_LOCK must be released.
1860 * ADAPTER_STATE_LOCK must be released.
1861 *
1862 * Returns:
1863 * qla2x00 local function return status code.
1864 *
1865 * Context:
1866 * Kernel context.
1867 */
1868int
7b867cf7 1869qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states)
1da177e4
LT
1870{
1871 int rval;
1872 mbx_cmd_t mc;
1873 mbx_cmd_t *mcp = &mc;
1874
5f28d2d7
SK
1875 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1054,
1876 "Entered %s.\n", __func__);
1da177e4
LT
1877
1878 mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
1879 mcp->out_mb = MBX_0;
9d2683c0 1880 if (IS_FWI2_CAPABLE(vha->hw))
b5a340dd 1881 mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
9d2683c0
AV
1882 else
1883 mcp->in_mb = MBX_1|MBX_0;
b93480e3 1884 mcp->tov = MBX_TOV_SECONDS;
1da177e4 1885 mcp->flags = 0;
7b867cf7 1886 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4 1887
4d4df193
HK
1888 /* Return firmware states. */
1889 states[0] = mcp->mb[1];
9d2683c0
AV
1890 if (IS_FWI2_CAPABLE(vha->hw)) {
1891 states[1] = mcp->mb[2];
ec891462 1892 states[2] = mcp->mb[3]; /* SFP info */
9d2683c0
AV
1893 states[3] = mcp->mb[4];
1894 states[4] = mcp->mb[5];
b5a340dd 1895 states[5] = mcp->mb[6]; /* DPORT status */
9d2683c0 1896 }
1da177e4
LT
1897
1898 if (rval != QLA_SUCCESS) {
1899 /*EMPTY*/
7c3df132 1900 ql_dbg(ql_dbg_mbx, vha, 0x1055, "Failed=%x.\n", rval);
1da177e4
LT
1901 } else {
1902 /*EMPTY*/
5f28d2d7
SK
1903 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1056,
1904 "Done %s.\n", __func__);
1da177e4
LT
1905 }
1906
1907 return rval;
1908}
1909
1910/*
1911 * qla2x00_get_port_name
1912 * Issue get port name mailbox command.
1913 * Returned name is in big endian format.
1914 *
1915 * Input:
1916 * ha = adapter block pointer.
1917 * loop_id = loop ID of device.
1918 * name = pointer for name.
1919 * TARGET_QUEUE_LOCK must be released.
1920 * ADAPTER_STATE_LOCK must be released.
1921 *
1922 * Returns:
1923 * qla2x00 local function return status code.
1924 *
1925 * Context:
1926 * Kernel context.
1927 */
1928int
7b867cf7 1929qla2x00_get_port_name(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t *name,
1da177e4
LT
1930 uint8_t opt)
1931{
1932 int rval;
1933 mbx_cmd_t mc;
1934 mbx_cmd_t *mcp = &mc;
1935
5f28d2d7
SK
1936 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1057,
1937 "Entered %s.\n", __func__);
1da177e4
LT
1938
1939 mcp->mb[0] = MBC_GET_PORT_NAME;
7b867cf7 1940 mcp->mb[9] = vha->vp_idx;
2c3dfe3f 1941 mcp->out_mb = MBX_9|MBX_1|MBX_0;
7b867cf7 1942 if (HAS_EXTENDED_IDS(vha->hw)) {
1da177e4
LT
1943 mcp->mb[1] = loop_id;
1944 mcp->mb[10] = opt;
1945 mcp->out_mb |= MBX_10;
1946 } else {
1947 mcp->mb[1] = loop_id << 8 | opt;
1948 }
1949
1950 mcp->in_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
b93480e3 1951 mcp->tov = MBX_TOV_SECONDS;
1da177e4 1952 mcp->flags = 0;
7b867cf7 1953 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
1954
1955 if (rval != QLA_SUCCESS) {
1956 /*EMPTY*/
7c3df132 1957 ql_dbg(ql_dbg_mbx, vha, 0x1058, "Failed=%x.\n", rval);
1da177e4
LT
1958 } else {
1959 if (name != NULL) {
1960 /* This function returns name in big endian. */
1196ae02
RL
1961 name[0] = MSB(mcp->mb[2]);
1962 name[1] = LSB(mcp->mb[2]);
1963 name[2] = MSB(mcp->mb[3]);
1964 name[3] = LSB(mcp->mb[3]);
1965 name[4] = MSB(mcp->mb[6]);
1966 name[5] = LSB(mcp->mb[6]);
1967 name[6] = MSB(mcp->mb[7]);
1968 name[7] = LSB(mcp->mb[7]);
1da177e4
LT
1969 }
1970
5f28d2d7
SK
1971 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1059,
1972 "Done %s.\n", __func__);
1da177e4
LT
1973 }
1974
1975 return rval;
1976}
1977
61e1b269
JC
1978/*
1979 * qla24xx_link_initialization
1980 * Issue link initialization mailbox command.
1981 *
1982 * Input:
1983 * ha = adapter block pointer.
1984 * TARGET_QUEUE_LOCK must be released.
1985 * ADAPTER_STATE_LOCK must be released.
1986 *
1987 * Returns:
1988 * qla2x00 local function return status code.
1989 *
1990 * Context:
1991 * Kernel context.
1992 */
1993int
1994qla24xx_link_initialize(scsi_qla_host_t *vha)
1995{
1996 int rval;
1997 mbx_cmd_t mc;
1998 mbx_cmd_t *mcp = &mc;
1999
2000 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1152,
2001 "Entered %s.\n", __func__);
2002
2003 if (!IS_FWI2_CAPABLE(vha->hw) || IS_CNA_CAPABLE(vha->hw))
2004 return QLA_FUNCTION_FAILED;
2005
2006 mcp->mb[0] = MBC_LINK_INITIALIZATION;
5a5c27b6
JC
2007 mcp->mb[1] = BIT_4;
2008 if (vha->hw->operating_mode == LOOP)
2009 mcp->mb[1] |= BIT_6;
2010 else
2011 mcp->mb[1] |= BIT_5;
61e1b269
JC
2012 mcp->mb[2] = 0;
2013 mcp->mb[3] = 0;
2014 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2015 mcp->in_mb = MBX_0;
2016 mcp->tov = MBX_TOV_SECONDS;
2017 mcp->flags = 0;
2018 rval = qla2x00_mailbox_command(vha, mcp);
2019
2020 if (rval != QLA_SUCCESS) {
2021 ql_dbg(ql_dbg_mbx, vha, 0x1153, "Failed=%x.\n", rval);
2022 } else {
2023 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1154,
2024 "Done %s.\n", __func__);
2025 }
2026
2027 return rval;
2028}
2029
1da177e4
LT
2030/*
2031 * qla2x00_lip_reset
2032 * Issue LIP reset mailbox command.
2033 *
2034 * Input:
2035 * ha = adapter block pointer.
2036 * TARGET_QUEUE_LOCK must be released.
2037 * ADAPTER_STATE_LOCK must be released.
2038 *
2039 * Returns:
2040 * qla2x00 local function return status code.
2041 *
2042 * Context:
2043 * Kernel context.
2044 */
2045int
7b867cf7 2046qla2x00_lip_reset(scsi_qla_host_t *vha)
1da177e4
LT
2047{
2048 int rval;
2049 mbx_cmd_t mc;
2050 mbx_cmd_t *mcp = &mc;
2051
5f28d2d7
SK
2052 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105a,
2053 "Entered %s.\n", __func__);
1da177e4 2054
6246b8a1 2055 if (IS_CNA_CAPABLE(vha->hw)) {
3a03eb79
AV
2056 /* Logout across all FCFs. */
2057 mcp->mb[0] = MBC_LIP_FULL_LOGIN;
2058 mcp->mb[1] = BIT_1;
2059 mcp->mb[2] = 0;
2060 mcp->out_mb = MBX_2|MBX_1|MBX_0;
2061 } else if (IS_FWI2_CAPABLE(vha->hw)) {
1c7c6357 2062 mcp->mb[0] = MBC_LIP_FULL_LOGIN;
0c8c39af
AV
2063 mcp->mb[1] = BIT_6;
2064 mcp->mb[2] = 0;
7b867cf7 2065 mcp->mb[3] = vha->hw->loop_reset_delay;
1c7c6357 2066 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
1da177e4 2067 } else {
1c7c6357
AV
2068 mcp->mb[0] = MBC_LIP_RESET;
2069 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
7b867cf7 2070 if (HAS_EXTENDED_IDS(vha->hw)) {
1c7c6357
AV
2071 mcp->mb[1] = 0x00ff;
2072 mcp->mb[10] = 0;
2073 mcp->out_mb |= MBX_10;
2074 } else {
2075 mcp->mb[1] = 0xff00;
2076 }
7b867cf7 2077 mcp->mb[2] = vha->hw->loop_reset_delay;
1c7c6357 2078 mcp->mb[3] = 0;
1da177e4 2079 }
1da177e4 2080 mcp->in_mb = MBX_0;
b93480e3 2081 mcp->tov = MBX_TOV_SECONDS;
1da177e4 2082 mcp->flags = 0;
7b867cf7 2083 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
2084
2085 if (rval != QLA_SUCCESS) {
2086 /*EMPTY*/
7c3df132 2087 ql_dbg(ql_dbg_mbx, vha, 0x105b, "Failed=%x.\n", rval);
1da177e4
LT
2088 } else {
2089 /*EMPTY*/
5f28d2d7
SK
2090 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105c,
2091 "Done %s.\n", __func__);
1da177e4
LT
2092 }
2093
2094 return rval;
2095}
2096
2097/*
2098 * qla2x00_send_sns
2099 * Send SNS command.
2100 *
2101 * Input:
2102 * ha = adapter block pointer.
2103 * sns = pointer for command.
2104 * cmd_size = command size.
2105 * buf_size = response/command size.
2106 * TARGET_QUEUE_LOCK must be released.
2107 * ADAPTER_STATE_LOCK must be released.
2108 *
2109 * Returns:
2110 * qla2x00 local function return status code.
2111 *
2112 * Context:
2113 * Kernel context.
2114 */
2115int
7b867cf7 2116qla2x00_send_sns(scsi_qla_host_t *vha, dma_addr_t sns_phys_address,
1da177e4
LT
2117 uint16_t cmd_size, size_t buf_size)
2118{
2119 int rval;
2120 mbx_cmd_t mc;
2121 mbx_cmd_t *mcp = &mc;
2122
5f28d2d7
SK
2123 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105d,
2124 "Entered %s.\n", __func__);
1da177e4 2125
5f28d2d7 2126 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105e,
7c3df132
SK
2127 "Retry cnt=%d ratov=%d total tov=%d.\n",
2128 vha->hw->retry_count, vha->hw->login_timeout, mcp->tov);
1da177e4
LT
2129
2130 mcp->mb[0] = MBC_SEND_SNS_COMMAND;
2131 mcp->mb[1] = cmd_size;
2132 mcp->mb[2] = MSW(sns_phys_address);
2133 mcp->mb[3] = LSW(sns_phys_address);
2134 mcp->mb[6] = MSW(MSD(sns_phys_address));
2135 mcp->mb[7] = LSW(MSD(sns_phys_address));
2136 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2137 mcp->in_mb = MBX_0|MBX_1;
2138 mcp->buf_size = buf_size;
2139 mcp->flags = MBX_DMA_OUT|MBX_DMA_IN;
7b867cf7
AC
2140 mcp->tov = (vha->hw->login_timeout * 2) + (vha->hw->login_timeout / 2);
2141 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
2142
2143 if (rval != QLA_SUCCESS) {
2144 /*EMPTY*/
7c3df132
SK
2145 ql_dbg(ql_dbg_mbx, vha, 0x105f,
2146 "Failed=%x mb[0]=%x mb[1]=%x.\n",
2147 rval, mcp->mb[0], mcp->mb[1]);
1da177e4
LT
2148 } else {
2149 /*EMPTY*/
5f28d2d7
SK
2150 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1060,
2151 "Done %s.\n", __func__);
1da177e4
LT
2152 }
2153
2154 return rval;
2155}
2156
1c7c6357 2157int
7b867cf7 2158qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
1c7c6357
AV
2159 uint8_t area, uint8_t al_pa, uint16_t *mb, uint8_t opt)
2160{
2161 int rval;
2162
2163 struct logio_entry_24xx *lg;
2164 dma_addr_t lg_dma;
2165 uint32_t iop[2];
7b867cf7 2166 struct qla_hw_data *ha = vha->hw;
2afa19a9 2167 struct req_que *req;
1c7c6357 2168
5f28d2d7
SK
2169 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1061,
2170 "Entered %s.\n", __func__);
1c7c6357 2171
d7459527
MH
2172 if (vha->vp_idx && vha->qpair)
2173 req = vha->qpair->req;
68ca949c 2174 else
d7459527 2175 req = ha->req_q_map[0];
2afa19a9 2176
1c7c6357
AV
2177 lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
2178 if (lg == NULL) {
7c3df132
SK
2179 ql_log(ql_log_warn, vha, 0x1062,
2180 "Failed to allocate login IOCB.\n");
1c7c6357
AV
2181 return QLA_MEMORY_ALLOC_FAILED;
2182 }
2183 memset(lg, 0, sizeof(struct logio_entry_24xx));
2184
2185 lg->entry_type = LOGINOUT_PORT_IOCB_TYPE;
2186 lg->entry_count = 1;
2afa19a9 2187 lg->handle = MAKE_HANDLE(req->id, lg->handle);
1c7c6357 2188 lg->nport_handle = cpu_to_le16(loop_id);
ad950360 2189 lg->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI);
1c7c6357 2190 if (opt & BIT_0)
ad950360 2191 lg->control_flags |= cpu_to_le16(LCF_COND_PLOGI);
8baa51a6 2192 if (opt & BIT_1)
ad950360 2193 lg->control_flags |= cpu_to_le16(LCF_SKIP_PRLI);
1c7c6357
AV
2194 lg->port_id[0] = al_pa;
2195 lg->port_id[1] = area;
2196 lg->port_id[2] = domain;
7b867cf7 2197 lg->vp_index = vha->vp_idx;
7f45dd0b
AV
2198 rval = qla2x00_issue_iocb_timeout(vha, lg, lg_dma, 0,
2199 (ha->r_a_tov / 10 * 2) + 2);
1c7c6357 2200 if (rval != QLA_SUCCESS) {
7c3df132
SK
2201 ql_dbg(ql_dbg_mbx, vha, 0x1063,
2202 "Failed to issue login IOCB (%x).\n", rval);
1c7c6357 2203 } else if (lg->entry_status != 0) {
7c3df132
SK
2204 ql_dbg(ql_dbg_mbx, vha, 0x1064,
2205 "Failed to complete IOCB -- error status (%x).\n",
2206 lg->entry_status);
1c7c6357 2207 rval = QLA_FUNCTION_FAILED;
ad950360 2208 } else if (lg->comp_status != cpu_to_le16(CS_COMPLETE)) {
1c7c6357
AV
2209 iop[0] = le32_to_cpu(lg->io_parameter[0]);
2210 iop[1] = le32_to_cpu(lg->io_parameter[1]);
2211
7c3df132
SK
2212 ql_dbg(ql_dbg_mbx, vha, 0x1065,
2213 "Failed to complete IOCB -- completion status (%x) "
2214 "ioparam=%x/%x.\n", le16_to_cpu(lg->comp_status),
2215 iop[0], iop[1]);
1c7c6357
AV
2216
2217 switch (iop[0]) {
2218 case LSC_SCODE_PORTID_USED:
2219 mb[0] = MBS_PORT_ID_USED;
2220 mb[1] = LSW(iop[1]);
2221 break;
2222 case LSC_SCODE_NPORT_USED:
2223 mb[0] = MBS_LOOP_ID_USED;
2224 break;
2225 case LSC_SCODE_NOLINK:
2226 case LSC_SCODE_NOIOCB:
2227 case LSC_SCODE_NOXCB:
2228 case LSC_SCODE_CMD_FAILED:
2229 case LSC_SCODE_NOFABRIC:
2230 case LSC_SCODE_FW_NOT_READY:
2231 case LSC_SCODE_NOT_LOGGED_IN:
2232 case LSC_SCODE_NOPCB:
2233 case LSC_SCODE_ELS_REJECT:
2234 case LSC_SCODE_CMD_PARAM_ERR:
2235 case LSC_SCODE_NONPORT:
2236 case LSC_SCODE_LOGGED_IN:
2237 case LSC_SCODE_NOFLOGI_ACC:
2238 default:
2239 mb[0] = MBS_COMMAND_ERROR;
2240 break;
2241 }
2242 } else {
5f28d2d7
SK
2243 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1066,
2244 "Done %s.\n", __func__);
1c7c6357
AV
2245
2246 iop[0] = le32_to_cpu(lg->io_parameter[0]);
2247
2248 mb[0] = MBS_COMMAND_COMPLETE;
2249 mb[1] = 0;
2250 if (iop[0] & BIT_4) {
2251 if (iop[0] & BIT_8)
2252 mb[1] |= BIT_1;
2253 } else
2254 mb[1] = BIT_0;
ad3e0eda
AV
2255
2256 /* Passback COS information. */
2257 mb[10] = 0;
2258 if (lg->io_parameter[7] || lg->io_parameter[8])
2259 mb[10] |= BIT_0; /* Class 2. */
2260 if (lg->io_parameter[9] || lg->io_parameter[10])
2261 mb[10] |= BIT_1; /* Class 3. */
ad950360 2262 if (lg->io_parameter[0] & cpu_to_le32(BIT_7))
2d70c103
NB
2263 mb[10] |= BIT_7; /* Confirmed Completion
2264 * Allowed
2265 */
1c7c6357
AV
2266 }
2267
2268 dma_pool_free(ha->s_dma_pool, lg, lg_dma);
2269
2270 return rval;
2271}
2272
1da177e4
LT
2273/*
2274 * qla2x00_login_fabric
2275 * Issue login fabric port mailbox command.
2276 *
2277 * Input:
2278 * ha = adapter block pointer.
2279 * loop_id = device loop ID.
2280 * domain = device domain.
2281 * area = device area.
2282 * al_pa = device AL_PA.
2283 * status = pointer for return status.
2284 * opt = command options.
2285 * TARGET_QUEUE_LOCK must be released.
2286 * ADAPTER_STATE_LOCK must be released.
2287 *
2288 * Returns:
2289 * qla2x00 local function return status code.
2290 *
2291 * Context:
2292 * Kernel context.
2293 */
2294int
7b867cf7 2295qla2x00_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
1da177e4
LT
2296 uint8_t area, uint8_t al_pa, uint16_t *mb, uint8_t opt)
2297{
2298 int rval;
2299 mbx_cmd_t mc;
2300 mbx_cmd_t *mcp = &mc;
7b867cf7 2301 struct qla_hw_data *ha = vha->hw;
1da177e4 2302
5f28d2d7
SK
2303 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1067,
2304 "Entered %s.\n", __func__);
1da177e4
LT
2305
2306 mcp->mb[0] = MBC_LOGIN_FABRIC_PORT;
2307 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2308 if (HAS_EXTENDED_IDS(ha)) {
2309 mcp->mb[1] = loop_id;
2310 mcp->mb[10] = opt;
2311 mcp->out_mb |= MBX_10;
2312 } else {
2313 mcp->mb[1] = (loop_id << 8) | opt;
2314 }
2315 mcp->mb[2] = domain;
2316 mcp->mb[3] = area << 8 | al_pa;
2317
2318 mcp->in_mb = MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
2319 mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
2320 mcp->flags = 0;
7b867cf7 2321 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
2322
2323 /* Return mailbox statuses. */
2324 if (mb != NULL) {
2325 mb[0] = mcp->mb[0];
2326 mb[1] = mcp->mb[1];
2327 mb[2] = mcp->mb[2];
2328 mb[6] = mcp->mb[6];
2329 mb[7] = mcp->mb[7];
ad3e0eda
AV
2330 /* COS retrieved from Get-Port-Database mailbox command. */
2331 mb[10] = 0;
1da177e4
LT
2332 }
2333
2334 if (rval != QLA_SUCCESS) {
2335 /* RLU tmp code: need to change main mailbox_command function to
2336 * return ok even when the mailbox completion value is not
2337 * SUCCESS. The caller needs to be responsible to interpret
2338 * the return values of this mailbox command if we're not
2339 * to change too much of the existing code.
2340 */
2341 if (mcp->mb[0] == 0x4001 || mcp->mb[0] == 0x4002 ||
2342 mcp->mb[0] == 0x4003 || mcp->mb[0] == 0x4005 ||
2343 mcp->mb[0] == 0x4006)
2344 rval = QLA_SUCCESS;
2345
2346 /*EMPTY*/
7c3df132
SK
2347 ql_dbg(ql_dbg_mbx, vha, 0x1068,
2348 "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
2349 rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
1da177e4
LT
2350 } else {
2351 /*EMPTY*/
5f28d2d7
SK
2352 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1069,
2353 "Done %s.\n", __func__);
1da177e4
LT
2354 }
2355
2356 return rval;
2357}
2358
2359/*
2360 * qla2x00_login_local_device
2361 * Issue login loop port mailbox command.
fa2a1ce5 2362 *
1da177e4
LT
2363 * Input:
2364 * ha = adapter block pointer.
2365 * loop_id = device loop ID.
2366 * opt = command options.
fa2a1ce5 2367 *
1da177e4
LT
2368 * Returns:
2369 * Return status code.
fa2a1ce5 2370 *
1da177e4
LT
2371 * Context:
2372 * Kernel context.
fa2a1ce5 2373 *
1da177e4
LT
2374 */
2375int
7b867cf7 2376qla2x00_login_local_device(scsi_qla_host_t *vha, fc_port_t *fcport,
1da177e4
LT
2377 uint16_t *mb_ret, uint8_t opt)
2378{
2379 int rval;
2380 mbx_cmd_t mc;
2381 mbx_cmd_t *mcp = &mc;
7b867cf7 2382 struct qla_hw_data *ha = vha->hw;
1da177e4 2383
5f28d2d7
SK
2384 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106a,
2385 "Entered %s.\n", __func__);
7c3df132 2386
e428924c 2387 if (IS_FWI2_CAPABLE(ha))
7b867cf7 2388 return qla24xx_login_fabric(vha, fcport->loop_id,
9a52a57c 2389 fcport->d_id.b.domain, fcport->d_id.b.area,
2390 fcport->d_id.b.al_pa, mb_ret, opt);
2391
1da177e4
LT
2392 mcp->mb[0] = MBC_LOGIN_LOOP_PORT;
2393 if (HAS_EXTENDED_IDS(ha))
9a52a57c 2394 mcp->mb[1] = fcport->loop_id;
1da177e4 2395 else
9a52a57c 2396 mcp->mb[1] = fcport->loop_id << 8;
1da177e4
LT
2397 mcp->mb[2] = opt;
2398 mcp->out_mb = MBX_2|MBX_1|MBX_0;
2399 mcp->in_mb = MBX_7|MBX_6|MBX_1|MBX_0;
2400 mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
2401 mcp->flags = 0;
7b867cf7 2402 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
2403
2404 /* Return mailbox statuses. */
2405 if (mb_ret != NULL) {
2406 mb_ret[0] = mcp->mb[0];
2407 mb_ret[1] = mcp->mb[1];
2408 mb_ret[6] = mcp->mb[6];
2409 mb_ret[7] = mcp->mb[7];
2410 }
2411
2412 if (rval != QLA_SUCCESS) {
2413 /* AV tmp code: need to change main mailbox_command function to
2414 * return ok even when the mailbox completion value is not
2415 * SUCCESS. The caller needs to be responsible to interpret
2416 * the return values of this mailbox command if we're not
2417 * to change too much of the existing code.
2418 */
2419 if (mcp->mb[0] == 0x4005 || mcp->mb[0] == 0x4006)
2420 rval = QLA_SUCCESS;
2421
7c3df132
SK
2422 ql_dbg(ql_dbg_mbx, vha, 0x106b,
2423 "Failed=%x mb[0]=%x mb[1]=%x mb[6]=%x mb[7]=%x.\n",
2424 rval, mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]);
1da177e4
LT
2425 } else {
2426 /*EMPTY*/
5f28d2d7
SK
2427 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106c,
2428 "Done %s.\n", __func__);
1da177e4
LT
2429 }
2430
2431 return (rval);
2432}
2433
1c7c6357 2434int
7b867cf7 2435qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
1c7c6357
AV
2436 uint8_t area, uint8_t al_pa)
2437{
2438 int rval;
2439 struct logio_entry_24xx *lg;
2440 dma_addr_t lg_dma;
7b867cf7 2441 struct qla_hw_data *ha = vha->hw;
2afa19a9 2442 struct req_que *req;
1c7c6357 2443
5f28d2d7
SK
2444 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106d,
2445 "Entered %s.\n", __func__);
1c7c6357
AV
2446
2447 lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
2448 if (lg == NULL) {
7c3df132
SK
2449 ql_log(ql_log_warn, vha, 0x106e,
2450 "Failed to allocate logout IOCB.\n");
1c7c6357
AV
2451 return QLA_MEMORY_ALLOC_FAILED;
2452 }
2453 memset(lg, 0, sizeof(struct logio_entry_24xx));
2454
d7459527 2455 req = vha->req;
1c7c6357
AV
2456 lg->entry_type = LOGINOUT_PORT_IOCB_TYPE;
2457 lg->entry_count = 1;
2afa19a9 2458 lg->handle = MAKE_HANDLE(req->id, lg->handle);
1c7c6357
AV
2459 lg->nport_handle = cpu_to_le16(loop_id);
2460 lg->control_flags =
ad950360 2461 cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO|
c8d6691b 2462 LCF_FREE_NPORT);
1c7c6357
AV
2463 lg->port_id[0] = al_pa;
2464 lg->port_id[1] = area;
2465 lg->port_id[2] = domain;
7b867cf7 2466 lg->vp_index = vha->vp_idx;
7f45dd0b
AV
2467 rval = qla2x00_issue_iocb_timeout(vha, lg, lg_dma, 0,
2468 (ha->r_a_tov / 10 * 2) + 2);
1c7c6357 2469 if (rval != QLA_SUCCESS) {
7c3df132
SK
2470 ql_dbg(ql_dbg_mbx, vha, 0x106f,
2471 "Failed to issue logout IOCB (%x).\n", rval);
1c7c6357 2472 } else if (lg->entry_status != 0) {
7c3df132
SK
2473 ql_dbg(ql_dbg_mbx, vha, 0x1070,
2474 "Failed to complete IOCB -- error status (%x).\n",
2475 lg->entry_status);
1c7c6357 2476 rval = QLA_FUNCTION_FAILED;
ad950360 2477 } else if (lg->comp_status != cpu_to_le16(CS_COMPLETE)) {
7c3df132
SK
2478 ql_dbg(ql_dbg_mbx, vha, 0x1071,
2479 "Failed to complete IOCB -- completion status (%x) "
2480 "ioparam=%x/%x.\n", le16_to_cpu(lg->comp_status),
1c7c6357 2481 le32_to_cpu(lg->io_parameter[0]),
7c3df132 2482 le32_to_cpu(lg->io_parameter[1]));
1c7c6357
AV
2483 } else {
2484 /*EMPTY*/
5f28d2d7
SK
2485 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1072,
2486 "Done %s.\n", __func__);
1c7c6357
AV
2487 }
2488
2489 dma_pool_free(ha->s_dma_pool, lg, lg_dma);
2490
2491 return rval;
2492}
2493
1da177e4
LT
2494/*
2495 * qla2x00_fabric_logout
2496 * Issue logout fabric port mailbox command.
2497 *
2498 * Input:
2499 * ha = adapter block pointer.
2500 * loop_id = device loop ID.
2501 * TARGET_QUEUE_LOCK must be released.
2502 * ADAPTER_STATE_LOCK must be released.
2503 *
2504 * Returns:
2505 * qla2x00 local function return status code.
2506 *
2507 * Context:
2508 * Kernel context.
2509 */
2510int
7b867cf7 2511qla2x00_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
1c7c6357 2512 uint8_t area, uint8_t al_pa)
1da177e4
LT
2513{
2514 int rval;
2515 mbx_cmd_t mc;
2516 mbx_cmd_t *mcp = &mc;
2517
5f28d2d7
SK
2518 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1073,
2519 "Entered %s.\n", __func__);
1da177e4
LT
2520
2521 mcp->mb[0] = MBC_LOGOUT_FABRIC_PORT;
2522 mcp->out_mb = MBX_1|MBX_0;
7b867cf7 2523 if (HAS_EXTENDED_IDS(vha->hw)) {
1da177e4
LT
2524 mcp->mb[1] = loop_id;
2525 mcp->mb[10] = 0;
2526 mcp->out_mb |= MBX_10;
2527 } else {
2528 mcp->mb[1] = loop_id << 8;
2529 }
2530
2531 mcp->in_mb = MBX_1|MBX_0;
b93480e3 2532 mcp->tov = MBX_TOV_SECONDS;
1da177e4 2533 mcp->flags = 0;
7b867cf7 2534 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
2535
2536 if (rval != QLA_SUCCESS) {
2537 /*EMPTY*/
7c3df132
SK
2538 ql_dbg(ql_dbg_mbx, vha, 0x1074,
2539 "Failed=%x mb[1]=%x.\n", rval, mcp->mb[1]);
1da177e4
LT
2540 } else {
2541 /*EMPTY*/
5f28d2d7
SK
2542 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1075,
2543 "Done %s.\n", __func__);
1da177e4
LT
2544 }
2545
2546 return rval;
2547}
2548
2549/*
2550 * qla2x00_full_login_lip
2551 * Issue full login LIP mailbox command.
2552 *
2553 * Input:
2554 * ha = adapter block pointer.
2555 * TARGET_QUEUE_LOCK must be released.
2556 * ADAPTER_STATE_LOCK must be released.
2557 *
2558 * Returns:
2559 * qla2x00 local function return status code.
2560 *
2561 * Context:
2562 * Kernel context.
2563 */
2564int
7b867cf7 2565qla2x00_full_login_lip(scsi_qla_host_t *vha)
1da177e4
LT
2566{
2567 int rval;
2568 mbx_cmd_t mc;
2569 mbx_cmd_t *mcp = &mc;
2570
5f28d2d7
SK
2571 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1076,
2572 "Entered %s.\n", __func__);
1da177e4
LT
2573
2574 mcp->mb[0] = MBC_LIP_FULL_LOGIN;
7b867cf7 2575 mcp->mb[1] = IS_FWI2_CAPABLE(vha->hw) ? BIT_3 : 0;
0c8c39af 2576 mcp->mb[2] = 0;
1da177e4
LT
2577 mcp->mb[3] = 0;
2578 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2579 mcp->in_mb = MBX_0;
b93480e3 2580 mcp->tov = MBX_TOV_SECONDS;
1da177e4 2581 mcp->flags = 0;
7b867cf7 2582 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
2583
2584 if (rval != QLA_SUCCESS) {
2585 /*EMPTY*/
7c3df132 2586 ql_dbg(ql_dbg_mbx, vha, 0x1077, "Failed=%x.\n", rval);
1da177e4
LT
2587 } else {
2588 /*EMPTY*/
5f28d2d7
SK
2589 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1078,
2590 "Done %s.\n", __func__);
1da177e4
LT
2591 }
2592
2593 return rval;
2594}
2595
2596/*
2597 * qla2x00_get_id_list
2598 *
2599 * Input:
2600 * ha = adapter block pointer.
2601 *
2602 * Returns:
2603 * qla2x00 local function return status code.
2604 *
2605 * Context:
2606 * Kernel context.
2607 */
2608int
7b867cf7 2609qla2x00_get_id_list(scsi_qla_host_t *vha, void *id_list, dma_addr_t id_list_dma,
1da177e4
LT
2610 uint16_t *entries)
2611{
2612 int rval;
2613 mbx_cmd_t mc;
2614 mbx_cmd_t *mcp = &mc;
2615
5f28d2d7
SK
2616 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1079,
2617 "Entered %s.\n", __func__);
1da177e4
LT
2618
2619 if (id_list == NULL)
2620 return QLA_FUNCTION_FAILED;
2621
2622 mcp->mb[0] = MBC_GET_ID_LIST;
1c7c6357 2623 mcp->out_mb = MBX_0;
7b867cf7 2624 if (IS_FWI2_CAPABLE(vha->hw)) {
1c7c6357
AV
2625 mcp->mb[2] = MSW(id_list_dma);
2626 mcp->mb[3] = LSW(id_list_dma);
2627 mcp->mb[6] = MSW(MSD(id_list_dma));
2628 mcp->mb[7] = LSW(MSD(id_list_dma));
247ec457 2629 mcp->mb[8] = 0;
7b867cf7 2630 mcp->mb[9] = vha->vp_idx;
2c3dfe3f 2631 mcp->out_mb |= MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2;
1c7c6357
AV
2632 } else {
2633 mcp->mb[1] = MSW(id_list_dma);
2634 mcp->mb[2] = LSW(id_list_dma);
2635 mcp->mb[3] = MSW(MSD(id_list_dma));
2636 mcp->mb[6] = LSW(MSD(id_list_dma));
2637 mcp->out_mb |= MBX_6|MBX_3|MBX_2|MBX_1;
2638 }
1da177e4 2639 mcp->in_mb = MBX_1|MBX_0;
b93480e3 2640 mcp->tov = MBX_TOV_SECONDS;
1da177e4 2641 mcp->flags = 0;
7b867cf7 2642 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
2643
2644 if (rval != QLA_SUCCESS) {
2645 /*EMPTY*/
7c3df132 2646 ql_dbg(ql_dbg_mbx, vha, 0x107a, "Failed=%x.\n", rval);
1da177e4
LT
2647 } else {
2648 *entries = mcp->mb[1];
5f28d2d7
SK
2649 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107b,
2650 "Done %s.\n", __func__);
1da177e4
LT
2651 }
2652
2653 return rval;
2654}
2655
2656/*
2657 * qla2x00_get_resource_cnts
2658 * Get current firmware resource counts.
2659 *
2660 * Input:
2661 * ha = adapter block pointer.
2662 *
2663 * Returns:
2664 * qla2x00 local function return status code.
2665 *
2666 * Context:
2667 * Kernel context.
2668 */
2669int
03e8c680 2670qla2x00_get_resource_cnts(scsi_qla_host_t *vha)
1da177e4 2671{
03e8c680 2672 struct qla_hw_data *ha = vha->hw;
1da177e4
LT
2673 int rval;
2674 mbx_cmd_t mc;
2675 mbx_cmd_t *mcp = &mc;
2676
5f28d2d7
SK
2677 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107c,
2678 "Entered %s.\n", __func__);
1da177e4
LT
2679
2680 mcp->mb[0] = MBC_GET_RESOURCE_COUNTS;
2681 mcp->out_mb = MBX_0;
4d0ea247 2682 mcp->in_mb = MBX_11|MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
f73cb695 2683 if (IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw) || IS_QLA27XX(vha->hw))
f3a0a77e 2684 mcp->in_mb |= MBX_12;
b93480e3 2685 mcp->tov = MBX_TOV_SECONDS;
1da177e4 2686 mcp->flags = 0;
7b867cf7 2687 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
2688
2689 if (rval != QLA_SUCCESS) {
2690 /*EMPTY*/
7c3df132
SK
2691 ql_dbg(ql_dbg_mbx, vha, 0x107d,
2692 "Failed mb[0]=%x.\n", mcp->mb[0]);
1da177e4 2693 } else {
5f28d2d7 2694 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107e,
7c3df132
SK
2695 "Done %s mb1=%x mb2=%x mb3=%x mb6=%x mb7=%x mb10=%x "
2696 "mb11=%x mb12=%x.\n", __func__, mcp->mb[1], mcp->mb[2],
2697 mcp->mb[3], mcp->mb[6], mcp->mb[7], mcp->mb[10],
2698 mcp->mb[11], mcp->mb[12]);
1da177e4 2699
03e8c680
QT
2700 ha->orig_fw_tgt_xcb_count = mcp->mb[1];
2701 ha->cur_fw_tgt_xcb_count = mcp->mb[2];
2702 ha->cur_fw_xcb_count = mcp->mb[3];
2703 ha->orig_fw_xcb_count = mcp->mb[6];
2704 ha->cur_fw_iocb_count = mcp->mb[7];
2705 ha->orig_fw_iocb_count = mcp->mb[10];
2706 if (ha->flags.npiv_supported)
2707 ha->max_npiv_vports = mcp->mb[11];
2708 if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
2709 ha->fw_max_fcf_count = mcp->mb[12];
1da177e4
LT
2710 }
2711
2712 return (rval);
2713}
2714
1da177e4
LT
2715/*
2716 * qla2x00_get_fcal_position_map
2717 * Get FCAL (LILP) position map using mailbox command
2718 *
2719 * Input:
2720 * ha = adapter state pointer.
2721 * pos_map = buffer pointer (can be NULL).
2722 *
2723 * Returns:
2724 * qla2x00 local function return status code.
2725 *
2726 * Context:
2727 * Kernel context.
2728 */
2729int
7b867cf7 2730qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map)
1da177e4
LT
2731{
2732 int rval;
2733 mbx_cmd_t mc;
2734 mbx_cmd_t *mcp = &mc;
2735 char *pmap;
2736 dma_addr_t pmap_dma;
7b867cf7 2737 struct qla_hw_data *ha = vha->hw;
1da177e4 2738
5f28d2d7
SK
2739 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107f,
2740 "Entered %s.\n", __func__);
7c3df132 2741
4b89258c 2742 pmap = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pmap_dma);
1da177e4 2743 if (pmap == NULL) {
7c3df132
SK
2744 ql_log(ql_log_warn, vha, 0x1080,
2745 "Memory alloc failed.\n");
1da177e4
LT
2746 return QLA_MEMORY_ALLOC_FAILED;
2747 }
2748 memset(pmap, 0, FCAL_MAP_SIZE);
2749
2750 mcp->mb[0] = MBC_GET_FC_AL_POSITION_MAP;
2751 mcp->mb[2] = MSW(pmap_dma);
2752 mcp->mb[3] = LSW(pmap_dma);
2753 mcp->mb[6] = MSW(MSD(pmap_dma));
2754 mcp->mb[7] = LSW(MSD(pmap_dma));
2755 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
2756 mcp->in_mb = MBX_1|MBX_0;
2757 mcp->buf_size = FCAL_MAP_SIZE;
2758 mcp->flags = MBX_DMA_IN;
2759 mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
7b867cf7 2760 rval = qla2x00_mailbox_command(vha, mcp);
1da177e4
LT
2761
2762 if (rval == QLA_SUCCESS) {
5f28d2d7 2763 ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1081,
7c3df132
SK
2764 "mb0/mb1=%x/%X FC/AL position map size (%x).\n",
2765 mcp->mb[0], mcp->mb[1], (unsigned)pmap[0]);
2766 ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111d,
2767 pmap, pmap[0] + 1);
1da177e4
LT
2768
2769 if (pos_map)
2770 memcpy(pos_map, pmap, FCAL_MAP_SIZE);
2771 }
2772 dma_pool_free(ha->s_dma_pool, pmap, pmap_dma);
2773
2774 if (rval != QLA_SUCCESS) {
7c3df132 2775 ql_dbg(ql_dbg_mbx, vha, 0x1082, "Failed=%x.\n", rval);
1da177e4 2776 } else {
5f28d2d7
SK
2777 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1083,
2778 "Done %s.\n", __func__);
1da177e4
LT
2779 }
2780
2781 return rval;
2782}
392e2f65 2783
2784/*
2785 * qla2x00_get_link_status
2786 *
2787 * Input:
2788 * ha = adapter block pointer.
2789 * loop_id = device loop ID.
2790 * ret_buf = pointer to link status return buffer.
2791 *
2792 * Returns:
2793 * 0 = success.
2794 * BIT_0 = mem alloc error.
2795 * BIT_1 = mailbox error.
2796 */
2797int
7b867cf7 2798qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
43ef0580 2799 struct link_statistics *stats, dma_addr_t stats_dma)
392e2f65 2800{
2801 int rval;
2802 mbx_cmd_t mc;
2803 mbx_cmd_t *mcp = &mc;
c6dc9905
JC
2804 uint32_t *iter = (void *)stats;
2805 ushort dwords = offsetof(typeof(*stats), link_up_cnt)/sizeof(*iter);
7b867cf7 2806 struct qla_hw_data *ha = vha->hw;
392e2f65 2807
5f28d2d7
SK
2808 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1084,
2809 "Entered %s.\n", __func__);
392e2f65 2810
392e2f65 2811 mcp->mb[0] = MBC_GET_LINK_STATUS;
c6dc9905
JC
2812 mcp->mb[2] = MSW(LSD(stats_dma));
2813 mcp->mb[3] = LSW(LSD(stats_dma));
43ef0580
AV
2814 mcp->mb[6] = MSW(MSD(stats_dma));
2815 mcp->mb[7] = LSW(MSD(stats_dma));
392e2f65 2816 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
2817 mcp->in_mb = MBX_0;
e428924c 2818 if (IS_FWI2_CAPABLE(ha)) {
392e2f65 2819 mcp->mb[1] = loop_id;
2820 mcp->mb[4] = 0;
2821 mcp->mb[10] = 0;
2822 mcp->out_mb |= MBX_10|MBX_4|MBX_1;
2823 mcp->in_mb |= MBX_1;
2824 } else if (HAS_EXTENDED_IDS(ha)) {
2825 mcp->mb[1] = loop_id;
2826 mcp->mb[10] = 0;
2827 mcp->out_mb |= MBX_10|MBX_1;
2828 } else {
2829 mcp->mb[1] = loop_id << 8;
2830 mcp->out_mb |= MBX_1;
2831 }
b93480e3 2832 mcp->tov = MBX_TOV_SECONDS;
392e2f65 2833 mcp->flags = IOCTL_CMD;
7b867cf7 2834 rval = qla2x00_mailbox_command(vha, mcp);
392e2f65 2835
2836 if (rval == QLA_SUCCESS) {
2837 if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
7c3df132
SK
2838 ql_dbg(ql_dbg_mbx, vha, 0x1085,
2839 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
43ef0580 2840 rval = QLA_FUNCTION_FAILED;
392e2f65 2841 } else {
c6dc9905 2842 /* Re-endianize - firmware data is le32. */
5f28d2d7
SK
2843 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1086,
2844 "Done %s.\n", __func__);
da08ef5c
JC
2845 for ( ; dwords--; iter++)
2846 le32_to_cpus(iter);
392e2f65 2847 }
2848 } else {
2849 /* Failed. */
7c3df132 2850 ql_dbg(ql_dbg_mbx, vha, 0x1087, "Failed=%x.\n", rval);
392e2f65 2851 }
2852
392e2f65 2853 return rval;
2854}
2855
2856int
7b867cf7 2857qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
15f30a57 2858 dma_addr_t stats_dma, uint16_t options)
1c7c6357
AV
2859{
2860 int rval;
2861 mbx_cmd_t mc;
2862 mbx_cmd_t *mcp = &mc;
da08ef5c 2863 uint32_t *iter, dwords;
1c7c6357 2864
5f28d2d7
SK
2865 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1088,
2866 "Entered %s.\n", __func__);
1c7c6357 2867
15f30a57
QT
2868 memset(&mc, 0, sizeof(mc));
2869 mc.mb[0] = MBC_GET_LINK_PRIV_STATS;
2870 mc.mb[2] = MSW(stats_dma);
2871 mc.mb[3] = LSW(stats_dma);
2872 mc.mb[6] = MSW(MSD(stats_dma));
2873 mc.mb[7] = LSW(MSD(stats_dma));
2874 mc.mb[8] = sizeof(struct link_statistics) / 4;
2875 mc.mb[9] = cpu_to_le16(vha->vp_idx);
2876 mc.mb[10] = cpu_to_le16(options);
2877
2878 rval = qla24xx_send_mb_cmd(vha, &mc);
1c7c6357
AV
2879
2880 if (rval == QLA_SUCCESS) {
2881 if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
7c3df132
SK
2882 ql_dbg(ql_dbg_mbx, vha, 0x1089,
2883 "Failed mb[0]=%x.\n", mcp->mb[0]);
43ef0580 2884 rval = QLA_FUNCTION_FAILED;
1c7c6357 2885 } else {
5f28d2d7
SK
2886 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108a,
2887 "Done %s.\n", __func__);
c6dc9905 2888 /* Re-endianize - firmware data is le32. */
43ef0580 2889 dwords = sizeof(struct link_statistics) / 4;
da08ef5c
JC
2890 iter = &stats->link_fail_cnt;
2891 for ( ; dwords--; iter++)
2892 le32_to_cpus(iter);
1c7c6357
AV
2893 }
2894 } else {
2895 /* Failed. */
7c3df132 2896 ql_dbg(ql_dbg_mbx, vha, 0x108b, "Failed=%x.\n", rval);
1c7c6357
AV
2897 }
2898
1c7c6357
AV
2899 return rval;
2900}
1c7c6357
AV
2901
2902int
2afa19a9 2903qla24xx_abort_command(srb_t *sp)
1c7c6357
AV
2904{
2905 int rval;
1c7c6357
AV
2906 unsigned long flags = 0;
2907
2908 struct abort_entry_24xx *abt;
2909 dma_addr_t abt_dma;
2910 uint32_t handle;
2afa19a9
AC
2911 fc_port_t *fcport = sp->fcport;
2912 struct scsi_qla_host *vha = fcport->vha;
7b867cf7 2913 struct qla_hw_data *ha = vha->hw;
67c2e93a 2914 struct req_que *req = vha->req;
1c7c6357 2915
5f28d2d7
SK
2916 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108c,
2917 "Entered %s.\n", __func__);
1c7c6357 2918
d7459527
MH
2919 if (vha->flags.qpairs_available && sp->qpair)
2920 req = sp->qpair->req;
2921
4440e46d
AB
2922 if (ql2xasynctmfenable)
2923 return qla24xx_async_abort_command(sp);
2924
7b867cf7 2925 spin_lock_irqsave(&ha->hardware_lock, flags);
8d93f550 2926 for (handle = 1; handle < req->num_outstanding_cmds; handle++) {
7b867cf7 2927 if (req->outstanding_cmds[handle] == sp)
1c7c6357
AV
2928 break;
2929 }
7b867cf7 2930 spin_unlock_irqrestore(&ha->hardware_lock, flags);
8d93f550 2931 if (handle == req->num_outstanding_cmds) {
1c7c6357
AV
2932 /* Command not found. */
2933 return QLA_FUNCTION_FAILED;
2934 }
2935
2936 abt = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &abt_dma);
2937 if (abt == NULL) {
7c3df132
SK
2938 ql_log(ql_log_warn, vha, 0x108d,
2939 "Failed to allocate abort IOCB.\n");
1c7c6357
AV
2940 return QLA_MEMORY_ALLOC_FAILED;
2941 }
2942 memset(abt, 0, sizeof(struct abort_entry_24xx));
2943
2944 abt->entry_type = ABORT_IOCB_TYPE;
2945 abt->entry_count = 1;
2afa19a9 2946 abt->handle = MAKE_HANDLE(req->id, abt->handle);
1c7c6357 2947 abt->nport_handle = cpu_to_le16(fcport->loop_id);
a74ec14f 2948 abt->handle_to_abort = MAKE_HANDLE(req->id, handle);
1c7c6357
AV
2949 abt->port_id[0] = fcport->d_id.b.al_pa;
2950 abt->port_id[1] = fcport->d_id.b.area;
2951 abt->port_id[2] = fcport->d_id.b.domain;
c6d39e23 2952 abt->vp_index = fcport->vha->vp_idx;
73208dfd
AC
2953
2954 abt->req_que_no = cpu_to_le16(req->id);
2955
7b867cf7 2956 rval = qla2x00_issue_iocb(vha, abt, abt_dma, 0);
1c7c6357 2957 if (rval != QLA_SUCCESS) {
7c3df132
SK
2958 ql_dbg(ql_dbg_mbx, vha, 0x108e,
2959 "Failed to issue IOCB (%x).\n", rval);
1c7c6357 2960 } else if (abt->entry_status != 0) {
7c3df132
SK
2961 ql_dbg(ql_dbg_mbx, vha, 0x108f,
2962 "Failed to complete IOCB -- error status (%x).\n",
2963 abt->entry_status);
1c7c6357 2964 rval = QLA_FUNCTION_FAILED;
ad950360 2965 } else if (abt->nport_handle != cpu_to_le16(0)) {
7c3df132
SK
2966 ql_dbg(ql_dbg_mbx, vha, 0x1090,
2967 "Failed to complete IOCB -- completion status (%x).\n",
2968 le16_to_cpu(abt->nport_handle));
f934c9d0
CD
2969 if (abt->nport_handle == CS_IOCB_ERROR)
2970 rval = QLA_FUNCTION_PARAMETER_ERROR;
2971 else
2972 rval = QLA_FUNCTION_FAILED;
1c7c6357 2973 } else {
5f28d2d7
SK
2974 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1091,
2975 "Done %s.\n", __func__);
1c7c6357
AV
2976 }
2977
2978 dma_pool_free(ha->s_dma_pool, abt, abt_dma);
2979
2980 return rval;
2981}
2982
2983struct tsk_mgmt_cmd {
2984 union {
2985 struct tsk_mgmt_entry tsk;
2986 struct sts_entry_24xx sts;
2987 } p;
2988};
2989
523ec773
AV
2990static int
2991__qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
9cb78c16 2992 uint64_t l, int tag)
1c7c6357 2993{
523ec773 2994 int rval, rval2;
1c7c6357 2995 struct tsk_mgmt_cmd *tsk;
9ca1d01f 2996 struct sts_entry_24xx *sts;
1c7c6357 2997 dma_addr_t tsk_dma;
7b867cf7
AC
2998 scsi_qla_host_t *vha;
2999 struct qla_hw_data *ha;
73208dfd
AC
3000 struct req_que *req;
3001 struct rsp_que *rsp;
d7459527 3002 struct qla_qpair *qpair;
1c7c6357 3003
7b867cf7
AC
3004 vha = fcport->vha;
3005 ha = vha->hw;
2afa19a9 3006 req = vha->req;
7c3df132 3007
5f28d2d7
SK
3008 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1092,
3009 "Entered %s.\n", __func__);
7c3df132 3010
d7459527
MH
3011 if (vha->vp_idx && vha->qpair) {
3012 /* NPIV port */
3013 qpair = vha->qpair;
3014 rsp = qpair->rsp;
3015 req = qpair->req;
3016 } else {
68ca949c 3017 rsp = req->rsp;
d7459527
MH
3018 }
3019
7b867cf7 3020 tsk = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma);
1c7c6357 3021 if (tsk == NULL) {
7c3df132
SK
3022 ql_log(ql_log_warn, vha, 0x1093,
3023 "Failed to allocate task management IOCB.\n");
1c7c6357
AV
3024 return QLA_MEMORY_ALLOC_FAILED;
3025 }
3026 memset(tsk, 0, sizeof(struct tsk_mgmt_cmd));
3027
3028 tsk->p.tsk.entry_type = TSK_MGMT_IOCB_TYPE;
3029 tsk->p.tsk.entry_count = 1;
2afa19a9 3030 tsk->p.tsk.handle = MAKE_HANDLE(req->id, tsk->p.tsk.handle);
1c7c6357 3031 tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id);
00a537b8 3032 tsk->p.tsk.timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
523ec773 3033 tsk->p.tsk.control_flags = cpu_to_le32(type);
1c7c6357
AV
3034 tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa;
3035 tsk->p.tsk.port_id[1] = fcport->d_id.b.area;
3036 tsk->p.tsk.port_id[2] = fcport->d_id.b.domain;
c6d39e23 3037 tsk->p.tsk.vp_index = fcport->vha->vp_idx;
523ec773
AV
3038 if (type == TCF_LUN_RESET) {
3039 int_to_scsilun(l, &tsk->p.tsk.lun);
3040 host_to_fcp_swap((uint8_t *)&tsk->p.tsk.lun,
3041 sizeof(tsk->p.tsk.lun));
3042 }
2c3dfe3f 3043
9ca1d01f 3044 sts = &tsk->p.sts;
7b867cf7 3045 rval = qla2x00_issue_iocb(vha, tsk, tsk_dma, 0);
1c7c6357 3046 if (rval != QLA_SUCCESS) {
7c3df132
SK
3047 ql_dbg(ql_dbg_mbx, vha, 0x1094,
3048 "Failed to issue %s reset IOCB (%x).\n", name, rval);
9ca1d01f 3049 } else if (sts->entry_status != 0) {
7c3df132
SK
3050 ql_dbg(ql_dbg_mbx, vha, 0x1095,
3051 "Failed to complete IOCB -- error status (%x).\n",
3052 sts->entry_status);
1c7c6357 3053 rval = QLA_FUNCTION_FAILED;
ad950360 3054 } else if (sts->comp_status != cpu_to_le16(CS_COMPLETE)) {
7c3df132
SK
3055 ql_dbg(ql_dbg_mbx, vha, 0x1096,
3056 "Failed to complete IOCB -- completion status (%x).\n",
3057 le16_to_cpu(sts->comp_status));
9ca1d01f 3058 rval = QLA_FUNCTION_FAILED;
97dec564
AV
3059 } else if (le16_to_cpu(sts->scsi_status) &
3060 SS_RESPONSE_INFO_LEN_VALID) {
3061 if (le32_to_cpu(sts->rsp_data_len) < 4) {
5f28d2d7 3062 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1097,
7c3df132
SK
3063 "Ignoring inconsistent data length -- not enough "
3064 "response info (%d).\n",
3065 le32_to_cpu(sts->rsp_data_len));
97dec564 3066 } else if (sts->data[3]) {
7c3df132
SK
3067 ql_dbg(ql_dbg_mbx, vha, 0x1098,
3068 "Failed to complete IOCB -- response (%x).\n",
3069 sts->data[3]);
97dec564
AV
3070 rval = QLA_FUNCTION_FAILED;
3071 }
1c7c6357
AV
3072 }
3073
3074 /* Issue marker IOCB. */
73208dfd 3075 rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, l,
523ec773
AV
3076 type == TCF_LUN_RESET ? MK_SYNC_ID_LUN: MK_SYNC_ID);
3077 if (rval2 != QLA_SUCCESS) {
7c3df132
SK
3078 ql_dbg(ql_dbg_mbx, vha, 0x1099,
3079 "Failed to issue marker IOCB (%x).\n", rval2);
1c7c6357 3080 } else {
5f28d2d7
SK
3081 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109a,
3082 "Done %s.\n", __func__);
1c7c6357
AV
3083 }
3084
7b867cf7 3085 dma_pool_free(ha->s_dma_pool, tsk, tsk_dma);
1c7c6357
AV
3086
3087 return rval;
3088}
3089
523ec773 3090int
9cb78c16 3091qla24xx_abort_target(struct fc_port *fcport, uint64_t l, int tag)
523ec773 3092{
3822263e
MI
3093 struct qla_hw_data *ha = fcport->vha->hw;
3094
3095 if ((ql2xasynctmfenable) && IS_FWI2_CAPABLE(ha))
3096 return qla2x00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag);
3097
2afa19a9 3098 return __qla24xx_issue_tmf("Target", TCF_TARGET_RESET, fcport, l, tag);
523ec773
AV
3099}
3100
3101int
9cb78c16 3102qla24xx_lun_reset(struct fc_port *fcport, uint64_t l, int tag)
523ec773 3103{
3822263e
MI
3104 struct qla_hw_data *ha = fcport->vha->hw;
3105
3106 if ((ql2xasynctmfenable) && IS_FWI2_CAPABLE(ha))
3107 return qla2x00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag);
3108
2afa19a9 3109 return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l, tag);
523ec773
AV
3110}
3111
1c7c6357 3112int
7b867cf7 3113qla2x00_system_error(scsi_qla_host_t *vha)
1c7c6357
AV
3114{
3115 int rval;
3116 mbx_cmd_t mc;
3117 mbx_cmd_t *mcp = &mc;
7b867cf7 3118 struct qla_hw_data *ha = vha->hw;
1c7c6357 3119
68af0811 3120 if (!IS_QLA23XX(ha) && !IS_FWI2_CAPABLE(ha))
1c7c6357
AV
3121 return QLA_FUNCTION_FAILED;
3122
5f28d2d7
SK
3123 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109b,
3124 "Entered %s.\n", __func__);
1c7c6357
AV
3125
3126 mcp->mb[0] = MBC_GEN_SYSTEM_ERROR;
3127 mcp->out_mb = MBX_0;
3128 mcp->in_mb = MBX_0;
3129 mcp->tov = 5;
3130 mcp->flags = 0;
7b867cf7 3131 rval = qla2x00_mailbox_command(vha, mcp);
1c7c6357
AV
3132
3133 if (rval != QLA_SUCCESS) {
7c3df132 3134 ql_dbg(ql_dbg_mbx, vha, 0x109c, "Failed=%x.\n", rval);
1c7c6357 3135 } else {
5f28d2d7
SK
3136 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109d,
3137 "Done %s.\n", __func__);
1c7c6357
AV
3138 }
3139
3140 return rval;
3141}
3142
db64e930
JC
3143int
3144qla2x00_write_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t data)
3145{
3146 int rval;
3147 mbx_cmd_t mc;
3148 mbx_cmd_t *mcp = &mc;
3149
f299c7c2
JC
3150 if (!IS_QLA25XX(vha->hw) && !IS_QLA2031(vha->hw) &&
3151 !IS_QLA27XX(vha->hw))
db64e930
JC
3152 return QLA_FUNCTION_FAILED;
3153
3154 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1182,
3155 "Entered %s.\n", __func__);
3156
3157 mcp->mb[0] = MBC_WRITE_SERDES;
3158 mcp->mb[1] = addr;
064135e0
AV
3159 if (IS_QLA2031(vha->hw))
3160 mcp->mb[2] = data & 0xff;
3161 else
3162 mcp->mb[2] = data;
3163
db64e930
JC
3164 mcp->mb[3] = 0;
3165 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
3166 mcp->in_mb = MBX_0;
3167 mcp->tov = MBX_TOV_SECONDS;
3168 mcp->flags = 0;
3169 rval = qla2x00_mailbox_command(vha, mcp);
3170
3171 if (rval != QLA_SUCCESS) {
3172 ql_dbg(ql_dbg_mbx, vha, 0x1183,
3173 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
3174 } else {
3175 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1184,
3176 "Done %s.\n", __func__);
3177 }
3178
3179 return rval;
3180}
3181
3182int
3183qla2x00_read_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t *data)
3184{
3185 int rval;
3186 mbx_cmd_t mc;
3187 mbx_cmd_t *mcp = &mc;
3188
f299c7c2
JC
3189 if (!IS_QLA25XX(vha->hw) && !IS_QLA2031(vha->hw) &&
3190 !IS_QLA27XX(vha->hw))
db64e930
JC
3191 return QLA_FUNCTION_FAILED;
3192
3193 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1185,
3194 "Entered %s.\n", __func__);
3195
3196 mcp->mb[0] = MBC_READ_SERDES;
3197 mcp->mb[1] = addr;
3198 mcp->mb[3] = 0;
3199 mcp->out_mb = MBX_3|MBX_1|MBX_0;
3200 mcp->in_mb = MBX_1|MBX_0;
3201 mcp->tov = MBX_TOV_SECONDS;
3202 mcp->flags = 0;
3203 rval = qla2x00_mailbox_command(vha, mcp);
3204
064135e0
AV
3205 if (IS_QLA2031(vha->hw))
3206 *data = mcp->mb[1] & 0xff;
3207 else
3208 *data = mcp->mb[1];
db64e930
JC
3209
3210 if (rval != QLA_SUCCESS) {
3211 ql_dbg(ql_dbg_mbx, vha, 0x1186,
3212 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
3213 } else {
3214 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1187,
3215 "Done %s.\n", __func__);
3216 }
3217
3218 return rval;
3219}
3220
e8887c51
JC
3221int
3222qla8044_write_serdes_word(scsi_qla_host_t *vha, uint32_t addr, uint32_t data)
3223{
3224 int rval;
3225 mbx_cmd_t mc;
3226 mbx_cmd_t *mcp = &mc;
3227
3228 if (!IS_QLA8044(vha->hw))
3229 return QLA_FUNCTION_FAILED;
3230
83548fe2 3231 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x11a0,
e8887c51
JC
3232 "Entered %s.\n", __func__);
3233
3234 mcp->mb[0] = MBC_SET_GET_ETH_SERDES_REG;
3235 mcp->mb[1] = HCS_WRITE_SERDES;
3236 mcp->mb[3] = LSW(addr);
3237 mcp->mb[4] = MSW(addr);
3238 mcp->mb[5] = LSW(data);
3239 mcp->mb[6] = MSW(data);
3240 mcp->out_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_1|MBX_0;
3241 mcp->in_mb = MBX_0;
3242 mcp->tov = MBX_TOV_SECONDS;
3243 mcp->flags = 0;
3244 rval = qla2x00_mailbox_command(vha, mcp);
3245
3246 if (rval != QLA_SUCCESS) {
83548fe2 3247 ql_dbg(ql_dbg_mbx, vha, 0x11a1,
e8887c51
JC
3248 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
3249 } else {
3250 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1188,
3251 "Done %s.\n", __func__);
3252 }
3253
3254 return rval;
3255}
3256
3257int
3258qla8044_read_serdes_word(scsi_qla_host_t *vha, uint32_t addr, uint32_t *data)
3259{
3260 int rval;
3261 mbx_cmd_t mc;
3262 mbx_cmd_t *mcp = &mc;
3263
3264 if (!IS_QLA8044(vha->hw))
3265 return QLA_FUNCTION_FAILED;
3266
3267 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1189,
3268 "Entered %s.\n", __func__);
3269
3270 mcp->mb[0] = MBC_SET_GET_ETH_SERDES_REG;
3271 mcp->mb[1] = HCS_READ_SERDES;
3272 mcp->mb[3] = LSW(addr);
3273 mcp->mb[4] = MSW(addr);
3274 mcp->out_mb = MBX_4|MBX_3|MBX_1|MBX_0;
3275 mcp->in_mb = MBX_2|MBX_1|MBX_0;
3276 mcp->tov = MBX_TOV_SECONDS;
3277 mcp->flags = 0;
3278 rval = qla2x00_mailbox_command(vha, mcp);
3279
3280 *data = mcp->mb[2] << 16 | mcp->mb[1];
3281
3282 if (rval != QLA_SUCCESS) {
3283 ql_dbg(ql_dbg_mbx, vha, 0x118a,
3284 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
3285 } else {
3286 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118b,
3287 "Done %s.\n", __func__);
3288 }
3289
3290 return rval;
3291}
3292
1c7c6357
AV
3293/**
3294 * qla2x00_set_serdes_params() -
3295 * @ha: HA context
3296 *
3297 * Returns
3298 */
3299int
7b867cf7 3300qla2x00_set_serdes_params(scsi_qla_host_t *vha, uint16_t sw_em_1g,
1c7c6357
AV
3301 uint16_t sw_em_2g, uint16_t sw_em_4g)
3302{
3303 int rval;
3304 mbx_cmd_t mc;
3305 mbx_cmd_t *mcp = &mc;
3306
5f28d2d7
SK
3307 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109e,
3308 "Entered %s.\n", __func__);
1c7c6357
AV
3309
3310 mcp->mb[0] = MBC_SERDES_PARAMS;
3311 mcp->mb[1] = BIT_0;
fdbc6833 3312 mcp->mb[2] = sw_em_1g | BIT_15;
3313 mcp->mb[3] = sw_em_2g | BIT_15;
3314 mcp->mb[4] = sw_em_4g | BIT_15;
1c7c6357
AV
3315 mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3316 mcp->in_mb = MBX_0;
b93480e3 3317 mcp->tov = MBX_TOV_SECONDS;
1c7c6357 3318 mcp->flags = 0;
7b867cf7 3319 rval = qla2x00_mailbox_command(vha, mcp);
1c7c6357
AV
3320
3321 if (rval != QLA_SUCCESS) {
3322 /*EMPTY*/
7c3df132
SK
3323 ql_dbg(ql_dbg_mbx, vha, 0x109f,
3324 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
1c7c6357
AV
3325 } else {
3326 /*EMPTY*/
5f28d2d7
SK
3327 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a0,
3328 "Done %s.\n", __func__);
1c7c6357
AV
3329 }
3330
3331 return rval;
3332}
f6ef3b18
AV
3333
3334int
7b867cf7 3335qla2x00_stop_firmware(scsi_qla_host_t *vha)
f6ef3b18
AV
3336{
3337 int rval;
3338 mbx_cmd_t mc;
3339 mbx_cmd_t *mcp = &mc;
3340
7b867cf7 3341 if (!IS_FWI2_CAPABLE(vha->hw))
f6ef3b18
AV
3342 return QLA_FUNCTION_FAILED;
3343
5f28d2d7
SK
3344 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a1,
3345 "Entered %s.\n", __func__);
f6ef3b18
AV
3346
3347 mcp->mb[0] = MBC_STOP_FIRMWARE;
4ba988db
AV
3348 mcp->mb[1] = 0;
3349 mcp->out_mb = MBX_1|MBX_0;
f6ef3b18
AV
3350 mcp->in_mb = MBX_0;
3351 mcp->tov = 5;
3352 mcp->flags = 0;
7b867cf7 3353 rval = qla2x00_mailbox_command(vha, mcp);
f6ef3b18
AV
3354
3355 if (rval != QLA_SUCCESS) {
7c3df132 3356 ql_dbg(ql_dbg_mbx, vha, 0x10a2, "Failed=%x.\n", rval);
b469a7cb
AV
3357 if (mcp->mb[0] == MBS_INVALID_COMMAND)
3358 rval = QLA_INVALID_COMMAND;
f6ef3b18 3359 } else {
5f28d2d7
SK
3360 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a3,
3361 "Done %s.\n", __func__);
f6ef3b18
AV
3362 }
3363
3364 return rval;
3365}
a7a167bf
AV
3366
3367int
7b867cf7 3368qla2x00_enable_eft_trace(scsi_qla_host_t *vha, dma_addr_t eft_dma,
a7a167bf
AV
3369 uint16_t buffers)
3370{
3371 int rval;
3372 mbx_cmd_t mc;
3373 mbx_cmd_t *mcp = &mc;
3374
5f28d2d7
SK
3375 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a4,
3376 "Entered %s.\n", __func__);
7c3df132 3377
7b867cf7 3378 if (!IS_FWI2_CAPABLE(vha->hw))
a7a167bf
AV
3379 return QLA_FUNCTION_FAILED;
3380
85880801
AV
3381 if (unlikely(pci_channel_offline(vha->hw->pdev)))
3382 return QLA_FUNCTION_FAILED;
3383
a7a167bf 3384 mcp->mb[0] = MBC_TRACE_CONTROL;
00b6bd25
AV
3385 mcp->mb[1] = TC_EFT_ENABLE;
3386 mcp->mb[2] = LSW(eft_dma);
3387 mcp->mb[3] = MSW(eft_dma);
3388 mcp->mb[4] = LSW(MSD(eft_dma));
3389 mcp->mb[5] = MSW(MSD(eft_dma));
3390 mcp->mb[6] = buffers;
3391 mcp->mb[7] = TC_AEN_DISABLE;
3392 mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
a7a167bf 3393 mcp->in_mb = MBX_1|MBX_0;
b93480e3 3394 mcp->tov = MBX_TOV_SECONDS;
a7a167bf 3395 mcp->flags = 0;
7b867cf7 3396 rval = qla2x00_mailbox_command(vha, mcp);
00b6bd25 3397 if (rval != QLA_SUCCESS) {
7c3df132
SK
3398 ql_dbg(ql_dbg_mbx, vha, 0x10a5,
3399 "Failed=%x mb[0]=%x mb[1]=%x.\n",
3400 rval, mcp->mb[0], mcp->mb[1]);
00b6bd25 3401 } else {
5f28d2d7
SK
3402 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a6,
3403 "Done %s.\n", __func__);
00b6bd25
AV
3404 }
3405
3406 return rval;
3407}
a7a167bf 3408
00b6bd25 3409int
7b867cf7 3410qla2x00_disable_eft_trace(scsi_qla_host_t *vha)
00b6bd25
AV
3411{
3412 int rval;
3413 mbx_cmd_t mc;
3414 mbx_cmd_t *mcp = &mc;
3415
5f28d2d7
SK
3416 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a7,
3417 "Entered %s.\n", __func__);
7c3df132 3418
7b867cf7 3419 if (!IS_FWI2_CAPABLE(vha->hw))
00b6bd25
AV
3420 return QLA_FUNCTION_FAILED;
3421
85880801
AV
3422 if (unlikely(pci_channel_offline(vha->hw->pdev)))
3423 return QLA_FUNCTION_FAILED;
3424
00b6bd25
AV
3425 mcp->mb[0] = MBC_TRACE_CONTROL;
3426 mcp->mb[1] = TC_EFT_DISABLE;
3427 mcp->out_mb = MBX_1|MBX_0;
3428 mcp->in_mb = MBX_1|MBX_0;
b93480e3 3429 mcp->tov = MBX_TOV_SECONDS;
00b6bd25 3430 mcp->flags = 0;
7b867cf7 3431 rval = qla2x00_mailbox_command(vha, mcp);
a7a167bf 3432 if (rval != QLA_SUCCESS) {
7c3df132
SK
3433 ql_dbg(ql_dbg_mbx, vha, 0x10a8,
3434 "Failed=%x mb[0]=%x mb[1]=%x.\n",
3435 rval, mcp->mb[0], mcp->mb[1]);
a7a167bf 3436 } else {
5f28d2d7
SK
3437 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a9,
3438 "Done %s.\n", __func__);
a7a167bf
AV
3439 }
3440
3441 return rval;
3442}
3443
df613b96 3444int
7b867cf7 3445qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma,
df613b96
AV
3446 uint16_t buffers, uint16_t *mb, uint32_t *dwords)
3447{
3448 int rval;
3449 mbx_cmd_t mc;
3450 mbx_cmd_t *mcp = &mc;
3451
5f28d2d7
SK
3452 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10aa,
3453 "Entered %s.\n", __func__);
7c3df132 3454
6246b8a1 3455 if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw) &&
f73cb695 3456 !IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw))
df613b96
AV
3457 return QLA_FUNCTION_FAILED;
3458
85880801
AV
3459 if (unlikely(pci_channel_offline(vha->hw->pdev)))
3460 return QLA_FUNCTION_FAILED;
3461
df613b96
AV
3462 mcp->mb[0] = MBC_TRACE_CONTROL;
3463 mcp->mb[1] = TC_FCE_ENABLE;
3464 mcp->mb[2] = LSW(fce_dma);
3465 mcp->mb[3] = MSW(fce_dma);
3466 mcp->mb[4] = LSW(MSD(fce_dma));
3467 mcp->mb[5] = MSW(MSD(fce_dma));
3468 mcp->mb[6] = buffers;
3469 mcp->mb[7] = TC_AEN_DISABLE;
3470 mcp->mb[8] = 0;
3471 mcp->mb[9] = TC_FCE_DEFAULT_RX_SIZE;
3472 mcp->mb[10] = TC_FCE_DEFAULT_TX_SIZE;
3473 mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|
3474 MBX_1|MBX_0;
3475 mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
b93480e3 3476 mcp->tov = MBX_TOV_SECONDS;
df613b96 3477 mcp->flags = 0;
7b867cf7 3478 rval = qla2x00_mailbox_command(vha, mcp);
df613b96 3479 if (rval != QLA_SUCCESS) {
7c3df132
SK
3480 ql_dbg(ql_dbg_mbx, vha, 0x10ab,
3481 "Failed=%x mb[0]=%x mb[1]=%x.\n",
3482 rval, mcp->mb[0], mcp->mb[1]);
df613b96 3483 } else {
5f28d2d7
SK
3484 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ac,
3485 "Done %s.\n", __func__);
df613b96
AV
3486
3487 if (mb)
3488 memcpy(mb, mcp->mb, 8 * sizeof(*mb));
3489 if (dwords)
fa0926df 3490 *dwords = buffers;
df613b96
AV
3491 }
3492
3493 return rval;
3494}
3495
3496int
7b867cf7 3497qla2x00_disable_fce_trace(scsi_qla_host_t *vha, uint64_t *wr, uint64_t *rd)
df613b96
AV
3498{
3499 int rval;
3500 mbx_cmd_t mc;
3501 mbx_cmd_t *mcp = &mc;
3502
5f28d2d7
SK
3503 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ad,
3504 "Entered %s.\n", __func__);
7c3df132 3505
7b867cf7 3506 if (!IS_FWI2_CAPABLE(vha->hw))
df613b96
AV
3507 return QLA_FUNCTION_FAILED;
3508
85880801
AV
3509 if (unlikely(pci_channel_offline(vha->hw->pdev)))
3510 return QLA_FUNCTION_FAILED;
3511
df613b96
AV
3512 mcp->mb[0] = MBC_TRACE_CONTROL;
3513 mcp->mb[1] = TC_FCE_DISABLE;
3514 mcp->mb[2] = TC_FCE_DISABLE_TRACE;
3515 mcp->out_mb = MBX_2|MBX_1|MBX_0;
3516 mcp->in_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|
3517 MBX_1|MBX_0;
b93480e3 3518 mcp->tov = MBX_TOV_SECONDS;
df613b96 3519 mcp->flags = 0;
7b867cf7 3520 rval = qla2x00_mailbox_command(vha, mcp);
df613b96 3521 if (rval != QLA_SUCCESS) {
7c3df132
SK
3522 ql_dbg(ql_dbg_mbx, vha, 0x10ae,
3523 "Failed=%x mb[0]=%x mb[1]=%x.\n",
3524 rval, mcp->mb[0], mcp->mb[1]);
df613b96 3525 } else {
5f28d2d7
SK
3526 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10af,
3527 "Done %s.\n", __func__);
df613b96
AV
3528
3529 if (wr)
3530 *wr = (uint64_t) mcp->mb[5] << 48 |
3531 (uint64_t) mcp->mb[4] << 32 |
3532 (uint64_t) mcp->mb[3] << 16 |
3533 (uint64_t) mcp->mb[2];
3534 if (rd)
3535 *rd = (uint64_t) mcp->mb[9] << 48 |
3536 (uint64_t) mcp->mb[8] << 32 |
3537 (uint64_t) mcp->mb[7] << 16 |
3538 (uint64_t) mcp->mb[6];
3539 }
3540
3541 return rval;
3542}
3543
6e98016c
GM
3544int
3545qla2x00_get_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
3546 uint16_t *port_speed, uint16_t *mb)
3547{
3548 int rval;
3549 mbx_cmd_t mc;
3550 mbx_cmd_t *mcp = &mc;
3551
5f28d2d7
SK
3552 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b0,
3553 "Entered %s.\n", __func__);
7c3df132 3554
6e98016c
GM
3555 if (!IS_IIDMA_CAPABLE(vha->hw))
3556 return QLA_FUNCTION_FAILED;
3557
6e98016c
GM
3558 mcp->mb[0] = MBC_PORT_PARAMS;
3559 mcp->mb[1] = loop_id;
3560 mcp->mb[2] = mcp->mb[3] = 0;
3561 mcp->mb[9] = vha->vp_idx;
3562 mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0;
3563 mcp->in_mb = MBX_3|MBX_1|MBX_0;
3564 mcp->tov = MBX_TOV_SECONDS;
3565 mcp->flags = 0;
3566 rval = qla2x00_mailbox_command(vha, mcp);
3567
3568 /* Return mailbox statuses. */
3569 if (mb != NULL) {
3570 mb[0] = mcp->mb[0];
3571 mb[1] = mcp->mb[1];
3572 mb[3] = mcp->mb[3];
3573 }
3574
3575 if (rval != QLA_SUCCESS) {
7c3df132 3576 ql_dbg(ql_dbg_mbx, vha, 0x10b1, "Failed=%x.\n", rval);
6e98016c 3577 } else {
5f28d2d7
SK
3578 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b2,
3579 "Done %s.\n", __func__);
6e98016c
GM
3580 if (port_speed)
3581 *port_speed = mcp->mb[3];
3582 }
3583
3584 return rval;
3585}
3586
d8b45213 3587int
7b867cf7 3588qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
d8b45213
AV
3589 uint16_t port_speed, uint16_t *mb)
3590{
3591 int rval;
3592 mbx_cmd_t mc;
3593 mbx_cmd_t *mcp = &mc;
3594
5f28d2d7
SK
3595 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b3,
3596 "Entered %s.\n", __func__);
7c3df132 3597
7b867cf7 3598 if (!IS_IIDMA_CAPABLE(vha->hw))
d8b45213
AV
3599 return QLA_FUNCTION_FAILED;
3600
d8b45213
AV
3601 mcp->mb[0] = MBC_PORT_PARAMS;
3602 mcp->mb[1] = loop_id;
3603 mcp->mb[2] = BIT_0;
6246b8a1 3604 if (IS_CNA_CAPABLE(vha->hw))
1bb39548
HZ
3605 mcp->mb[3] = port_speed & (BIT_5|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0);
3606 else
3607 mcp->mb[3] = port_speed & (BIT_2|BIT_1|BIT_0);
3608 mcp->mb[9] = vha->vp_idx;
3609 mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0;
3610 mcp->in_mb = MBX_3|MBX_1|MBX_0;
b93480e3 3611 mcp->tov = MBX_TOV_SECONDS;
d8b45213 3612 mcp->flags = 0;
7b867cf7 3613 rval = qla2x00_mailbox_command(vha, mcp);
d8b45213
AV
3614
3615 /* Return mailbox statuses. */
3616 if (mb != NULL) {
3617 mb[0] = mcp->mb[0];
3618 mb[1] = mcp->mb[1];
3619 mb[3] = mcp->mb[3];
d8b45213
AV
3620 }
3621
3622 if (rval != QLA_SUCCESS) {
5f28d2d7
SK
3623 ql_dbg(ql_dbg_mbx, vha, 0x10b4,
3624 "Failed=%x.\n", rval);
d8b45213 3625 } else {
5f28d2d7
SK
3626 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b5,
3627 "Done %s.\n", __func__);
d8b45213
AV
3628 }
3629
3630 return rval;
3631}
2c3dfe3f 3632
2c3dfe3f 3633void
7b867cf7 3634qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
2c3dfe3f
SJ
3635 struct vp_rpt_id_entry_24xx *rptid_entry)
3636{
7b867cf7 3637 struct qla_hw_data *ha = vha->hw;
41dc529a 3638 scsi_qla_host_t *vp = NULL;
feafb7b1 3639 unsigned long flags;
4ac8d4ca 3640 int found;
482c9dc7 3641 port_id_t id;
2c3dfe3f 3642
5f28d2d7
SK
3643 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b6,
3644 "Entered %s.\n", __func__);
7c3df132 3645
2c3dfe3f
SJ
3646 if (rptid_entry->entry_status != 0)
3647 return;
2c3dfe3f 3648
482c9dc7
QT
3649 id.b.domain = rptid_entry->port_id[2];
3650 id.b.area = rptid_entry->port_id[1];
3651 id.b.al_pa = rptid_entry->port_id[0];
3652 id.b.rsvd_1 = 0;
3653
2c3dfe3f 3654 if (rptid_entry->format == 0) {
41dc529a 3655 /* loop */
ec7193e2 3656 ql_dbg(ql_dbg_async, vha, 0x10b7,
7c3df132 3657 "Format 0 : Number of VPs setup %d, number of "
41dc529a
QT
3658 "VPs acquired %d.\n", rptid_entry->vp_setup,
3659 rptid_entry->vp_acquired);
ec7193e2 3660 ql_dbg(ql_dbg_async, vha, 0x10b8,
7c3df132
SK
3661 "Primary port id %02x%02x%02x.\n",
3662 rptid_entry->port_id[2], rptid_entry->port_id[1],
3663 rptid_entry->port_id[0]);
41dc529a 3664
482c9dc7 3665 qlt_update_host_map(vha, id);
41dc529a 3666
2c3dfe3f 3667 } else if (rptid_entry->format == 1) {
41dc529a 3668 /* fabric */
ec7193e2 3669 ql_dbg(ql_dbg_async, vha, 0x10b9,
7c3df132 3670 "Format 1: VP[%d] enabled - status %d - with "
41dc529a
QT
3671 "port id %02x%02x%02x.\n", rptid_entry->vp_idx,
3672 rptid_entry->vp_status,
2c3dfe3f 3673 rptid_entry->port_id[2], rptid_entry->port_id[1],
7c3df132 3674 rptid_entry->port_id[0]);
531a82d1 3675
969a6199 3676 /* buffer to buffer credit flag */
41dc529a
QT
3677 vha->flags.bbcr_enable = (rptid_entry->u.f1.bbcr & 0xf) != 0;
3678
3679 if (rptid_entry->vp_idx == 0) {
3680 if (rptid_entry->vp_status == VP_STAT_COMPL) {
3681 /* FA-WWN is only for physical port */
3682 if (qla_ini_mode_enabled(vha) &&
3683 ha->flags.fawwpn_enabled &&
3684 (rptid_entry->u.f1.flags &
3685 VP_FLAGS_NAME_VALID)) {
3686 memcpy(vha->port_name,
3687 rptid_entry->u.f1.port_name,
3688 WWN_SIZE);
3689 }
7c9c4766 3690
482c9dc7 3691 qlt_update_host_map(vha, id);
7c9c4766 3692 }
41dc529a 3693
41dc529a
QT
3694 set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
3695 set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
3696 } else {
3697 if (rptid_entry->vp_status != VP_STAT_COMPL &&
3698 rptid_entry->vp_status != VP_STAT_ID_CHG) {
3699 ql_dbg(ql_dbg_mbx, vha, 0x10ba,
3700 "Could not acquire ID for VP[%d].\n",
3701 rptid_entry->vp_idx);
3702 return;
4ac8d4ca 3703 }
feafb7b1 3704
41dc529a
QT
3705 found = 0;
3706 spin_lock_irqsave(&ha->vport_slock, flags);
3707 list_for_each_entry(vp, &ha->vp_list, list) {
3708 if (rptid_entry->vp_idx == vp->vp_idx) {
3709 found = 1;
3710 break;
3711 }
3712 }
3713 spin_unlock_irqrestore(&ha->vport_slock, flags);
2c3dfe3f 3714
41dc529a
QT
3715 if (!found)
3716 return;
2c3dfe3f 3717
482c9dc7 3718 qlt_update_host_map(vp, id);
2c3dfe3f 3719
41dc529a
QT
3720 /*
3721 * Cannot configure here as we are still sitting on the
3722 * response queue. Handle it in dpc context.
3723 */
3724 set_bit(VP_IDX_ACQUIRED, &vp->vp_flags);
3725 set_bit(REGISTER_FC4_NEEDED, &vp->dpc_flags);
3726 set_bit(REGISTER_FDMI_NEEDED, &vp->dpc_flags);
3727 }
531a82d1 3728 set_bit(VP_DPC_NEEDED, &vha->dpc_flags);
7b867cf7 3729 qla2xxx_wake_dpc(vha);
41dc529a 3730 } else if (rptid_entry->format == 2) {
83548fe2 3731 ql_dbg(ql_dbg_async, vha, 0x505f,
41dc529a
QT
3732 "RIDA: format 2/N2N Primary port id %02x%02x%02x.\n",
3733 rptid_entry->port_id[2], rptid_entry->port_id[1],
3734 rptid_entry->port_id[0]);
3735
83548fe2 3736 ql_dbg(ql_dbg_async, vha, 0x5075,
41dc529a
QT
3737 "N2N: Remote WWPN %8phC.\n",
3738 rptid_entry->u.f2.port_name);
3739
3740 /* N2N. direct connect */
3741 vha->d_id.b.domain = rptid_entry->port_id[2];
3742 vha->d_id.b.area = rptid_entry->port_id[1];
3743 vha->d_id.b.al_pa = rptid_entry->port_id[0];
3744
3745 spin_lock_irqsave(&ha->vport_slock, flags);
3746 qlt_update_vp_map(vha, SET_AL_PA);
3747 spin_unlock_irqrestore(&ha->vport_slock, flags);
2c3dfe3f
SJ
3748 }
3749}
3750
3751/*
3752 * qla24xx_modify_vp_config
3753 * Change VP configuration for vha
3754 *
3755 * Input:
3756 * vha = adapter block pointer.
3757 *
3758 * Returns:
3759 * qla2xxx local function return status code.
3760 *
3761 * Context:
3762 * Kernel context.
3763 */
3764int
3765qla24xx_modify_vp_config(scsi_qla_host_t *vha)
3766{
3767 int rval;
3768 struct vp_config_entry_24xx *vpmod;
3769 dma_addr_t vpmod_dma;
7b867cf7
AC
3770 struct qla_hw_data *ha = vha->hw;
3771 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
2c3dfe3f
SJ
3772
3773 /* This can be called by the parent */
2c3dfe3f 3774
5f28d2d7
SK
3775 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10bb,
3776 "Entered %s.\n", __func__);
7c3df132 3777
7b867cf7 3778 vpmod = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &vpmod_dma);
2c3dfe3f 3779 if (!vpmod) {
7c3df132
SK
3780 ql_log(ql_log_warn, vha, 0x10bc,
3781 "Failed to allocate modify VP IOCB.\n");
2c3dfe3f
SJ
3782 return QLA_MEMORY_ALLOC_FAILED;
3783 }
3784
3785 memset(vpmod, 0, sizeof(struct vp_config_entry_24xx));
3786 vpmod->entry_type = VP_CONFIG_IOCB_TYPE;
3787 vpmod->entry_count = 1;
3788 vpmod->command = VCT_COMMAND_MOD_ENABLE_VPS;
3789 vpmod->vp_count = 1;
3790 vpmod->vp_index1 = vha->vp_idx;
3791 vpmod->options_idx1 = BIT_3|BIT_4|BIT_5;
2d70c103
NB
3792
3793 qlt_modify_vp_config(vha, vpmod);
3794
2c3dfe3f
SJ
3795 memcpy(vpmod->node_name_idx1, vha->node_name, WWN_SIZE);
3796 memcpy(vpmod->port_name_idx1, vha->port_name, WWN_SIZE);
3797 vpmod->entry_count = 1;
3798
7b867cf7 3799 rval = qla2x00_issue_iocb(base_vha, vpmod, vpmod_dma, 0);
2c3dfe3f 3800 if (rval != QLA_SUCCESS) {
7c3df132
SK
3801 ql_dbg(ql_dbg_mbx, vha, 0x10bd,
3802 "Failed to issue VP config IOCB (%x).\n", rval);
2c3dfe3f 3803 } else if (vpmod->comp_status != 0) {
7c3df132
SK
3804 ql_dbg(ql_dbg_mbx, vha, 0x10be,
3805 "Failed to complete IOCB -- error status (%x).\n",
3806 vpmod->comp_status);
2c3dfe3f 3807 rval = QLA_FUNCTION_FAILED;
ad950360 3808 } else if (vpmod->comp_status != cpu_to_le16(CS_COMPLETE)) {
7c3df132
SK
3809 ql_dbg(ql_dbg_mbx, vha, 0x10bf,
3810 "Failed to complete IOCB -- completion status (%x).\n",
3811 le16_to_cpu(vpmod->comp_status));
2c3dfe3f
SJ
3812 rval = QLA_FUNCTION_FAILED;
3813 } else {
3814 /* EMPTY */
5f28d2d7
SK
3815 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c0,
3816 "Done %s.\n", __func__);
2c3dfe3f
SJ
3817 fc_vport_set_state(vha->fc_vport, FC_VPORT_INITIALIZING);
3818 }
7b867cf7 3819 dma_pool_free(ha->s_dma_pool, vpmod, vpmod_dma);
2c3dfe3f
SJ
3820
3821 return rval;
3822}
3823
3824/*
3825 * qla24xx_control_vp
3826 * Enable a virtual port for given host
3827 *
3828 * Input:
3829 * ha = adapter block pointer.
3830 * vhba = virtual adapter (unused)
3831 * index = index number for enabled VP
3832 *
3833 * Returns:
3834 * qla2xxx local function return status code.
3835 *
3836 * Context:
3837 * Kernel context.
3838 */
3839int
3840qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
3841{
3842 int rval;
3843 int map, pos;
3844 struct vp_ctrl_entry_24xx *vce;
3845 dma_addr_t vce_dma;
7b867cf7 3846 struct qla_hw_data *ha = vha->hw;
2c3dfe3f 3847 int vp_index = vha->vp_idx;
7b867cf7 3848 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
2c3dfe3f 3849
5f28d2d7 3850 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c1,
7c3df132 3851 "Entered %s enabling index %d.\n", __func__, vp_index);
2c3dfe3f 3852
eb66dc60 3853 if (vp_index == 0 || vp_index >= ha->max_npiv_vports)
2c3dfe3f
SJ
3854 return QLA_PARAMETER_ERROR;
3855
3856 vce = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &vce_dma);
3857 if (!vce) {
7c3df132
SK
3858 ql_log(ql_log_warn, vha, 0x10c2,
3859 "Failed to allocate VP control IOCB.\n");
2c3dfe3f
SJ
3860 return QLA_MEMORY_ALLOC_FAILED;
3861 }
3862 memset(vce, 0, sizeof(struct vp_ctrl_entry_24xx));
3863
3864 vce->entry_type = VP_CTRL_IOCB_TYPE;
3865 vce->entry_count = 1;
3866 vce->command = cpu_to_le16(cmd);
ad950360 3867 vce->vp_count = cpu_to_le16(1);
2c3dfe3f
SJ
3868
3869 /* index map in firmware starts with 1; decrement index
3870 * this is ok as we never use index 0
3871 */
3872 map = (vp_index - 1) / 8;
3873 pos = (vp_index - 1) & 7;
6c2f527c 3874 mutex_lock(&ha->vport_lock);
2c3dfe3f 3875 vce->vp_idx_map[map] |= 1 << pos;
6c2f527c 3876 mutex_unlock(&ha->vport_lock);
2c3dfe3f 3877
7b867cf7 3878 rval = qla2x00_issue_iocb(base_vha, vce, vce_dma, 0);
2c3dfe3f 3879 if (rval != QLA_SUCCESS) {
7c3df132
SK
3880 ql_dbg(ql_dbg_mbx, vha, 0x10c3,
3881 "Failed to issue VP control IOCB (%x).\n", rval);
2c3dfe3f 3882 } else if (vce->entry_status != 0) {
7c3df132
SK
3883 ql_dbg(ql_dbg_mbx, vha, 0x10c4,
3884 "Failed to complete IOCB -- error status (%x).\n",
2c3dfe3f
SJ
3885 vce->entry_status);
3886 rval = QLA_FUNCTION_FAILED;
ad950360 3887 } else if (vce->comp_status != cpu_to_le16(CS_COMPLETE)) {
7c3df132 3888 ql_dbg(ql_dbg_mbx, vha, 0x10c5,
0bf0efa1 3889 "Failed to complete IOCB -- completion status (%x).\n",
2c3dfe3f
SJ
3890 le16_to_cpu(vce->comp_status));
3891 rval = QLA_FUNCTION_FAILED;
3892 } else {
5f28d2d7
SK
3893 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c6,
3894 "Done %s.\n", __func__);
2c3dfe3f
SJ
3895 }
3896
3897 dma_pool_free(ha->s_dma_pool, vce, vce_dma);
3898
3899 return rval;
3900}
3901
3902/*
3903 * qla2x00_send_change_request
3904 * Receive or disable RSCN request from fabric controller
3905 *
3906 * Input:
3907 * ha = adapter block pointer
3908 * format = registration format:
3909 * 0 - Reserved
3910 * 1 - Fabric detected registration
3911 * 2 - N_port detected registration
3912 * 3 - Full registration
3913 * FF - clear registration
3914 * vp_idx = Virtual port index
3915 *
3916 * Returns:
3917 * qla2x00 local function return status code.
3918 *
3919 * Context:
3920 * Kernel Context
3921 */
3922
3923int
7b867cf7 3924qla2x00_send_change_request(scsi_qla_host_t *vha, uint16_t format,
2c3dfe3f
SJ
3925 uint16_t vp_idx)
3926{
3927 int rval;
3928 mbx_cmd_t mc;
3929 mbx_cmd_t *mcp = &mc;
3930
5f28d2d7
SK
3931 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c7,
3932 "Entered %s.\n", __func__);
7c3df132 3933
2c3dfe3f
SJ
3934 mcp->mb[0] = MBC_SEND_CHANGE_REQUEST;
3935 mcp->mb[1] = format;
3936 mcp->mb[9] = vp_idx;
3937 mcp->out_mb = MBX_9|MBX_1|MBX_0;
3938 mcp->in_mb = MBX_0|MBX_1;
3939 mcp->tov = MBX_TOV_SECONDS;
3940 mcp->flags = 0;
7b867cf7 3941 rval = qla2x00_mailbox_command(vha, mcp);
2c3dfe3f
SJ
3942
3943 if (rval == QLA_SUCCESS) {
3944 if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
3945 rval = BIT_1;
3946 }
3947 } else
3948 rval = BIT_1;
3949
3950 return rval;
3951}
338c9161
AV
3952
3953int
7b867cf7 3954qla2x00_dump_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr,
338c9161
AV
3955 uint32_t size)
3956{
3957 int rval;
3958 mbx_cmd_t mc;
3959 mbx_cmd_t *mcp = &mc;
3960
5f28d2d7
SK
3961 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1009,
3962 "Entered %s.\n", __func__);
338c9161 3963
7b867cf7 3964 if (MSW(addr) || IS_FWI2_CAPABLE(vha->hw)) {
338c9161
AV
3965 mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED;
3966 mcp->mb[8] = MSW(addr);
3967 mcp->out_mb = MBX_8|MBX_0;
3968 } else {
3969 mcp->mb[0] = MBC_DUMP_RISC_RAM;
3970 mcp->out_mb = MBX_0;
3971 }
3972 mcp->mb[1] = LSW(addr);
3973 mcp->mb[2] = MSW(req_dma);
3974 mcp->mb[3] = LSW(req_dma);
3975 mcp->mb[6] = MSW(MSD(req_dma));
3976 mcp->mb[7] = LSW(MSD(req_dma));
3977 mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1;
7b867cf7 3978 if (IS_FWI2_CAPABLE(vha->hw)) {
338c9161
AV
3979 mcp->mb[4] = MSW(size);
3980 mcp->mb[5] = LSW(size);
3981 mcp->out_mb |= MBX_5|MBX_4;
3982 } else {
3983 mcp->mb[4] = LSW(size);
3984 mcp->out_mb |= MBX_4;
3985 }
3986
3987 mcp->in_mb = MBX_0;
b93480e3 3988 mcp->tov = MBX_TOV_SECONDS;
338c9161 3989 mcp->flags = 0;
7b867cf7 3990 rval = qla2x00_mailbox_command(vha, mcp);
338c9161
AV
3991
3992 if (rval != QLA_SUCCESS) {
7c3df132
SK
3993 ql_dbg(ql_dbg_mbx, vha, 0x1008,
3994 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
338c9161 3995 } else {
5f28d2d7
SK
3996 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1007,
3997 "Done %s.\n", __func__);
338c9161
AV
3998 }
3999
4000 return rval;
4001}
4d4df193
HK
4002/* 84XX Support **************************************************************/
4003
4004struct cs84xx_mgmt_cmd {
4005 union {
4006 struct verify_chip_entry_84xx req;
4007 struct verify_chip_rsp_84xx rsp;
4008 } p;
4009};
4010
4011int
7b867cf7 4012qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status)
4d4df193
HK
4013{
4014 int rval, retry;
4015 struct cs84xx_mgmt_cmd *mn;
4016 dma_addr_t mn_dma;
4017 uint16_t options;
4018 unsigned long flags;
7b867cf7 4019 struct qla_hw_data *ha = vha->hw;
4d4df193 4020
5f28d2d7
SK
4021 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c8,
4022 "Entered %s.\n", __func__);
4d4df193
HK
4023
4024 mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
4025 if (mn == NULL) {
4d4df193
HK
4026 return QLA_MEMORY_ALLOC_FAILED;
4027 }
4028
4029 /* Force Update? */
4030 options = ha->cs84xx->fw_update ? VCO_FORCE_UPDATE : 0;
4031 /* Diagnostic firmware? */
4032 /* options |= MENLO_DIAG_FW; */
4033 /* We update the firmware with only one data sequence. */
4034 options |= VCO_END_OF_DATA;
4035
4d4df193 4036 do {
c1ec1f1b 4037 retry = 0;
4d4df193
HK
4038 memset(mn, 0, sizeof(*mn));
4039 mn->p.req.entry_type = VERIFY_CHIP_IOCB_TYPE;
4040 mn->p.req.entry_count = 1;
4041 mn->p.req.options = cpu_to_le16(options);
4042
7c3df132
SK
4043 ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111c,
4044 "Dump of Verify Request.\n");
4045 ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111e,
4046 (uint8_t *)mn, sizeof(*mn));
4d4df193 4047
7b867cf7 4048 rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120);
4d4df193 4049 if (rval != QLA_SUCCESS) {
7c3df132
SK
4050 ql_dbg(ql_dbg_mbx, vha, 0x10cb,
4051 "Failed to issue verify IOCB (%x).\n", rval);
4d4df193
HK
4052 goto verify_done;
4053 }
4054
7c3df132
SK
4055 ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1110,
4056 "Dump of Verify Response.\n");
4057 ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1118,
4058 (uint8_t *)mn, sizeof(*mn));
4d4df193
HK
4059
4060 status[0] = le16_to_cpu(mn->p.rsp.comp_status);
4061 status[1] = status[0] == CS_VCS_CHIP_FAILURE ?
4062 le16_to_cpu(mn->p.rsp.failure_code) : 0;
5f28d2d7 4063 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ce,
7c3df132 4064 "cs=%x fc=%x.\n", status[0], status[1]);
4d4df193
HK
4065
4066 if (status[0] != CS_COMPLETE) {
4067 rval = QLA_FUNCTION_FAILED;
4068 if (!(options & VCO_DONT_UPDATE_FW)) {
7c3df132
SK
4069 ql_dbg(ql_dbg_mbx, vha, 0x10cf,
4070 "Firmware update failed. Retrying "
4071 "without update firmware.\n");
4d4df193
HK
4072 options |= VCO_DONT_UPDATE_FW;
4073 options &= ~VCO_FORCE_UPDATE;
4074 retry = 1;
4075 }
4076 } else {
5f28d2d7 4077 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d0,
7c3df132
SK
4078 "Firmware updated to %x.\n",
4079 le32_to_cpu(mn->p.rsp.fw_ver));
4d4df193
HK
4080
4081 /* NOTE: we only update OP firmware. */
4082 spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
4083 ha->cs84xx->op_fw_version =
4084 le32_to_cpu(mn->p.rsp.fw_ver);
4085 spin_unlock_irqrestore(&ha->cs84xx->access_lock,
4086 flags);
4087 }
4088 } while (retry);
4089
4090verify_done:
4091 dma_pool_free(ha->s_dma_pool, mn, mn_dma);
4092
4093 if (rval != QLA_SUCCESS) {
5f28d2d7
SK
4094 ql_dbg(ql_dbg_mbx, vha, 0x10d1,
4095 "Failed=%x.\n", rval);
4d4df193 4096 } else {
5f28d2d7
SK
4097 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d2,
4098 "Done %s.\n", __func__);
4d4df193
HK
4099 }
4100
4101 return rval;
4102}
73208dfd
AC
4103
4104int
618a7523 4105qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req)
73208dfd
AC
4106{
4107 int rval;
4108 unsigned long flags;
4109 mbx_cmd_t mc;
4110 mbx_cmd_t *mcp = &mc;
73208dfd
AC
4111 struct qla_hw_data *ha = vha->hw;
4112
5f28d2d7
SK
4113 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d3,
4114 "Entered %s.\n", __func__);
7c3df132 4115
7c6300e3
JC
4116 if (IS_SHADOW_REG_CAPABLE(ha))
4117 req->options |= BIT_13;
4118
73208dfd 4119 mcp->mb[0] = MBC_INITIALIZE_MULTIQ;
618a7523 4120 mcp->mb[1] = req->options;
73208dfd
AC
4121 mcp->mb[2] = MSW(LSD(req->dma));
4122 mcp->mb[3] = LSW(LSD(req->dma));
4123 mcp->mb[6] = MSW(MSD(req->dma));
4124 mcp->mb[7] = LSW(MSD(req->dma));
4125 mcp->mb[5] = req->length;
4126 if (req->rsp)
4127 mcp->mb[10] = req->rsp->id;
4128 mcp->mb[12] = req->qos;
4129 mcp->mb[11] = req->vp_idx;
4130 mcp->mb[13] = req->rid;
f73cb695 4131 if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
6246b8a1 4132 mcp->mb[15] = 0;
73208dfd 4133
73208dfd
AC
4134 mcp->mb[4] = req->id;
4135 /* que in ptr index */
4136 mcp->mb[8] = 0;
4137 /* que out ptr index */
7c6300e3 4138 mcp->mb[9] = *req->out_ptr = 0;
73208dfd
AC
4139 mcp->out_mb = MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|MBX_7|
4140 MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4141 mcp->in_mb = MBX_0;
4142 mcp->flags = MBX_DMA_OUT;
6246b8a1
GM
4143 mcp->tov = MBX_TOV_SECONDS * 2;
4144
f73cb695 4145 if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
6246b8a1 4146 mcp->in_mb |= MBX_1;
ba4828b7 4147 if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
6246b8a1
GM
4148 mcp->out_mb |= MBX_15;
4149 /* debug q create issue in SR-IOV */
4150 mcp->in_mb |= MBX_9 | MBX_8 | MBX_7;
4151 }
73208dfd
AC
4152
4153 spin_lock_irqsave(&ha->hardware_lock, flags);
618a7523 4154 if (!(req->options & BIT_0)) {
da9b1d5c 4155 WRT_REG_DWORD(req->req_q_in, 0);
29db41c3 4156 if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
da9b1d5c 4157 WRT_REG_DWORD(req->req_q_out, 0);
73208dfd
AC
4158 }
4159 spin_unlock_irqrestore(&ha->hardware_lock, flags);
4160
17d98630 4161 rval = qla2x00_mailbox_command(vha, mcp);
7c3df132
SK
4162 if (rval != QLA_SUCCESS) {
4163 ql_dbg(ql_dbg_mbx, vha, 0x10d4,
4164 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
4165 } else {
5f28d2d7
SK
4166 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d5,
4167 "Done %s.\n", __func__);
7c3df132
SK
4168 }
4169
73208dfd
AC
4170 return rval;
4171}
4172
4173int
618a7523 4174qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
73208dfd
AC
4175{
4176 int rval;
4177 unsigned long flags;
4178 mbx_cmd_t mc;
4179 mbx_cmd_t *mcp = &mc;
73208dfd
AC
4180 struct qla_hw_data *ha = vha->hw;
4181
5f28d2d7
SK
4182 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d6,
4183 "Entered %s.\n", __func__);
7c3df132 4184
7c6300e3
JC
4185 if (IS_SHADOW_REG_CAPABLE(ha))
4186 rsp->options |= BIT_13;
4187
73208dfd 4188 mcp->mb[0] = MBC_INITIALIZE_MULTIQ;
618a7523 4189 mcp->mb[1] = rsp->options;
73208dfd
AC
4190 mcp->mb[2] = MSW(LSD(rsp->dma));
4191 mcp->mb[3] = LSW(LSD(rsp->dma));
4192 mcp->mb[6] = MSW(MSD(rsp->dma));
4193 mcp->mb[7] = LSW(MSD(rsp->dma));
4194 mcp->mb[5] = rsp->length;
444786d7 4195 mcp->mb[14] = rsp->msix->entry;
73208dfd 4196 mcp->mb[13] = rsp->rid;
f73cb695 4197 if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
6246b8a1 4198 mcp->mb[15] = 0;
73208dfd 4199
73208dfd
AC
4200 mcp->mb[4] = rsp->id;
4201 /* que in ptr index */
7c6300e3 4202 mcp->mb[8] = *rsp->in_ptr = 0;
73208dfd
AC
4203 /* que out ptr index */
4204 mcp->mb[9] = 0;
2afa19a9 4205 mcp->out_mb = MBX_14|MBX_13|MBX_9|MBX_8|MBX_7
73208dfd
AC
4206 |MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4207 mcp->in_mb = MBX_0;
4208 mcp->flags = MBX_DMA_OUT;
6246b8a1
GM
4209 mcp->tov = MBX_TOV_SECONDS * 2;
4210
4211 if (IS_QLA81XX(ha)) {
4212 mcp->out_mb |= MBX_12|MBX_11|MBX_10;
4213 mcp->in_mb |= MBX_1;
f73cb695 4214 } else if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
6246b8a1
GM
4215 mcp->out_mb |= MBX_15|MBX_12|MBX_11|MBX_10;
4216 mcp->in_mb |= MBX_1;
4217 /* debug q create issue in SR-IOV */
4218 mcp->in_mb |= MBX_9 | MBX_8 | MBX_7;
4219 }
73208dfd
AC
4220
4221 spin_lock_irqsave(&ha->hardware_lock, flags);
618a7523 4222 if (!(rsp->options & BIT_0)) {
da9b1d5c 4223 WRT_REG_DWORD(rsp->rsp_q_out, 0);
b20f02e1 4224 if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
da9b1d5c 4225 WRT_REG_DWORD(rsp->rsp_q_in, 0);
73208dfd
AC
4226 }
4227
4228 spin_unlock_irqrestore(&ha->hardware_lock, flags);
4229
17d98630 4230 rval = qla2x00_mailbox_command(vha, mcp);
7c3df132
SK
4231 if (rval != QLA_SUCCESS) {
4232 ql_dbg(ql_dbg_mbx, vha, 0x10d7,
4233 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
4234 } else {
5f28d2d7
SK
4235 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d8,
4236 "Done %s.\n", __func__);
7c3df132
SK
4237 }
4238
73208dfd
AC
4239 return rval;
4240}
4241
8a659571
AV
4242int
4243qla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb)
4244{
4245 int rval;
4246 mbx_cmd_t mc;
4247 mbx_cmd_t *mcp = &mc;
4248
5f28d2d7
SK
4249 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d9,
4250 "Entered %s.\n", __func__);
8a659571
AV
4251
4252 mcp->mb[0] = MBC_IDC_ACK;
4253 memcpy(&mcp->mb[1], mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
4254 mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4255 mcp->in_mb = MBX_0;
4256 mcp->tov = MBX_TOV_SECONDS;
4257 mcp->flags = 0;
4258 rval = qla2x00_mailbox_command(vha, mcp);
4259
4260 if (rval != QLA_SUCCESS) {
7c3df132
SK
4261 ql_dbg(ql_dbg_mbx, vha, 0x10da,
4262 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
8a659571 4263 } else {
5f28d2d7
SK
4264 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10db,
4265 "Done %s.\n", __func__);
8a659571
AV
4266 }
4267
4268 return rval;
4269}
1d2874de
JC
4270
4271int
4272qla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size)
4273{
4274 int rval;
4275 mbx_cmd_t mc;
4276 mbx_cmd_t *mcp = &mc;
4277
5f28d2d7
SK
4278 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10dc,
4279 "Entered %s.\n", __func__);
7c3df132 4280
f73cb695
CD
4281 if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) &&
4282 !IS_QLA27XX(vha->hw))
1d2874de
JC
4283 return QLA_FUNCTION_FAILED;
4284
1d2874de
JC
4285 mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
4286 mcp->mb[1] = FAC_OPT_CMD_GET_SECTOR_SIZE;
4287 mcp->out_mb = MBX_1|MBX_0;
4288 mcp->in_mb = MBX_1|MBX_0;
4289 mcp->tov = MBX_TOV_SECONDS;
4290 mcp->flags = 0;
4291 rval = qla2x00_mailbox_command(vha, mcp);
4292
4293 if (rval != QLA_SUCCESS) {
7c3df132
SK
4294 ql_dbg(ql_dbg_mbx, vha, 0x10dd,
4295 "Failed=%x mb[0]=%x mb[1]=%x.\n",
4296 rval, mcp->mb[0], mcp->mb[1]);
1d2874de 4297 } else {
5f28d2d7
SK
4298 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10de,
4299 "Done %s.\n", __func__);
1d2874de
JC
4300 *sector_size = mcp->mb[1];
4301 }
4302
4303 return rval;
4304}
4305
4306int
4307qla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable)
4308{
4309 int rval;
4310 mbx_cmd_t mc;
4311 mbx_cmd_t *mcp = &mc;
4312
f73cb695
CD
4313 if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) &&
4314 !IS_QLA27XX(vha->hw))
1d2874de
JC
4315 return QLA_FUNCTION_FAILED;
4316
5f28d2d7
SK
4317 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10df,
4318 "Entered %s.\n", __func__);
1d2874de
JC
4319
4320 mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
4321 mcp->mb[1] = enable ? FAC_OPT_CMD_WRITE_ENABLE :
4322 FAC_OPT_CMD_WRITE_PROTECT;
4323 mcp->out_mb = MBX_1|MBX_0;
4324 mcp->in_mb = MBX_1|MBX_0;
4325 mcp->tov = MBX_TOV_SECONDS;
4326 mcp->flags = 0;
4327 rval = qla2x00_mailbox_command(vha, mcp);
4328
4329 if (rval != QLA_SUCCESS) {
7c3df132
SK
4330 ql_dbg(ql_dbg_mbx, vha, 0x10e0,
4331 "Failed=%x mb[0]=%x mb[1]=%x.\n",
4332 rval, mcp->mb[0], mcp->mb[1]);
1d2874de 4333 } else {
5f28d2d7
SK
4334 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e1,
4335 "Done %s.\n", __func__);
1d2874de
JC
4336 }
4337
4338 return rval;
4339}
4340
4341int
4342qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish)
4343{
4344 int rval;
4345 mbx_cmd_t mc;
4346 mbx_cmd_t *mcp = &mc;
4347
f73cb695
CD
4348 if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) &&
4349 !IS_QLA27XX(vha->hw))
1d2874de
JC
4350 return QLA_FUNCTION_FAILED;
4351
5f28d2d7
SK
4352 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e2,
4353 "Entered %s.\n", __func__);
1d2874de
JC
4354
4355 mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
4356 mcp->mb[1] = FAC_OPT_CMD_ERASE_SECTOR;
4357 mcp->mb[2] = LSW(start);
4358 mcp->mb[3] = MSW(start);
4359 mcp->mb[4] = LSW(finish);
4360 mcp->mb[5] = MSW(finish);
4361 mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4362 mcp->in_mb = MBX_2|MBX_1|MBX_0;
4363 mcp->tov = MBX_TOV_SECONDS;
4364 mcp->flags = 0;
4365 rval = qla2x00_mailbox_command(vha, mcp);
4366
4367 if (rval != QLA_SUCCESS) {
7c3df132
SK
4368 ql_dbg(ql_dbg_mbx, vha, 0x10e3,
4369 "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
4370 rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
1d2874de 4371 } else {
5f28d2d7
SK
4372 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e4,
4373 "Done %s.\n", __func__);
1d2874de
JC
4374 }
4375
4376 return rval;
4377}
6e181be5
LC
4378
4379int
4380qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha)
4381{
4382 int rval = 0;
4383 mbx_cmd_t mc;
4384 mbx_cmd_t *mcp = &mc;
4385
5f28d2d7
SK
4386 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e5,
4387 "Entered %s.\n", __func__);
6e181be5
LC
4388
4389 mcp->mb[0] = MBC_RESTART_MPI_FW;
4390 mcp->out_mb = MBX_0;
4391 mcp->in_mb = MBX_0|MBX_1;
4392 mcp->tov = MBX_TOV_SECONDS;
4393 mcp->flags = 0;
4394 rval = qla2x00_mailbox_command(vha, mcp);
4395
4396 if (rval != QLA_SUCCESS) {
7c3df132
SK
4397 ql_dbg(ql_dbg_mbx, vha, 0x10e6,
4398 "Failed=%x mb[0]=%x mb[1]=%x.\n",
4399 rval, mcp->mb[0], mcp->mb[1]);
6e181be5 4400 } else {
5f28d2d7
SK
4401 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e7,
4402 "Done %s.\n", __func__);
6e181be5
LC
4403 }
4404
4405 return rval;
4406}
ad0ecd61 4407
c46e65c7
JC
4408int
4409qla82xx_set_driver_version(scsi_qla_host_t *vha, char *version)
4410{
4411 int rval;
4412 mbx_cmd_t mc;
4413 mbx_cmd_t *mcp = &mc;
4414 int i;
4415 int len;
4416 uint16_t *str;
4417 struct qla_hw_data *ha = vha->hw;
4418
4419 if (!IS_P3P_TYPE(ha))
4420 return QLA_FUNCTION_FAILED;
4421
4422 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x117b,
4423 "Entered %s.\n", __func__);
4424
4425 str = (void *)version;
4426 len = strlen(version);
4427
4428 mcp->mb[0] = MBC_SET_RNID_PARAMS;
4429 mcp->mb[1] = RNID_TYPE_SET_VERSION << 8;
4430 mcp->out_mb = MBX_1|MBX_0;
4431 for (i = 4; i < 16 && len; i++, str++, len -= 2) {
4432 mcp->mb[i] = cpu_to_le16p(str);
4433 mcp->out_mb |= 1<<i;
4434 }
4435 for (; i < 16; i++) {
4436 mcp->mb[i] = 0;
4437 mcp->out_mb |= 1<<i;
4438 }
4439 mcp->in_mb = MBX_1|MBX_0;
4440 mcp->tov = MBX_TOV_SECONDS;
4441 mcp->flags = 0;
4442 rval = qla2x00_mailbox_command(vha, mcp);
4443
4444 if (rval != QLA_SUCCESS) {
4445 ql_dbg(ql_dbg_mbx, vha, 0x117c,
4446 "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]);
4447 } else {
4448 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x117d,
4449 "Done %s.\n", __func__);
4450 }
4451
4452 return rval;
4453}
4454
4455int
4456qla25xx_set_driver_version(scsi_qla_host_t *vha, char *version)
4457{
4458 int rval;
4459 mbx_cmd_t mc;
4460 mbx_cmd_t *mcp = &mc;
4461 int len;
4462 uint16_t dwlen;
4463 uint8_t *str;
4464 dma_addr_t str_dma;
4465 struct qla_hw_data *ha = vha->hw;
4466
4467 if (!IS_FWI2_CAPABLE(ha) || IS_QLA24XX_TYPE(ha) || IS_QLA81XX(ha) ||
4468 IS_P3P_TYPE(ha))
4469 return QLA_FUNCTION_FAILED;
4470
4471 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x117e,
4472 "Entered %s.\n", __func__);
4473
4474 str = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &str_dma);
4475 if (!str) {
4476 ql_log(ql_log_warn, vha, 0x117f,
4477 "Failed to allocate driver version param.\n");
4478 return QLA_MEMORY_ALLOC_FAILED;
4479 }
4480
4481 memcpy(str, "\x7\x3\x11\x0", 4);
4482 dwlen = str[0];
4483 len = dwlen * 4 - 4;
4484 memset(str + 4, 0, len);
4485 if (len > strlen(version))
4486 len = strlen(version);
4487 memcpy(str + 4, version, len);
4488
4489 mcp->mb[0] = MBC_SET_RNID_PARAMS;
4490 mcp->mb[1] = RNID_TYPE_SET_VERSION << 8 | dwlen;
4491 mcp->mb[2] = MSW(LSD(str_dma));
4492 mcp->mb[3] = LSW(LSD(str_dma));
4493 mcp->mb[6] = MSW(MSD(str_dma));
4494 mcp->mb[7] = LSW(MSD(str_dma));
4495 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
4496 mcp->in_mb = MBX_1|MBX_0;
4497 mcp->tov = MBX_TOV_SECONDS;
4498 mcp->flags = 0;
4499 rval = qla2x00_mailbox_command(vha, mcp);
4500
4501 if (rval != QLA_SUCCESS) {
4502 ql_dbg(ql_dbg_mbx, vha, 0x1180,
4503 "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]);
4504 } else {
4505 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1181,
4506 "Done %s.\n", __func__);
4507 }
4508
4509 dma_pool_free(ha->s_dma_pool, str, str_dma);
4510
4511 return rval;
4512}
4513
fe52f6e1
JC
4514static int
4515qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp)
4516{
4517 int rval;
4518 mbx_cmd_t mc;
4519 mbx_cmd_t *mcp = &mc;
4520
4521 if (!IS_FWI2_CAPABLE(vha->hw))
4522 return QLA_FUNCTION_FAILED;
4523
4524 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1159,
4525 "Entered %s.\n", __func__);
4526
4527 mcp->mb[0] = MBC_GET_RNID_PARAMS;
4528 mcp->mb[1] = RNID_TYPE_ASIC_TEMP << 8;
4529 mcp->out_mb = MBX_1|MBX_0;
4530 mcp->in_mb = MBX_1|MBX_0;
4531 mcp->tov = MBX_TOV_SECONDS;
4532 mcp->flags = 0;
4533 rval = qla2x00_mailbox_command(vha, mcp);
4534 *temp = mcp->mb[1];
4535
4536 if (rval != QLA_SUCCESS) {
4537 ql_dbg(ql_dbg_mbx, vha, 0x115a,
4538 "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]);
4539 } else {
4540 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x115b,
4541 "Done %s.\n", __func__);
4542 }
4543
4544 return rval;
4545}
4546
ad0ecd61 4547int
6766df9e
JC
4548qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp,
4549 uint16_t dev, uint16_t off, uint16_t len, uint16_t opt)
ad0ecd61
JC
4550{
4551 int rval;
4552 mbx_cmd_t mc;
4553 mbx_cmd_t *mcp = &mc;
6766df9e
JC
4554 struct qla_hw_data *ha = vha->hw;
4555
5f28d2d7
SK
4556 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e8,
4557 "Entered %s.\n", __func__);
7c3df132 4558
6766df9e
JC
4559 if (!IS_FWI2_CAPABLE(ha))
4560 return QLA_FUNCTION_FAILED;
ad0ecd61 4561
6766df9e
JC
4562 if (len == 1)
4563 opt |= BIT_0;
4564
ad0ecd61
JC
4565 mcp->mb[0] = MBC_READ_SFP;
4566 mcp->mb[1] = dev;
4567 mcp->mb[2] = MSW(sfp_dma);
4568 mcp->mb[3] = LSW(sfp_dma);
4569 mcp->mb[6] = MSW(MSD(sfp_dma));
4570 mcp->mb[7] = LSW(MSD(sfp_dma));
4571 mcp->mb[8] = len;
6766df9e 4572 mcp->mb[9] = off;
ad0ecd61
JC
4573 mcp->mb[10] = opt;
4574 mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
1bff6cc8 4575 mcp->in_mb = MBX_1|MBX_0;
ad0ecd61
JC
4576 mcp->tov = MBX_TOV_SECONDS;
4577 mcp->flags = 0;
4578 rval = qla2x00_mailbox_command(vha, mcp);
4579
4580 if (opt & BIT_0)
6766df9e 4581 *sfp = mcp->mb[1];
ad0ecd61
JC
4582
4583 if (rval != QLA_SUCCESS) {
7c3df132
SK
4584 ql_dbg(ql_dbg_mbx, vha, 0x10e9,
4585 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
ad0ecd61 4586 } else {
5f28d2d7
SK
4587 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea,
4588 "Done %s.\n", __func__);
ad0ecd61
JC
4589 }
4590
4591 return rval;
4592}
4593
4594int
6766df9e
JC
4595qla2x00_write_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp,
4596 uint16_t dev, uint16_t off, uint16_t len, uint16_t opt)
ad0ecd61
JC
4597{
4598 int rval;
4599 mbx_cmd_t mc;
4600 mbx_cmd_t *mcp = &mc;
6766df9e
JC
4601 struct qla_hw_data *ha = vha->hw;
4602
5f28d2d7
SK
4603 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10eb,
4604 "Entered %s.\n", __func__);
7c3df132 4605
6766df9e
JC
4606 if (!IS_FWI2_CAPABLE(ha))
4607 return QLA_FUNCTION_FAILED;
ad0ecd61 4608
6766df9e
JC
4609 if (len == 1)
4610 opt |= BIT_0;
4611
ad0ecd61 4612 if (opt & BIT_0)
6766df9e 4613 len = *sfp;
ad0ecd61
JC
4614
4615 mcp->mb[0] = MBC_WRITE_SFP;
4616 mcp->mb[1] = dev;
4617 mcp->mb[2] = MSW(sfp_dma);
4618 mcp->mb[3] = LSW(sfp_dma);
4619 mcp->mb[6] = MSW(MSD(sfp_dma));
4620 mcp->mb[7] = LSW(MSD(sfp_dma));
4621 mcp->mb[8] = len;
6766df9e 4622 mcp->mb[9] = off;
ad0ecd61
JC
4623 mcp->mb[10] = opt;
4624 mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
6766df9e 4625 mcp->in_mb = MBX_1|MBX_0;
ad0ecd61
JC
4626 mcp->tov = MBX_TOV_SECONDS;
4627 mcp->flags = 0;
4628 rval = qla2x00_mailbox_command(vha, mcp);
4629
4630 if (rval != QLA_SUCCESS) {
7c3df132
SK
4631 ql_dbg(ql_dbg_mbx, vha, 0x10ec,
4632 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
ad0ecd61 4633 } else {
5f28d2d7
SK
4634 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ed,
4635 "Done %s.\n", __func__);
ad0ecd61
JC
4636 }
4637
4638 return rval;
4639}
ce0423f4
AV
4640
4641int
4642qla2x00_get_xgmac_stats(scsi_qla_host_t *vha, dma_addr_t stats_dma,
4643 uint16_t size_in_bytes, uint16_t *actual_size)
4644{
4645 int rval;
4646 mbx_cmd_t mc;
4647 mbx_cmd_t *mcp = &mc;
4648
5f28d2d7
SK
4649 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ee,
4650 "Entered %s.\n", __func__);
7c3df132 4651
6246b8a1 4652 if (!IS_CNA_CAPABLE(vha->hw))
ce0423f4
AV
4653 return QLA_FUNCTION_FAILED;
4654
ce0423f4
AV
4655 mcp->mb[0] = MBC_GET_XGMAC_STATS;
4656 mcp->mb[2] = MSW(stats_dma);
4657 mcp->mb[3] = LSW(stats_dma);
4658 mcp->mb[6] = MSW(MSD(stats_dma));
4659 mcp->mb[7] = LSW(MSD(stats_dma));
4660 mcp->mb[8] = size_in_bytes >> 2;
4661 mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
4662 mcp->in_mb = MBX_2|MBX_1|MBX_0;
4663 mcp->tov = MBX_TOV_SECONDS;
4664 mcp->flags = 0;
4665 rval = qla2x00_mailbox_command(vha, mcp);
4666
4667 if (rval != QLA_SUCCESS) {
7c3df132
SK
4668 ql_dbg(ql_dbg_mbx, vha, 0x10ef,
4669 "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
4670 rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
ce0423f4 4671 } else {
5f28d2d7
SK
4672 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f0,
4673 "Done %s.\n", __func__);
7c3df132 4674
ce0423f4
AV
4675
4676 *actual_size = mcp->mb[2] << 2;
4677 }
4678
4679 return rval;
4680}
11bbc1d8
AV
4681
4682int
4683qla2x00_get_dcbx_params(scsi_qla_host_t *vha, dma_addr_t tlv_dma,
4684 uint16_t size)
4685{
4686 int rval;
4687 mbx_cmd_t mc;
4688 mbx_cmd_t *mcp = &mc;
4689
5f28d2d7
SK
4690 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f1,
4691 "Entered %s.\n", __func__);
7c3df132 4692
6246b8a1 4693 if (!IS_CNA_CAPABLE(vha->hw))
11bbc1d8
AV
4694 return QLA_FUNCTION_FAILED;
4695
11bbc1d8
AV
4696 mcp->mb[0] = MBC_GET_DCBX_PARAMS;
4697 mcp->mb[1] = 0;
4698 mcp->mb[2] = MSW(tlv_dma);
4699 mcp->mb[3] = LSW(tlv_dma);
4700 mcp->mb[6] = MSW(MSD(tlv_dma));
4701 mcp->mb[7] = LSW(MSD(tlv_dma));
4702 mcp->mb[8] = size;
4703 mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
4704 mcp->in_mb = MBX_2|MBX_1|MBX_0;
4705 mcp->tov = MBX_TOV_SECONDS;
4706 mcp->flags = 0;
4707 rval = qla2x00_mailbox_command(vha, mcp);
4708
4709 if (rval != QLA_SUCCESS) {
7c3df132
SK
4710 ql_dbg(ql_dbg_mbx, vha, 0x10f2,
4711 "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
4712 rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
11bbc1d8 4713 } else {
5f28d2d7
SK
4714 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f3,
4715 "Done %s.\n", __func__);
11bbc1d8
AV
4716 }
4717
4718 return rval;
4719}
18e7555a
AV
4720
4721int
4722qla2x00_read_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t *data)
4723{
4724 int rval;
4725 mbx_cmd_t mc;
4726 mbx_cmd_t *mcp = &mc;
4727
5f28d2d7
SK
4728 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f4,
4729 "Entered %s.\n", __func__);
7c3df132 4730
18e7555a
AV
4731 if (!IS_FWI2_CAPABLE(vha->hw))
4732 return QLA_FUNCTION_FAILED;
4733
18e7555a
AV
4734 mcp->mb[0] = MBC_READ_RAM_EXTENDED;
4735 mcp->mb[1] = LSW(risc_addr);
4736 mcp->mb[8] = MSW(risc_addr);
4737 mcp->out_mb = MBX_8|MBX_1|MBX_0;
4738 mcp->in_mb = MBX_3|MBX_2|MBX_0;
4739 mcp->tov = 30;
4740 mcp->flags = 0;
4741 rval = qla2x00_mailbox_command(vha, mcp);
4742 if (rval != QLA_SUCCESS) {
7c3df132
SK
4743 ql_dbg(ql_dbg_mbx, vha, 0x10f5,
4744 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
18e7555a 4745 } else {
5f28d2d7
SK
4746 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f6,
4747 "Done %s.\n", __func__);
18e7555a
AV
4748 *data = mcp->mb[3] << 16 | mcp->mb[2];
4749 }
4750
4751 return rval;
4752}
4753
9a069e19 4754int
a9083016
GM
4755qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
4756 uint16_t *mresp)
9a069e19
GM
4757{
4758 int rval;
4759 mbx_cmd_t mc;
4760 mbx_cmd_t *mcp = &mc;
9a069e19 4761
5f28d2d7
SK
4762 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f7,
4763 "Entered %s.\n", __func__);
9a069e19
GM
4764
4765 memset(mcp->mb, 0 , sizeof(mcp->mb));
4766 mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
4767 mcp->mb[1] = mreq->options | BIT_6; // BIT_6 specifies 64 bit addressing
4768
4769 /* transfer count */
4770 mcp->mb[10] = LSW(mreq->transfer_size);
4771 mcp->mb[11] = MSW(mreq->transfer_size);
4772
4773 /* send data address */
4774 mcp->mb[14] = LSW(mreq->send_dma);
4775 mcp->mb[15] = MSW(mreq->send_dma);
4776 mcp->mb[20] = LSW(MSD(mreq->send_dma));
4777 mcp->mb[21] = MSW(MSD(mreq->send_dma));
4778
25985edc 4779 /* receive data address */
9a069e19
GM
4780 mcp->mb[16] = LSW(mreq->rcv_dma);
4781 mcp->mb[17] = MSW(mreq->rcv_dma);
4782 mcp->mb[6] = LSW(MSD(mreq->rcv_dma));
4783 mcp->mb[7] = MSW(MSD(mreq->rcv_dma));
4784
4785 /* Iteration count */
1b98b421
JC
4786 mcp->mb[18] = LSW(mreq->iteration_count);
4787 mcp->mb[19] = MSW(mreq->iteration_count);
9a069e19
GM
4788
4789 mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
4790 MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0;
6246b8a1 4791 if (IS_CNA_CAPABLE(vha->hw))
9a069e19
GM
4792 mcp->out_mb |= MBX_2;
4793 mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0;
4794
4795 mcp->buf_size = mreq->transfer_size;
4796 mcp->tov = MBX_TOV_SECONDS;
4797 mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
4798
4799 rval = qla2x00_mailbox_command(vha, mcp);
4800
4801 if (rval != QLA_SUCCESS) {
7c3df132
SK
4802 ql_dbg(ql_dbg_mbx, vha, 0x10f8,
4803 "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[3]=%x mb[18]=%x "
4804 "mb[19]=%x.\n", rval, mcp->mb[0], mcp->mb[1], mcp->mb[2],
4805 mcp->mb[3], mcp->mb[18], mcp->mb[19]);
9a069e19 4806 } else {
5f28d2d7
SK
4807 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f9,
4808 "Done %s.\n", __func__);
9a069e19
GM
4809 }
4810
4811 /* Copy mailbox information */
4812 memcpy( mresp, mcp->mb, 64);
9a069e19
GM
4813 return rval;
4814}
4815
4816int
a9083016
GM
4817qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
4818 uint16_t *mresp)
9a069e19
GM
4819{
4820 int rval;
4821 mbx_cmd_t mc;
4822 mbx_cmd_t *mcp = &mc;
4823 struct qla_hw_data *ha = vha->hw;
4824
5f28d2d7
SK
4825 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10fa,
4826 "Entered %s.\n", __func__);
9a069e19
GM
4827
4828 memset(mcp->mb, 0 , sizeof(mcp->mb));
4829 mcp->mb[0] = MBC_DIAGNOSTIC_ECHO;
1d634965
JC
4830 /* BIT_6 specifies 64bit address */
4831 mcp->mb[1] = mreq->options | BIT_15 | BIT_6;
6246b8a1 4832 if (IS_CNA_CAPABLE(ha)) {
a9083016
GM
4833 mcp->mb[2] = vha->fcoe_fcf_idx;
4834 }
9a069e19
GM
4835 mcp->mb[16] = LSW(mreq->rcv_dma);
4836 mcp->mb[17] = MSW(mreq->rcv_dma);
4837 mcp->mb[6] = LSW(MSD(mreq->rcv_dma));
4838 mcp->mb[7] = MSW(MSD(mreq->rcv_dma));
4839
4840 mcp->mb[10] = LSW(mreq->transfer_size);
4841
4842 mcp->mb[14] = LSW(mreq->send_dma);
4843 mcp->mb[15] = MSW(mreq->send_dma);
4844 mcp->mb[20] = LSW(MSD(mreq->send_dma));
4845 mcp->mb[21] = MSW(MSD(mreq->send_dma));
4846
4847 mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15|
4848 MBX_14|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0;
6246b8a1 4849 if (IS_CNA_CAPABLE(ha))
9a069e19
GM
4850 mcp->out_mb |= MBX_2;
4851
4852 mcp->in_mb = MBX_0;
6246b8a1
GM
4853 if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) ||
4854 IS_CNA_CAPABLE(ha) || IS_QLA2031(ha))
9a069e19 4855 mcp->in_mb |= MBX_1;
6246b8a1 4856 if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha))
9a069e19
GM
4857 mcp->in_mb |= MBX_3;
4858
4859 mcp->tov = MBX_TOV_SECONDS;
4860 mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
4861 mcp->buf_size = mreq->transfer_size;
4862
4863 rval = qla2x00_mailbox_command(vha, mcp);
4864
4865 if (rval != QLA_SUCCESS) {
7c3df132
SK
4866 ql_dbg(ql_dbg_mbx, vha, 0x10fb,
4867 "Failed=%x mb[0]=%x mb[1]=%x.\n",
4868 rval, mcp->mb[0], mcp->mb[1]);
9a069e19 4869 } else {
5f28d2d7
SK
4870 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10fc,
4871 "Done %s.\n", __func__);
9a069e19
GM
4872 }
4873
4874 /* Copy mailbox information */
6dbdda4d 4875 memcpy(mresp, mcp->mb, 64);
9a069e19
GM
4876 return rval;
4877}
6dbdda4d 4878
9a069e19 4879int
7c3df132 4880qla84xx_reset_chip(scsi_qla_host_t *vha, uint16_t enable_diagnostic)
9a069e19
GM
4881{
4882 int rval;
4883 mbx_cmd_t mc;
4884 mbx_cmd_t *mcp = &mc;
4885
5f28d2d7 4886 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10fd,
7c3df132 4887 "Entered %s enable_diag=%d.\n", __func__, enable_diagnostic);
9a069e19
GM
4888
4889 mcp->mb[0] = MBC_ISP84XX_RESET;
4890 mcp->mb[1] = enable_diagnostic;
4891 mcp->out_mb = MBX_1|MBX_0;
4892 mcp->in_mb = MBX_1|MBX_0;
4893 mcp->tov = MBX_TOV_SECONDS;
4894 mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
7c3df132 4895 rval = qla2x00_mailbox_command(vha, mcp);
9a069e19 4896
9a069e19 4897 if (rval != QLA_SUCCESS)
7c3df132 4898 ql_dbg(ql_dbg_mbx, vha, 0x10fe, "Failed=%x.\n", rval);
9a069e19 4899 else
5f28d2d7
SK
4900 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ff,
4901 "Done %s.\n", __func__);
9a069e19
GM
4902
4903 return rval;
4904}
4905
18e7555a
AV
4906int
4907qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data)
4908{
4909 int rval;
4910 mbx_cmd_t mc;
4911 mbx_cmd_t *mcp = &mc;
4912
5f28d2d7
SK
4913 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1100,
4914 "Entered %s.\n", __func__);
7c3df132 4915
18e7555a 4916 if (!IS_FWI2_CAPABLE(vha->hw))
6c452a45 4917 return QLA_FUNCTION_FAILED;
18e7555a 4918
18e7555a
AV
4919 mcp->mb[0] = MBC_WRITE_RAM_WORD_EXTENDED;
4920 mcp->mb[1] = LSW(risc_addr);
4921 mcp->mb[2] = LSW(data);
4922 mcp->mb[3] = MSW(data);
4923 mcp->mb[8] = MSW(risc_addr);
4924 mcp->out_mb = MBX_8|MBX_3|MBX_2|MBX_1|MBX_0;
4925 mcp->in_mb = MBX_0;
4926 mcp->tov = 30;
4927 mcp->flags = 0;
4928 rval = qla2x00_mailbox_command(vha, mcp);
4929 if (rval != QLA_SUCCESS) {
7c3df132
SK
4930 ql_dbg(ql_dbg_mbx, vha, 0x1101,
4931 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
18e7555a 4932 } else {
5f28d2d7
SK
4933 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1102,
4934 "Done %s.\n", __func__);
18e7555a
AV
4935 }
4936
4937 return rval;
4938}
3064ff39 4939
b1d46989
MI
4940int
4941qla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb)
4942{
4943 int rval;
4944 uint32_t stat, timer;
4945 uint16_t mb0 = 0;
4946 struct qla_hw_data *ha = vha->hw;
4947 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
4948
4949 rval = QLA_SUCCESS;
4950
5f28d2d7
SK
4951 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1103,
4952 "Entered %s.\n", __func__);
b1d46989
MI
4953
4954 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
4955
4956 /* Write the MBC data to the registers */
4957 WRT_REG_WORD(&reg->mailbox0, MBC_WRITE_MPI_REGISTER);
4958 WRT_REG_WORD(&reg->mailbox1, mb[0]);
4959 WRT_REG_WORD(&reg->mailbox2, mb[1]);
4960 WRT_REG_WORD(&reg->mailbox3, mb[2]);
4961 WRT_REG_WORD(&reg->mailbox4, mb[3]);
4962
4963 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_HOST_INT);
4964
4965 /* Poll for MBC interrupt */
4966 for (timer = 6000000; timer; timer--) {
4967 /* Check for pending interrupts. */
4968 stat = RD_REG_DWORD(&reg->host_status);
4969 if (stat & HSRX_RISC_INT) {
4970 stat &= 0xff;
4971
4972 if (stat == 0x1 || stat == 0x2 ||
4973 stat == 0x10 || stat == 0x11) {
4974 set_bit(MBX_INTERRUPT,
4975 &ha->mbx_cmd_flags);
4976 mb0 = RD_REG_WORD(&reg->mailbox0);
4977 WRT_REG_DWORD(&reg->hccr,
4978 HCCRX_CLR_RISC_INT);
4979 RD_REG_DWORD(&reg->hccr);
4980 break;
4981 }
4982 }
4983 udelay(5);
4984 }
4985
4986 if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags))
4987 rval = mb0 & MBS_MASK;
4988 else
4989 rval = QLA_FUNCTION_FAILED;
4990
4991 if (rval != QLA_SUCCESS) {
7c3df132
SK
4992 ql_dbg(ql_dbg_mbx, vha, 0x1104,
4993 "Failed=%x mb[0]=%x.\n", rval, mb[0]);
b1d46989 4994 } else {
5f28d2d7
SK
4995 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1105,
4996 "Done %s.\n", __func__);
b1d46989
MI
4997 }
4998
4999 return rval;
5000}
6246b8a1 5001
3064ff39
MH
5002int
5003qla2x00_get_data_rate(scsi_qla_host_t *vha)
5004{
5005 int rval;
5006 mbx_cmd_t mc;
5007 mbx_cmd_t *mcp = &mc;
5008 struct qla_hw_data *ha = vha->hw;
5009
5f28d2d7
SK
5010 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1106,
5011 "Entered %s.\n", __func__);
7c3df132 5012
3064ff39
MH
5013 if (!IS_FWI2_CAPABLE(ha))
5014 return QLA_FUNCTION_FAILED;
5015
3064ff39
MH
5016 mcp->mb[0] = MBC_DATA_RATE;
5017 mcp->mb[1] = 0;
5018 mcp->out_mb = MBX_1|MBX_0;
5019 mcp->in_mb = MBX_2|MBX_1|MBX_0;
f73cb695 5020 if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
6246b8a1 5021 mcp->in_mb |= MBX_3;
3064ff39
MH
5022 mcp->tov = MBX_TOV_SECONDS;
5023 mcp->flags = 0;
5024 rval = qla2x00_mailbox_command(vha, mcp);
5025 if (rval != QLA_SUCCESS) {
7c3df132
SK
5026 ql_dbg(ql_dbg_mbx, vha, 0x1107,
5027 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
3064ff39 5028 } else {
5f28d2d7
SK
5029 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1108,
5030 "Done %s.\n", __func__);
3064ff39
MH
5031 if (mcp->mb[1] != 0x7)
5032 ha->link_data_rate = mcp->mb[1];
5033 }
5034
5035 return rval;
5036}
09ff701a 5037
23f2ebd1
SR
5038int
5039qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb)
5040{
5041 int rval;
5042 mbx_cmd_t mc;
5043 mbx_cmd_t *mcp = &mc;
5044 struct qla_hw_data *ha = vha->hw;
5045
5f28d2d7
SK
5046 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1109,
5047 "Entered %s.\n", __func__);
23f2ebd1 5048
f73cb695
CD
5049 if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && !IS_QLA8044(ha) &&
5050 !IS_QLA27XX(ha))
23f2ebd1
SR
5051 return QLA_FUNCTION_FAILED;
5052 mcp->mb[0] = MBC_GET_PORT_CONFIG;
5053 mcp->out_mb = MBX_0;
5054 mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
5055 mcp->tov = MBX_TOV_SECONDS;
5056 mcp->flags = 0;
5057
5058 rval = qla2x00_mailbox_command(vha, mcp);
5059
5060 if (rval != QLA_SUCCESS) {
7c3df132
SK
5061 ql_dbg(ql_dbg_mbx, vha, 0x110a,
5062 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
23f2ebd1
SR
5063 } else {
5064 /* Copy all bits to preserve original value */
5065 memcpy(mb, &mcp->mb[1], sizeof(uint16_t) * 4);
5066
5f28d2d7
SK
5067 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110b,
5068 "Done %s.\n", __func__);
23f2ebd1
SR
5069 }
5070 return rval;
5071}
5072
5073int
5074qla81xx_set_port_config(scsi_qla_host_t *vha, uint16_t *mb)
5075{
5076 int rval;
5077 mbx_cmd_t mc;
5078 mbx_cmd_t *mcp = &mc;
5079
5f28d2d7
SK
5080 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110c,
5081 "Entered %s.\n", __func__);
23f2ebd1
SR
5082
5083 mcp->mb[0] = MBC_SET_PORT_CONFIG;
5084 /* Copy all bits to preserve original setting */
5085 memcpy(&mcp->mb[1], mb, sizeof(uint16_t) * 4);
5086 mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
5087 mcp->in_mb = MBX_0;
5088 mcp->tov = MBX_TOV_SECONDS;
5089 mcp->flags = 0;
5090 rval = qla2x00_mailbox_command(vha, mcp);
5091
5092 if (rval != QLA_SUCCESS) {
7c3df132
SK
5093 ql_dbg(ql_dbg_mbx, vha, 0x110d,
5094 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
23f2ebd1 5095 } else
5f28d2d7
SK
5096 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110e,
5097 "Done %s.\n", __func__);
23f2ebd1
SR
5098
5099 return rval;
5100}
5101
5102
09ff701a
SR
5103int
5104qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority,
5105 uint16_t *mb)
5106{
5107 int rval;
5108 mbx_cmd_t mc;
5109 mbx_cmd_t *mcp = &mc;
5110 struct qla_hw_data *ha = vha->hw;
5111
5f28d2d7
SK
5112 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110f,
5113 "Entered %s.\n", __func__);
7c3df132 5114
09ff701a
SR
5115 if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha))
5116 return QLA_FUNCTION_FAILED;
5117
09ff701a
SR
5118 mcp->mb[0] = MBC_PORT_PARAMS;
5119 mcp->mb[1] = loop_id;
5120 if (ha->flags.fcp_prio_enabled)
5121 mcp->mb[2] = BIT_1;
5122 else
5123 mcp->mb[2] = BIT_2;
5124 mcp->mb[4] = priority & 0xf;
5125 mcp->mb[9] = vha->vp_idx;
5126 mcp->out_mb = MBX_9|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
5127 mcp->in_mb = MBX_4|MBX_3|MBX_1|MBX_0;
5128 mcp->tov = 30;
5129 mcp->flags = 0;
5130 rval = qla2x00_mailbox_command(vha, mcp);
5131 if (mb != NULL) {
5132 mb[0] = mcp->mb[0];
5133 mb[1] = mcp->mb[1];
5134 mb[3] = mcp->mb[3];
5135 mb[4] = mcp->mb[4];
5136 }
5137
5138 if (rval != QLA_SUCCESS) {
7c3df132 5139 ql_dbg(ql_dbg_mbx, vha, 0x10cd, "Failed=%x.\n", rval);
09ff701a 5140 } else {
5f28d2d7
SK
5141 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10cc,
5142 "Done %s.\n", __func__);
09ff701a
SR
5143 }
5144
5145 return rval;
5146}
a9083016 5147
794a5691 5148int
fe52f6e1 5149qla2x00_get_thermal_temp(scsi_qla_host_t *vha, uint16_t *temp)
794a5691 5150{
fe52f6e1 5151 int rval = QLA_FUNCTION_FAILED;
794a5691 5152 struct qla_hw_data *ha = vha->hw;
fe52f6e1 5153 uint8_t byte;
794a5691 5154
1ae47cf3
JC
5155 if (!IS_FWI2_CAPABLE(ha) || IS_QLA24XX_TYPE(ha) || IS_QLA81XX(ha)) {
5156 ql_dbg(ql_dbg_mbx, vha, 0x1150,
5157 "Thermal not supported by this card.\n");
5158 return rval;
5159 }
5160
5161 if (IS_QLA25XX(ha)) {
5162 if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
5163 ha->pdev->subsystem_device == 0x0175) {
5164 rval = qla2x00_read_sfp(vha, 0, &byte,
5165 0x98, 0x1, 1, BIT_13|BIT_0);
5166 *temp = byte;
5167 return rval;
5168 }
5169 if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP &&
5170 ha->pdev->subsystem_device == 0x338e) {
5171 rval = qla2x00_read_sfp(vha, 0, &byte,
5172 0x98, 0x1, 1, BIT_15|BIT_14|BIT_0);
5173 *temp = byte;
5174 return rval;
5175 }
5176 ql_dbg(ql_dbg_mbx, vha, 0x10c9,
5177 "Thermal not supported by this card.\n");
5178 return rval;
794a5691 5179 }
794a5691 5180
1ae47cf3
JC
5181 if (IS_QLA82XX(ha)) {
5182 *temp = qla82xx_read_temperature(vha);
5183 rval = QLA_SUCCESS;
5184 return rval;
5185 } else if (IS_QLA8044(ha)) {
5186 *temp = qla8044_read_temperature(vha);
5187 rval = QLA_SUCCESS;
5188 return rval;
794a5691 5189 }
794a5691 5190
1ae47cf3 5191 rval = qla2x00_read_asic_temperature(vha, temp);
794a5691
AV
5192 return rval;
5193}
5194
a9083016
GM
5195int
5196qla82xx_mbx_intr_enable(scsi_qla_host_t *vha)
5197{
5198 int rval;
5199 struct qla_hw_data *ha = vha->hw;
5200 mbx_cmd_t mc;
5201 mbx_cmd_t *mcp = &mc;
5202
5f28d2d7
SK
5203 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1017,
5204 "Entered %s.\n", __func__);
7c3df132 5205
a9083016
GM
5206 if (!IS_FWI2_CAPABLE(ha))
5207 return QLA_FUNCTION_FAILED;
5208
a9083016 5209 memset(mcp, 0, sizeof(mbx_cmd_t));
3711333d 5210 mcp->mb[0] = MBC_TOGGLE_INTERRUPT;
a9083016
GM
5211 mcp->mb[1] = 1;
5212
5213 mcp->out_mb = MBX_1|MBX_0;
5214 mcp->in_mb = MBX_0;
5215 mcp->tov = 30;
5216 mcp->flags = 0;
5217
5218 rval = qla2x00_mailbox_command(vha, mcp);
5219 if (rval != QLA_SUCCESS) {
7c3df132
SK
5220 ql_dbg(ql_dbg_mbx, vha, 0x1016,
5221 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
a9083016 5222 } else {
5f28d2d7
SK
5223 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x100e,
5224 "Done %s.\n", __func__);
a9083016
GM
5225 }
5226
5227 return rval;
5228}
5229
5230int
5231qla82xx_mbx_intr_disable(scsi_qla_host_t *vha)
5232{
5233 int rval;
5234 struct qla_hw_data *ha = vha->hw;
5235 mbx_cmd_t mc;
5236 mbx_cmd_t *mcp = &mc;
5237
5f28d2d7
SK
5238 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x100d,
5239 "Entered %s.\n", __func__);
7c3df132 5240
7ec0effd 5241 if (!IS_P3P_TYPE(ha))
a9083016
GM
5242 return QLA_FUNCTION_FAILED;
5243
a9083016 5244 memset(mcp, 0, sizeof(mbx_cmd_t));
3711333d 5245 mcp->mb[0] = MBC_TOGGLE_INTERRUPT;
a9083016
GM
5246 mcp->mb[1] = 0;
5247
5248 mcp->out_mb = MBX_1|MBX_0;
5249 mcp->in_mb = MBX_0;
5250 mcp->tov = 30;
5251 mcp->flags = 0;
5252
5253 rval = qla2x00_mailbox_command(vha, mcp);
5254 if (rval != QLA_SUCCESS) {
7c3df132
SK
5255 ql_dbg(ql_dbg_mbx, vha, 0x100c,
5256 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
a9083016 5257 } else {
5f28d2d7
SK
5258 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x100b,
5259 "Done %s.\n", __func__);
a9083016
GM
5260 }
5261
5262 return rval;
5263}
08de2844
GM
5264
5265int
5266qla82xx_md_get_template_size(scsi_qla_host_t *vha)
5267{
5268 struct qla_hw_data *ha = vha->hw;
5269 mbx_cmd_t mc;
5270 mbx_cmd_t *mcp = &mc;
5271 int rval = QLA_FUNCTION_FAILED;
5272
5f28d2d7
SK
5273 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x111f,
5274 "Entered %s.\n", __func__);
08de2844
GM
5275
5276 memset(mcp->mb, 0 , sizeof(mcp->mb));
5277 mcp->mb[0] = LSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
5278 mcp->mb[1] = MSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
5279 mcp->mb[2] = LSW(RQST_TMPLT_SIZE);
5280 mcp->mb[3] = MSW(RQST_TMPLT_SIZE);
5281
5282 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
5283 mcp->in_mb = MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|
5284 MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
5285
5286 mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
5287 mcp->tov = MBX_TOV_SECONDS;
5288 rval = qla2x00_mailbox_command(vha, mcp);
5289
5290 /* Always copy back return mailbox values. */
5291 if (rval != QLA_SUCCESS) {
5292 ql_dbg(ql_dbg_mbx, vha, 0x1120,
5293 "mailbox command FAILED=0x%x, subcode=%x.\n",
5294 (mcp->mb[1] << 16) | mcp->mb[0],
5295 (mcp->mb[3] << 16) | mcp->mb[2]);
5296 } else {
5f28d2d7
SK
5297 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1121,
5298 "Done %s.\n", __func__);
08de2844
GM
5299 ha->md_template_size = ((mcp->mb[3] << 16) | mcp->mb[2]);
5300 if (!ha->md_template_size) {
5301 ql_dbg(ql_dbg_mbx, vha, 0x1122,
5302 "Null template size obtained.\n");
5303 rval = QLA_FUNCTION_FAILED;
5304 }
5305 }
5306 return rval;
5307}
5308
5309int
5310qla82xx_md_get_template(scsi_qla_host_t *vha)
5311{
5312 struct qla_hw_data *ha = vha->hw;
5313 mbx_cmd_t mc;
5314 mbx_cmd_t *mcp = &mc;
5315 int rval = QLA_FUNCTION_FAILED;
5316
5f28d2d7
SK
5317 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1123,
5318 "Entered %s.\n", __func__);
08de2844
GM
5319
5320 ha->md_tmplt_hdr = dma_alloc_coherent(&ha->pdev->dev,
5321 ha->md_template_size, &ha->md_tmplt_hdr_dma, GFP_KERNEL);
5322 if (!ha->md_tmplt_hdr) {
5323 ql_log(ql_log_warn, vha, 0x1124,
5324 "Unable to allocate memory for Minidump template.\n");
5325 return rval;
5326 }
5327
5328 memset(mcp->mb, 0 , sizeof(mcp->mb));
5329 mcp->mb[0] = LSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
5330 mcp->mb[1] = MSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
5331 mcp->mb[2] = LSW(RQST_TMPLT);
5332 mcp->mb[3] = MSW(RQST_TMPLT);
5333 mcp->mb[4] = LSW(LSD(ha->md_tmplt_hdr_dma));
5334 mcp->mb[5] = MSW(LSD(ha->md_tmplt_hdr_dma));
5335 mcp->mb[6] = LSW(MSD(ha->md_tmplt_hdr_dma));
5336 mcp->mb[7] = MSW(MSD(ha->md_tmplt_hdr_dma));
5337 mcp->mb[8] = LSW(ha->md_template_size);
5338 mcp->mb[9] = MSW(ha->md_template_size);
5339
5340 mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
5341 mcp->tov = MBX_TOV_SECONDS;
5342 mcp->out_mb = MBX_11|MBX_10|MBX_9|MBX_8|
5343 MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
5344 mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
5345 rval = qla2x00_mailbox_command(vha, mcp);
5346
5347 if (rval != QLA_SUCCESS) {
5348 ql_dbg(ql_dbg_mbx, vha, 0x1125,
5349 "mailbox command FAILED=0x%x, subcode=%x.\n",
5350 ((mcp->mb[1] << 16) | mcp->mb[0]),
5351 ((mcp->mb[3] << 16) | mcp->mb[2]));
5352 } else
5f28d2d7
SK
5353 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1126,
5354 "Done %s.\n", __func__);
08de2844
GM
5355 return rval;
5356}
999916dc 5357
7ec0effd
AD
5358int
5359qla8044_md_get_template(scsi_qla_host_t *vha)
5360{
5361 struct qla_hw_data *ha = vha->hw;
5362 mbx_cmd_t mc;
5363 mbx_cmd_t *mcp = &mc;
5364 int rval = QLA_FUNCTION_FAILED;
5365 int offset = 0, size = MINIDUMP_SIZE_36K;
5366 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0xb11f,
5367 "Entered %s.\n", __func__);
5368
5369 ha->md_tmplt_hdr = dma_alloc_coherent(&ha->pdev->dev,
5370 ha->md_template_size, &ha->md_tmplt_hdr_dma, GFP_KERNEL);
5371 if (!ha->md_tmplt_hdr) {
5372 ql_log(ql_log_warn, vha, 0xb11b,
5373 "Unable to allocate memory for Minidump template.\n");
5374 return rval;
5375 }
5376
5377 memset(mcp->mb, 0 , sizeof(mcp->mb));
5378 while (offset < ha->md_template_size) {
5379 mcp->mb[0] = LSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
5380 mcp->mb[1] = MSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
5381 mcp->mb[2] = LSW(RQST_TMPLT);
5382 mcp->mb[3] = MSW(RQST_TMPLT);
5383 mcp->mb[4] = LSW(LSD(ha->md_tmplt_hdr_dma + offset));
5384 mcp->mb[5] = MSW(LSD(ha->md_tmplt_hdr_dma + offset));
5385 mcp->mb[6] = LSW(MSD(ha->md_tmplt_hdr_dma + offset));
5386 mcp->mb[7] = MSW(MSD(ha->md_tmplt_hdr_dma + offset));
5387 mcp->mb[8] = LSW(size);
5388 mcp->mb[9] = MSW(size);
5389 mcp->mb[10] = offset & 0x0000FFFF;
5390 mcp->mb[11] = offset & 0xFFFF0000;
5391 mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
5392 mcp->tov = MBX_TOV_SECONDS;
5393 mcp->out_mb = MBX_11|MBX_10|MBX_9|MBX_8|
5394 MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
5395 mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
5396 rval = qla2x00_mailbox_command(vha, mcp);
5397
5398 if (rval != QLA_SUCCESS) {
5399 ql_dbg(ql_dbg_mbx, vha, 0xb11c,
5400 "mailbox command FAILED=0x%x, subcode=%x.\n",
5401 ((mcp->mb[1] << 16) | mcp->mb[0]),
5402 ((mcp->mb[3] << 16) | mcp->mb[2]));
5403 return rval;
5404 } else
5405 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0xb11d,
5406 "Done %s.\n", __func__);
5407 offset = offset + size;
5408 }
5409 return rval;
5410}
5411
6246b8a1
GM
5412int
5413qla81xx_set_led_config(scsi_qla_host_t *vha, uint16_t *led_cfg)
5414{
5415 int rval;
5416 struct qla_hw_data *ha = vha->hw;
5417 mbx_cmd_t mc;
5418 mbx_cmd_t *mcp = &mc;
5419
5420 if (!IS_QLA81XX(ha) && !IS_QLA8031(ha))
5421 return QLA_FUNCTION_FAILED;
5422
5f28d2d7
SK
5423 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1133,
5424 "Entered %s.\n", __func__);
6246b8a1
GM
5425
5426 memset(mcp, 0, sizeof(mbx_cmd_t));
5427 mcp->mb[0] = MBC_SET_LED_CONFIG;
5428 mcp->mb[1] = led_cfg[0];
5429 mcp->mb[2] = led_cfg[1];
5430 if (IS_QLA8031(ha)) {
5431 mcp->mb[3] = led_cfg[2];
5432 mcp->mb[4] = led_cfg[3];
5433 mcp->mb[5] = led_cfg[4];
5434 mcp->mb[6] = led_cfg[5];
5435 }
5436
5437 mcp->out_mb = MBX_2|MBX_1|MBX_0;
5438 if (IS_QLA8031(ha))
5439 mcp->out_mb |= MBX_6|MBX_5|MBX_4|MBX_3;
5440 mcp->in_mb = MBX_0;
5441 mcp->tov = 30;
5442 mcp->flags = 0;
5443
5444 rval = qla2x00_mailbox_command(vha, mcp);
5445 if (rval != QLA_SUCCESS) {
5446 ql_dbg(ql_dbg_mbx, vha, 0x1134,
5447 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
5448 } else {
5f28d2d7
SK
5449 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1135,
5450 "Done %s.\n", __func__);
6246b8a1
GM
5451 }
5452
5453 return rval;
5454}
5455
5456int
5457qla81xx_get_led_config(scsi_qla_host_t *vha, uint16_t *led_cfg)
5458{
5459 int rval;
5460 struct qla_hw_data *ha = vha->hw;
5461 mbx_cmd_t mc;
5462 mbx_cmd_t *mcp = &mc;
5463
5464 if (!IS_QLA81XX(ha) && !IS_QLA8031(ha))
5465 return QLA_FUNCTION_FAILED;
5466
5f28d2d7
SK
5467 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1136,
5468 "Entered %s.\n", __func__);
6246b8a1
GM
5469
5470 memset(mcp, 0, sizeof(mbx_cmd_t));
5471 mcp->mb[0] = MBC_GET_LED_CONFIG;
5472
5473 mcp->out_mb = MBX_0;
5474 mcp->in_mb = MBX_2|MBX_1|MBX_0;
5475 if (IS_QLA8031(ha))
5476 mcp->in_mb |= MBX_6|MBX_5|MBX_4|MBX_3;
5477 mcp->tov = 30;
5478 mcp->flags = 0;
5479
5480 rval = qla2x00_mailbox_command(vha, mcp);
5481 if (rval != QLA_SUCCESS) {
5482 ql_dbg(ql_dbg_mbx, vha, 0x1137,
5483 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
5484 } else {
5485 led_cfg[0] = mcp->mb[1];
5486 led_cfg[1] = mcp->mb[2];
5487 if (IS_QLA8031(ha)) {
5488 led_cfg[2] = mcp->mb[3];
5489 led_cfg[3] = mcp->mb[4];
5490 led_cfg[4] = mcp->mb[5];
5491 led_cfg[5] = mcp->mb[6];
5492 }
5f28d2d7
SK
5493 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1138,
5494 "Done %s.\n", __func__);
6246b8a1
GM
5495 }
5496
5497 return rval;
5498}
5499
999916dc
SK
5500int
5501qla82xx_mbx_beacon_ctl(scsi_qla_host_t *vha, int enable)
5502{
5503 int rval;
5504 struct qla_hw_data *ha = vha->hw;
5505 mbx_cmd_t mc;
5506 mbx_cmd_t *mcp = &mc;
5507
7ec0effd 5508 if (!IS_P3P_TYPE(ha))
999916dc
SK
5509 return QLA_FUNCTION_FAILED;
5510
5f28d2d7 5511 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1127,
999916dc
SK
5512 "Entered %s.\n", __func__);
5513
5514 memset(mcp, 0, sizeof(mbx_cmd_t));
5515 mcp->mb[0] = MBC_SET_LED_CONFIG;
5516 if (enable)
5517 mcp->mb[7] = 0xE;
5518 else
5519 mcp->mb[7] = 0xD;
5520
5521 mcp->out_mb = MBX_7|MBX_0;
5522 mcp->in_mb = MBX_0;
6246b8a1 5523 mcp->tov = MBX_TOV_SECONDS;
999916dc
SK
5524 mcp->flags = 0;
5525
5526 rval = qla2x00_mailbox_command(vha, mcp);
5527 if (rval != QLA_SUCCESS) {
5528 ql_dbg(ql_dbg_mbx, vha, 0x1128,
5529 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
5530 } else {
5f28d2d7 5531 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1129,
999916dc
SK
5532 "Done %s.\n", __func__);
5533 }
5534
5535 return rval;
5536}
6246b8a1
GM
5537
5538int
7d613ac6 5539qla83xx_wr_reg(scsi_qla_host_t *vha, uint32_t reg, uint32_t data)
6246b8a1
GM
5540{
5541 int rval;
5542 struct qla_hw_data *ha = vha->hw;
5543 mbx_cmd_t mc;
5544 mbx_cmd_t *mcp = &mc;
5545
f73cb695 5546 if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
6246b8a1
GM
5547 return QLA_FUNCTION_FAILED;
5548
5f28d2d7
SK
5549 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1130,
5550 "Entered %s.\n", __func__);
6246b8a1
GM
5551
5552 mcp->mb[0] = MBC_WRITE_REMOTE_REG;
5553 mcp->mb[1] = LSW(reg);
5554 mcp->mb[2] = MSW(reg);
5555 mcp->mb[3] = LSW(data);
5556 mcp->mb[4] = MSW(data);
5557 mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
5558
5559 mcp->in_mb = MBX_1|MBX_0;
5560 mcp->tov = MBX_TOV_SECONDS;
5561 mcp->flags = 0;
5562 rval = qla2x00_mailbox_command(vha, mcp);
5563
5564 if (rval != QLA_SUCCESS) {
5565 ql_dbg(ql_dbg_mbx, vha, 0x1131,
5566 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
5567 } else {
5f28d2d7 5568 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1132,
6246b8a1
GM
5569 "Done %s.\n", __func__);
5570 }
af11f64d 5571
6246b8a1
GM
5572 return rval;
5573}
af11f64d
AV
5574
5575int
5576qla2x00_port_logout(scsi_qla_host_t *vha, struct fc_port *fcport)
5577{
5578 int rval;
5579 struct qla_hw_data *ha = vha->hw;
5580 mbx_cmd_t mc;
5581 mbx_cmd_t *mcp = &mc;
5582
5583 if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
5f28d2d7 5584 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x113b,
af11f64d
AV
5585 "Implicit LOGO Unsupported.\n");
5586 return QLA_FUNCTION_FAILED;
5587 }
5588
5589
5f28d2d7
SK
5590 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x113c,
5591 "Entering %s.\n", __func__);
af11f64d
AV
5592
5593 /* Perform Implicit LOGO. */
5594 mcp->mb[0] = MBC_PORT_LOGOUT;
5595 mcp->mb[1] = fcport->loop_id;
5596 mcp->mb[10] = BIT_15;
5597 mcp->out_mb = MBX_10|MBX_1|MBX_0;
5598 mcp->in_mb = MBX_0;
5599 mcp->tov = MBX_TOV_SECONDS;
5600 mcp->flags = 0;
5601 rval = qla2x00_mailbox_command(vha, mcp);
5602 if (rval != QLA_SUCCESS)
5603 ql_dbg(ql_dbg_mbx, vha, 0x113d,
5604 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
5605 else
5f28d2d7
SK
5606 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x113e,
5607 "Done %s.\n", __func__);
af11f64d
AV
5608
5609 return rval;
5610}
5611
7d613ac6
SV
5612int
5613qla83xx_rd_reg(scsi_qla_host_t *vha, uint32_t reg, uint32_t *data)
5614{
5615 int rval;
5616 mbx_cmd_t mc;
5617 mbx_cmd_t *mcp = &mc;
5618 struct qla_hw_data *ha = vha->hw;
5619 unsigned long retry_max_time = jiffies + (2 * HZ);
5620
f73cb695 5621 if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
7d613ac6
SV
5622 return QLA_FUNCTION_FAILED;
5623
5624 ql_dbg(ql_dbg_mbx, vha, 0x114b, "Entered %s.\n", __func__);
5625
5626retry_rd_reg:
5627 mcp->mb[0] = MBC_READ_REMOTE_REG;
5628 mcp->mb[1] = LSW(reg);
5629 mcp->mb[2] = MSW(reg);
5630 mcp->out_mb = MBX_2|MBX_1|MBX_0;
5631 mcp->in_mb = MBX_4|MBX_3|MBX_1|MBX_0;
5632 mcp->tov = MBX_TOV_SECONDS;
5633 mcp->flags = 0;
5634 rval = qla2x00_mailbox_command(vha, mcp);
5635
5636 if (rval != QLA_SUCCESS) {
5637 ql_dbg(ql_dbg_mbx, vha, 0x114c,
5638 "Failed=%x mb[0]=%x mb[1]=%x.\n",
5639 rval, mcp->mb[0], mcp->mb[1]);
5640 } else {
5641 *data = (mcp->mb[3] | (mcp->mb[4] << 16));
5642 if (*data == QLA8XXX_BAD_VALUE) {
5643 /*
5644 * During soft-reset CAMRAM register reads might
5645 * return 0xbad0bad0. So retry for MAX of 2 sec
5646 * while reading camram registers.
5647 */
5648 if (time_after(jiffies, retry_max_time)) {
5649 ql_dbg(ql_dbg_mbx, vha, 0x1141,
5650 "Failure to read CAMRAM register. "
5651 "data=0x%x.\n", *data);
5652 return QLA_FUNCTION_FAILED;
5653 }
5654 msleep(100);
5655 goto retry_rd_reg;
5656 }
5657 ql_dbg(ql_dbg_mbx, vha, 0x1142, "Done %s.\n", __func__);
5658 }
5659
5660 return rval;
5661}
5662
5663int
5664qla83xx_restart_nic_firmware(scsi_qla_host_t *vha)
5665{
5666 int rval;
5667 mbx_cmd_t mc;
5668 mbx_cmd_t *mcp = &mc;
5669 struct qla_hw_data *ha = vha->hw;
5670
b20f02e1 5671 if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
7d613ac6
SV
5672 return QLA_FUNCTION_FAILED;
5673
5674 ql_dbg(ql_dbg_mbx, vha, 0x1143, "Entered %s.\n", __func__);
5675
5676 mcp->mb[0] = MBC_RESTART_NIC_FIRMWARE;
5677 mcp->out_mb = MBX_0;
5678 mcp->in_mb = MBX_1|MBX_0;
5679 mcp->tov = MBX_TOV_SECONDS;
5680 mcp->flags = 0;
5681 rval = qla2x00_mailbox_command(vha, mcp);
5682
5683 if (rval != QLA_SUCCESS) {
5684 ql_dbg(ql_dbg_mbx, vha, 0x1144,
5685 "Failed=%x mb[0]=%x mb[1]=%x.\n",
5686 rval, mcp->mb[0], mcp->mb[1]);
5687 ha->isp_ops->fw_dump(vha, 0);
5688 } else {
5689 ql_dbg(ql_dbg_mbx, vha, 0x1145, "Done %s.\n", __func__);
5690 }
5691
5692 return rval;
5693}
5694
5695int
5696qla83xx_access_control(scsi_qla_host_t *vha, uint16_t options,
5697 uint32_t start_addr, uint32_t end_addr, uint16_t *sector_size)
5698{
5699 int rval;
5700 mbx_cmd_t mc;
5701 mbx_cmd_t *mcp = &mc;
5702 uint8_t subcode = (uint8_t)options;
5703 struct qla_hw_data *ha = vha->hw;
5704
5705 if (!IS_QLA8031(ha))
5706 return QLA_FUNCTION_FAILED;
5707
5708 ql_dbg(ql_dbg_mbx, vha, 0x1146, "Entered %s.\n", __func__);
5709
5710 mcp->mb[0] = MBC_SET_ACCESS_CONTROL;
5711 mcp->mb[1] = options;
5712 mcp->out_mb = MBX_1|MBX_0;
5713 if (subcode & BIT_2) {
5714 mcp->mb[2] = LSW(start_addr);
5715 mcp->mb[3] = MSW(start_addr);
5716 mcp->mb[4] = LSW(end_addr);
5717 mcp->mb[5] = MSW(end_addr);
5718 mcp->out_mb |= MBX_5|MBX_4|MBX_3|MBX_2;
5719 }
5720 mcp->in_mb = MBX_2|MBX_1|MBX_0;
5721 if (!(subcode & (BIT_2 | BIT_5)))
5722 mcp->in_mb |= MBX_4|MBX_3;
5723 mcp->tov = MBX_TOV_SECONDS;
5724 mcp->flags = 0;
5725 rval = qla2x00_mailbox_command(vha, mcp);
5726
5727 if (rval != QLA_SUCCESS) {
5728 ql_dbg(ql_dbg_mbx, vha, 0x1147,
5729 "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[3]=%x mb[4]=%x.\n",
5730 rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3],
5731 mcp->mb[4]);
5732 ha->isp_ops->fw_dump(vha, 0);
5733 } else {
5734 if (subcode & BIT_5)
5735 *sector_size = mcp->mb[1];
5736 else if (subcode & (BIT_6 | BIT_7)) {
5737 ql_dbg(ql_dbg_mbx, vha, 0x1148,
5738 "Driver-lock id=%x%x", mcp->mb[4], mcp->mb[3]);
5739 } else if (subcode & (BIT_3 | BIT_4)) {
5740 ql_dbg(ql_dbg_mbx, vha, 0x1149,
5741 "Flash-lock id=%x%x", mcp->mb[4], mcp->mb[3]);
5742 }
5743 ql_dbg(ql_dbg_mbx, vha, 0x114a, "Done %s.\n", __func__);
5744 }
5745
5746 return rval;
5747}
81178772
SK
5748
5749int
5750qla2x00_dump_mctp_data(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr,
5751 uint32_t size)
5752{
5753 int rval;
5754 mbx_cmd_t mc;
5755 mbx_cmd_t *mcp = &mc;
5756
5757 if (!IS_MCTP_CAPABLE(vha->hw))
5758 return QLA_FUNCTION_FAILED;
5759
5760 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x114f,
5761 "Entered %s.\n", __func__);
5762
5763 mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED;
5764 mcp->mb[1] = LSW(addr);
5765 mcp->mb[2] = MSW(req_dma);
5766 mcp->mb[3] = LSW(req_dma);
5767 mcp->mb[4] = MSW(size);
5768 mcp->mb[5] = LSW(size);
5769 mcp->mb[6] = MSW(MSD(req_dma));
5770 mcp->mb[7] = LSW(MSD(req_dma));
5771 mcp->mb[8] = MSW(addr);
5772 /* Setting RAM ID to valid */
5773 mcp->mb[10] |= BIT_7;
5774 /* For MCTP RAM ID is 0x40 */
5775 mcp->mb[10] |= 0x40;
5776
5777 mcp->out_mb |= MBX_10|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|
5778 MBX_0;
5779
5780 mcp->in_mb = MBX_0;
5781 mcp->tov = MBX_TOV_SECONDS;
5782 mcp->flags = 0;
5783 rval = qla2x00_mailbox_command(vha, mcp);
5784
5785 if (rval != QLA_SUCCESS) {
5786 ql_dbg(ql_dbg_mbx, vha, 0x114e,
5787 "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
5788 } else {
5789 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x114d,
5790 "Done %s.\n", __func__);
5791 }
5792
5793 return rval;
5794}
ec891462
JC
5795
5796int
5797qla26xx_dport_diagnostics(scsi_qla_host_t *vha,
5798 void *dd_buf, uint size, uint options)
5799{
5800 int rval;
5801 mbx_cmd_t mc;
5802 mbx_cmd_t *mcp = &mc;
5803 dma_addr_t dd_dma;
5804
5805 if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw))
5806 return QLA_FUNCTION_FAILED;
5807
83548fe2 5808 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x119f,
ec891462
JC
5809 "Entered %s.\n", __func__);
5810
ec891462
JC
5811 dd_dma = dma_map_single(&vha->hw->pdev->dev,
5812 dd_buf, size, DMA_FROM_DEVICE);
0b2ce198 5813 if (dma_mapping_error(&vha->hw->pdev->dev, dd_dma)) {
ec891462
JC
5814 ql_log(ql_log_warn, vha, 0x1194, "Failed to map dma buffer.\n");
5815 return QLA_MEMORY_ALLOC_FAILED;
5816 }
5817
5818 memset(dd_buf, 0, size);
5819
5820 mcp->mb[0] = MBC_DPORT_DIAGNOSTICS;
5821 mcp->mb[1] = options;
5822 mcp->mb[2] = MSW(LSD(dd_dma));
5823 mcp->mb[3] = LSW(LSD(dd_dma));
5824 mcp->mb[6] = MSW(MSD(dd_dma));
5825 mcp->mb[7] = LSW(MSD(dd_dma));
5826 mcp->mb[8] = size;
5827 mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
5828 mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
5829 mcp->buf_size = size;
5830 mcp->flags = MBX_DMA_IN;
5831 mcp->tov = MBX_TOV_SECONDS * 4;
5832 rval = qla2x00_mailbox_command(vha, mcp);
5833
5834 if (rval != QLA_SUCCESS) {
5835 ql_dbg(ql_dbg_mbx, vha, 0x1195, "Failed=%x.\n", rval);
5836 } else {
5837 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1196,
5838 "Done %s.\n", __func__);
5839 }
5840
5841 dma_unmap_single(&vha->hw->pdev->dev, dd_dma,
5842 size, DMA_FROM_DEVICE);
5843
5844 return rval;
5845}
15f30a57
QT
5846
5847static void qla2x00_async_mb_sp_done(void *s, int res)
5848{
5849 struct srb *sp = s;
5850
5851 sp->u.iocb_cmd.u.mbx.rc = res;
5852
5853 complete(&sp->u.iocb_cmd.u.mbx.comp);
5854 /* don't free sp here. Let the caller do the free */
5855}
5856
5857/*
5858 * This mailbox uses the iocb interface to send MB command.
5859 * This allows non-critial (non chip setup) command to go
5860 * out in parrallel.
5861 */
5862int qla24xx_send_mb_cmd(struct scsi_qla_host *vha, mbx_cmd_t *mcp)
5863{
5864 int rval = QLA_FUNCTION_FAILED;
5865 srb_t *sp;
5866 struct srb_iocb *c;
5867
5868 if (!vha->hw->flags.fw_started)
5869 goto done;
5870
5871 sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
5872 if (!sp)
5873 goto done;
5874
5875 sp->type = SRB_MB_IOCB;
5876 sp->name = mb_to_str(mcp->mb[0]);
5877
5878 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
5879
5880 memcpy(sp->u.iocb_cmd.u.mbx.out_mb, mcp->mb, SIZEOF_IOCB_MB_REG);
5881
5882 c = &sp->u.iocb_cmd;
5883 c->timeout = qla2x00_async_iocb_timeout;
5884 init_completion(&c->u.mbx.comp);
5885
5886 sp->done = qla2x00_async_mb_sp_done;
5887
5888 rval = qla2x00_start_sp(sp);
5889 if (rval != QLA_SUCCESS) {
83548fe2 5890 ql_dbg(ql_dbg_mbx, vha, 0x1018,
15f30a57
QT
5891 "%s: %s Failed submission. %x.\n",
5892 __func__, sp->name, rval);
5893 goto done_free_sp;
5894 }
5895
83548fe2 5896 ql_dbg(ql_dbg_mbx, vha, 0x113f, "MB:%s hndl %x submitted\n",
15f30a57
QT
5897 sp->name, sp->handle);
5898
5899 wait_for_completion(&c->u.mbx.comp);
5900 memcpy(mcp->mb, sp->u.iocb_cmd.u.mbx.in_mb, SIZEOF_IOCB_MB_REG);
5901
5902 rval = c->u.mbx.rc;
5903 switch (rval) {
5904 case QLA_FUNCTION_TIMEOUT:
83548fe2 5905 ql_dbg(ql_dbg_mbx, vha, 0x1140, "%s: %s Timeout. %x.\n",
15f30a57
QT
5906 __func__, sp->name, rval);
5907 break;
5908 case QLA_SUCCESS:
83548fe2 5909 ql_dbg(ql_dbg_mbx, vha, 0x119d, "%s: %s done.\n",
15f30a57
QT
5910 __func__, sp->name);
5911 sp->free(sp);
5912 break;
5913 default:
83548fe2 5914 ql_dbg(ql_dbg_mbx, vha, 0x119e, "%s: %s Failed. %x.\n",
15f30a57
QT
5915 __func__, sp->name, rval);
5916 sp->free(sp);
5917 break;
5918 }
5919
5920 return rval;
5921
5922done_free_sp:
5923 sp->free(sp);
5924done:
5925 return rval;
5926}
5927
5928/*
5929 * qla24xx_gpdb_wait
5930 * NOTE: Do not call this routine from DPC thread
5931 */
5932int qla24xx_gpdb_wait(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
5933{
5934 int rval = QLA_FUNCTION_FAILED;
5935 dma_addr_t pd_dma;
5936 struct port_database_24xx *pd;
5937 struct qla_hw_data *ha = vha->hw;
5938 mbx_cmd_t mc;
5939
5940 if (!vha->hw->flags.fw_started)
5941 goto done;
5942
5943 pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
5944 if (pd == NULL) {
83548fe2
QT
5945 ql_log(ql_log_warn, vha, 0xd047,
5946 "Failed to allocate port database structure.\n");
15f30a57
QT
5947 goto done_free_sp;
5948 }
5949 memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE));
5950
5951 memset(&mc, 0, sizeof(mc));
5952 mc.mb[0] = MBC_GET_PORT_DATABASE;
5953 mc.mb[1] = cpu_to_le16(fcport->loop_id);
5954 mc.mb[2] = MSW(pd_dma);
5955 mc.mb[3] = LSW(pd_dma);
5956 mc.mb[6] = MSW(MSD(pd_dma));
5957 mc.mb[7] = LSW(MSD(pd_dma));
5958 mc.mb[9] = cpu_to_le16(vha->vp_idx);
5959 mc.mb[10] = cpu_to_le16((uint16_t)opt);
5960
5961 rval = qla24xx_send_mb_cmd(vha, &mc);
5962 if (rval != QLA_SUCCESS) {
83548fe2 5963 ql_dbg(ql_dbg_mbx, vha, 0x1193,
15f30a57
QT
5964 "%s: %8phC fail\n", __func__, fcport->port_name);
5965 goto done_free_sp;
5966 }
5967
5968 rval = __qla24xx_parse_gpdb(vha, fcport, pd);
5969
83548fe2 5970 ql_dbg(ql_dbg_mbx, vha, 0x1197, "%s: %8phC done\n",
15f30a57
QT
5971 __func__, fcport->port_name);
5972
5973done_free_sp:
5974 if (pd)
5975 dma_pool_free(ha->s_dma_pool, pd, pd_dma);
5976done:
5977 return rval;
5978}
5979
5980int __qla24xx_parse_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport,
5981 struct port_database_24xx *pd)
5982{
5983 int rval = QLA_SUCCESS;
5984 uint64_t zero = 0;
a5d42f4c
DG
5985 u8 current_login_state, last_login_state;
5986
5987 if (fcport->fc4f_nvme) {
5988 current_login_state = pd->current_login_state >> 4;
5989 last_login_state = pd->last_login_state >> 4;
5990 } else {
5991 current_login_state = pd->current_login_state & 0xf;
5992 last_login_state = pd->last_login_state & 0xf;
5993 }
15f30a57
QT
5994
5995 /* Check for logged in state. */
a5d42f4c
DG
5996 if (current_login_state != PDS_PRLI_COMPLETE &&
5997 last_login_state != PDS_PRLI_COMPLETE) {
83548fe2
QT
5998 ql_dbg(ql_dbg_mbx, vha, 0x119a,
5999 "Unable to verify login-state (%x/%x) for loop_id %x.\n",
a5d42f4c 6000 current_login_state, last_login_state, fcport->loop_id);
15f30a57
QT
6001 rval = QLA_FUNCTION_FAILED;
6002 goto gpd_error_out;
6003 }
6004
6005 if (fcport->loop_id == FC_NO_LOOP_ID ||
6006 (memcmp(fcport->port_name, (uint8_t *)&zero, 8) &&
6007 memcmp(fcport->port_name, pd->port_name, 8))) {
6008 /* We lost the device mid way. */
6009 rval = QLA_NOT_LOGGED_IN;
6010 goto gpd_error_out;
6011 }
6012
6013 /* Names are little-endian. */
6014 memcpy(fcport->node_name, pd->node_name, WWN_SIZE);
6015 memcpy(fcport->port_name, pd->port_name, WWN_SIZE);
6016
6017 /* Get port_id of device. */
6018 fcport->d_id.b.domain = pd->port_id[0];
6019 fcport->d_id.b.area = pd->port_id[1];
6020 fcport->d_id.b.al_pa = pd->port_id[2];
6021 fcport->d_id.b.rsvd_1 = 0;
6022
a5d42f4c
DG
6023 if (fcport->fc4f_nvme) {
6024 fcport->nvme_prli_service_param =
6025 pd->prli_nvme_svc_param_word_3;
6026 fcport->port_type = FCT_NVME;
6027 } else {
6028 /* If not target must be initiator or unknown type. */
6029 if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
6030 fcport->port_type = FCT_INITIATOR;
6031 else
6032 fcport->port_type = FCT_TARGET;
6033 }
15f30a57
QT
6034 /* Passback COS information. */
6035 fcport->supported_classes = (pd->flags & PDF_CLASS_2) ?
6036 FC_COS_CLASS2 : FC_COS_CLASS3;
6037
6038 if (pd->prli_svc_param_word_3[0] & BIT_7) {
6039 fcport->flags |= FCF_CONF_COMP_SUPPORTED;
6040 fcport->conf_compl_supported = 1;
6041 }
6042
6043gpd_error_out:
6044 return rval;
6045}
6046
6047/*
6048 * qla24xx_gidlist__wait
6049 * NOTE: don't call this routine from DPC thread.
6050 */
6051int qla24xx_gidlist_wait(struct scsi_qla_host *vha,
6052 void *id_list, dma_addr_t id_list_dma, uint16_t *entries)
6053{
6054 int rval = QLA_FUNCTION_FAILED;
6055 mbx_cmd_t mc;
6056
6057 if (!vha->hw->flags.fw_started)
6058 goto done;
6059
6060 memset(&mc, 0, sizeof(mc));
6061 mc.mb[0] = MBC_GET_ID_LIST;
6062 mc.mb[2] = MSW(id_list_dma);
6063 mc.mb[3] = LSW(id_list_dma);
6064 mc.mb[6] = MSW(MSD(id_list_dma));
6065 mc.mb[7] = LSW(MSD(id_list_dma));
6066 mc.mb[8] = 0;
6067 mc.mb[9] = cpu_to_le16(vha->vp_idx);
6068
6069 rval = qla24xx_send_mb_cmd(vha, &mc);
6070 if (rval != QLA_SUCCESS) {
83548fe2
QT
6071 ql_dbg(ql_dbg_mbx, vha, 0x119b,
6072 "%s: fail\n", __func__);
15f30a57
QT
6073 } else {
6074 *entries = mc.mb[1];
83548fe2
QT
6075 ql_dbg(ql_dbg_mbx, vha, 0x119c,
6076 "%s: done\n", __func__);
15f30a57
QT
6077 }
6078done:
6079 return rval;
6080}
deeae7a6
DG
6081
6082int qla27xx_set_zio_threshold(scsi_qla_host_t *vha, uint16_t value)
6083{
6084 int rval;
6085 mbx_cmd_t mc;
6086 mbx_cmd_t *mcp = &mc;
6087
6088 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1200,
6089 "Entered %s\n", __func__);
6090
6091 memset(mcp->mb, 0 , sizeof(mcp->mb));
6092 mcp->mb[0] = MBC_GET_SET_ZIO_THRESHOLD;
6093 mcp->mb[1] = cpu_to_le16(1);
6094 mcp->mb[2] = cpu_to_le16(value);
6095 mcp->out_mb = MBX_2 | MBX_1 | MBX_0;
6096 mcp->in_mb = MBX_2 | MBX_0;
6097 mcp->tov = MBX_TOV_SECONDS;
6098 mcp->flags = 0;
6099
6100 rval = qla2x00_mailbox_command(vha, mcp);
6101
6102 ql_dbg(ql_dbg_mbx, vha, 0x1201, "%s %x\n",
6103 (rval != QLA_SUCCESS) ? "Failed" : "Done", rval);
6104
6105 return rval;
6106}
6107
6108int qla27xx_get_zio_threshold(scsi_qla_host_t *vha, uint16_t *value)
6109{
6110 int rval;
6111 mbx_cmd_t mc;
6112 mbx_cmd_t *mcp = &mc;
6113
6114 ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1203,
6115 "Entered %s\n", __func__);
6116
6117 memset(mcp->mb, 0, sizeof(mcp->mb));
6118 mcp->mb[0] = MBC_GET_SET_ZIO_THRESHOLD;
6119 mcp->mb[1] = cpu_to_le16(0);
6120 mcp->out_mb = MBX_1 | MBX_0;
6121 mcp->in_mb = MBX_2 | MBX_0;
6122 mcp->tov = MBX_TOV_SECONDS;
6123 mcp->flags = 0;
6124
6125 rval = qla2x00_mailbox_command(vha, mcp);
6126 if (rval == QLA_SUCCESS)
6127 *value = mc.mb[2];
6128
6129 ql_dbg(ql_dbg_mbx, vha, 0x1205, "%s %x\n",
6130 (rval != QLA_SUCCESS) ? "Failed" : "Done", rval);
6131
6132 return rval;
6133}