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