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