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