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