diff options
author | Vikas Chaudhary <vikas.chaudhary@qlogic.com> | 2013-11-22 05:28:17 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-12-19 23:56:25 -0500 |
commit | df86f771578209599acc871a03f02346c8d7885b (patch) | |
tree | 1532bc2abf8f6479a5bd34238ba917bc0a144c69 /drivers/scsi | |
parent | 2da11ad218b1a30f46b4c8fdfa39aff6584c370b (diff) |
[SCSI] qla4xxx: Added support for Diagnostics MBOX command
Added support for Diagnostics MBOX command via BSG Vendor HST_VENDOR
interface. This command provides various tests for validating hardware
functionality.
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_bsg.c | 360 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_bsg.h | 13 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_def.h | 8 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_fw.h | 14 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_glbl.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_isr.c | 19 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_mbx.c | 43 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 3 |
8 files changed, 455 insertions, 7 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_bsg.c b/drivers/scsi/qla4xxx/ql4_bsg.c index cf8fdf1d1257..04a0027dbca0 100644 --- a/drivers/scsi/qla4xxx/ql4_bsg.c +++ b/drivers/scsi/qla4xxx/ql4_bsg.c | |||
@@ -446,6 +446,363 @@ leave: | |||
446 | return rval; | 446 | return rval; |
447 | } | 447 | } |
448 | 448 | ||
449 | static void ql4xxx_execute_diag_cmd(struct bsg_job *bsg_job) | ||
450 | { | ||
451 | struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); | ||
452 | struct scsi_qla_host *ha = to_qla_host(host); | ||
453 | struct iscsi_bsg_request *bsg_req = bsg_job->request; | ||
454 | struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; | ||
455 | uint8_t *rsp_ptr = NULL; | ||
456 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | ||
457 | uint32_t mbox_sts[MBOX_REG_COUNT]; | ||
458 | int status = QLA_ERROR; | ||
459 | |||
460 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__)); | ||
461 | |||
462 | if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) { | ||
463 | ql4_printk(KERN_INFO, ha, "%s: Adapter reset in progress. Invalid Request\n", | ||
464 | __func__); | ||
465 | bsg_reply->result = DID_ERROR << 16; | ||
466 | goto exit_diag_mem_test; | ||
467 | } | ||
468 | |||
469 | bsg_reply->reply_payload_rcv_len = 0; | ||
470 | memcpy(mbox_cmd, &bsg_req->rqst_data.h_vendor.vendor_cmd[1], | ||
471 | sizeof(uint32_t) * MBOX_REG_COUNT); | ||
472 | |||
473 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
474 | "%s: mbox_cmd: %08X %08X %08X %08X %08X %08X %08X %08X\n", | ||
475 | __func__, mbox_cmd[0], mbox_cmd[1], mbox_cmd[2], | ||
476 | mbox_cmd[3], mbox_cmd[4], mbox_cmd[5], mbox_cmd[6], | ||
477 | mbox_cmd[7])); | ||
478 | |||
479 | status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0], | ||
480 | &mbox_sts[0]); | ||
481 | |||
482 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
483 | "%s: mbox_sts: %08X %08X %08X %08X %08X %08X %08X %08X\n", | ||
484 | __func__, mbox_sts[0], mbox_sts[1], mbox_sts[2], | ||
485 | mbox_sts[3], mbox_sts[4], mbox_sts[5], mbox_sts[6], | ||
486 | mbox_sts[7])); | ||
487 | |||
488 | if (status == QLA_SUCCESS) | ||
489 | bsg_reply->result = DID_OK << 16; | ||
490 | else | ||
491 | bsg_reply->result = DID_ERROR << 16; | ||
492 | |||
493 | /* Send mbox_sts to application */ | ||
494 | bsg_job->reply_len = sizeof(struct iscsi_bsg_reply) + sizeof(mbox_sts); | ||
495 | rsp_ptr = ((uint8_t *)bsg_reply) + sizeof(struct iscsi_bsg_reply); | ||
496 | memcpy(rsp_ptr, mbox_sts, sizeof(mbox_sts)); | ||
497 | |||
498 | exit_diag_mem_test: | ||
499 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
500 | "%s: bsg_reply->result = x%x, status = %s\n", | ||
501 | __func__, bsg_reply->result, STATUS(status))); | ||
502 | |||
503 | bsg_job_done(bsg_job, bsg_reply->result, | ||
504 | bsg_reply->reply_payload_rcv_len); | ||
505 | } | ||
506 | |||
507 | static int qla4_83xx_wait_for_loopback_config_comp(struct scsi_qla_host *ha, | ||
508 | int wait_for_link) | ||
509 | { | ||
510 | int status = QLA_SUCCESS; | ||
511 | |||
512 | if (!wait_for_completion_timeout(&ha->idc_comp, (IDC_COMP_TOV * HZ))) { | ||
513 | ql4_printk(KERN_INFO, ha, "%s: IDC Complete notification not received, Waiting for another %d timeout", | ||
514 | __func__, ha->idc_extend_tmo); | ||
515 | if (ha->idc_extend_tmo) { | ||
516 | if (!wait_for_completion_timeout(&ha->idc_comp, | ||
517 | (ha->idc_extend_tmo * HZ))) { | ||
518 | ha->notify_idc_comp = 0; | ||
519 | ha->notify_link_up_comp = 0; | ||
520 | ql4_printk(KERN_WARNING, ha, "%s: IDC Complete notification not received", | ||
521 | __func__); | ||
522 | status = QLA_ERROR; | ||
523 | goto exit_wait; | ||
524 | } else { | ||
525 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
526 | "%s: IDC Complete notification received\n", | ||
527 | __func__)); | ||
528 | } | ||
529 | } | ||
530 | } else { | ||
531 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
532 | "%s: IDC Complete notification received\n", | ||
533 | __func__)); | ||
534 | } | ||
535 | ha->notify_idc_comp = 0; | ||
536 | |||
537 | if (wait_for_link) { | ||
538 | if (!wait_for_completion_timeout(&ha->link_up_comp, | ||
539 | (IDC_COMP_TOV * HZ))) { | ||
540 | ha->notify_link_up_comp = 0; | ||
541 | ql4_printk(KERN_WARNING, ha, "%s: LINK UP notification not received", | ||
542 | __func__); | ||
543 | status = QLA_ERROR; | ||
544 | goto exit_wait; | ||
545 | } else { | ||
546 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
547 | "%s: LINK UP notification received\n", | ||
548 | __func__)); | ||
549 | } | ||
550 | ha->notify_link_up_comp = 0; | ||
551 | } | ||
552 | |||
553 | exit_wait: | ||
554 | return status; | ||
555 | } | ||
556 | |||
557 | static int qla4_83xx_pre_loopback_config(struct scsi_qla_host *ha, | ||
558 | uint32_t *mbox_cmd) | ||
559 | { | ||
560 | uint32_t config = 0; | ||
561 | int status = QLA_SUCCESS; | ||
562 | |||
563 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__)); | ||
564 | |||
565 | status = qla4_83xx_get_port_config(ha, &config); | ||
566 | if (status != QLA_SUCCESS) | ||
567 | goto exit_pre_loopback_config; | ||
568 | |||
569 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Default port config=%08X\n", | ||
570 | __func__, config)); | ||
571 | |||
572 | if ((config & ENABLE_INTERNAL_LOOPBACK) || | ||
573 | (config & ENABLE_EXTERNAL_LOOPBACK)) { | ||
574 | ql4_printk(KERN_INFO, ha, "%s: Loopback diagnostics already in progress. Invalid requiest\n", | ||
575 | __func__); | ||
576 | goto exit_pre_loopback_config; | ||
577 | } | ||
578 | |||
579 | if (mbox_cmd[1] == QL_DIAG_CMD_TEST_INT_LOOPBACK) | ||
580 | config |= ENABLE_INTERNAL_LOOPBACK; | ||
581 | |||
582 | if (mbox_cmd[1] == QL_DIAG_CMD_TEST_EXT_LOOPBACK) | ||
583 | config |= ENABLE_EXTERNAL_LOOPBACK; | ||
584 | |||
585 | config &= ~ENABLE_DCBX; | ||
586 | |||
587 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: New port config=%08X\n", | ||
588 | __func__, config)); | ||
589 | |||
590 | ha->notify_idc_comp = 1; | ||
591 | ha->notify_link_up_comp = 1; | ||
592 | |||
593 | /* get the link state */ | ||
594 | qla4xxx_get_firmware_state(ha); | ||
595 | |||
596 | status = qla4_83xx_set_port_config(ha, &config); | ||
597 | if (status != QLA_SUCCESS) { | ||
598 | ha->notify_idc_comp = 0; | ||
599 | ha->notify_link_up_comp = 0; | ||
600 | goto exit_pre_loopback_config; | ||
601 | } | ||
602 | exit_pre_loopback_config: | ||
603 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: status = %s\n", __func__, | ||
604 | STATUS(status))); | ||
605 | return status; | ||
606 | } | ||
607 | |||
608 | static int qla4_83xx_post_loopback_config(struct scsi_qla_host *ha, | ||
609 | uint32_t *mbox_cmd) | ||
610 | { | ||
611 | int status = QLA_SUCCESS; | ||
612 | uint32_t config = 0; | ||
613 | |||
614 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__)); | ||
615 | |||
616 | status = qla4_83xx_get_port_config(ha, &config); | ||
617 | if (status != QLA_SUCCESS) | ||
618 | goto exit_post_loopback_config; | ||
619 | |||
620 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: port config=%08X\n", __func__, | ||
621 | config)); | ||
622 | |||
623 | if (mbox_cmd[1] == QL_DIAG_CMD_TEST_INT_LOOPBACK) | ||
624 | config &= ~ENABLE_INTERNAL_LOOPBACK; | ||
625 | else if (mbox_cmd[1] == QL_DIAG_CMD_TEST_EXT_LOOPBACK) | ||
626 | config &= ~ENABLE_EXTERNAL_LOOPBACK; | ||
627 | |||
628 | config |= ENABLE_DCBX; | ||
629 | |||
630 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
631 | "%s: Restore default port config=%08X\n", __func__, | ||
632 | config)); | ||
633 | |||
634 | ha->notify_idc_comp = 1; | ||
635 | if (ha->addl_fw_state & FW_ADDSTATE_LINK_UP) | ||
636 | ha->notify_link_up_comp = 1; | ||
637 | |||
638 | status = qla4_83xx_set_port_config(ha, &config); | ||
639 | if (status != QLA_SUCCESS) { | ||
640 | ql4_printk(KERN_INFO, ha, "%s: Scheduling adapter reset\n", | ||
641 | __func__); | ||
642 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
643 | clear_bit(AF_LOOPBACK, &ha->flags); | ||
644 | goto exit_post_loopback_config; | ||
645 | } | ||
646 | |||
647 | exit_post_loopback_config: | ||
648 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: status = %s\n", __func__, | ||
649 | STATUS(status))); | ||
650 | return status; | ||
651 | } | ||
652 | |||
653 | static void qla4xxx_execute_diag_loopback_cmd(struct bsg_job *bsg_job) | ||
654 | { | ||
655 | struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); | ||
656 | struct scsi_qla_host *ha = to_qla_host(host); | ||
657 | struct iscsi_bsg_request *bsg_req = bsg_job->request; | ||
658 | struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; | ||
659 | uint8_t *rsp_ptr = NULL; | ||
660 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | ||
661 | uint32_t mbox_sts[MBOX_REG_COUNT]; | ||
662 | int wait_for_link = 1; | ||
663 | int status = QLA_ERROR; | ||
664 | |||
665 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__)); | ||
666 | |||
667 | bsg_reply->reply_payload_rcv_len = 0; | ||
668 | |||
669 | if (test_bit(AF_LOOPBACK, &ha->flags)) { | ||
670 | ql4_printk(KERN_INFO, ha, "%s: Loopback Diagnostics already in progress. Invalid Request\n", | ||
671 | __func__); | ||
672 | bsg_reply->result = DID_ERROR << 16; | ||
673 | goto exit_loopback_cmd; | ||
674 | } | ||
675 | |||
676 | if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) { | ||
677 | ql4_printk(KERN_INFO, ha, "%s: Adapter reset in progress. Invalid Request\n", | ||
678 | __func__); | ||
679 | bsg_reply->result = DID_ERROR << 16; | ||
680 | goto exit_loopback_cmd; | ||
681 | } | ||
682 | |||
683 | memcpy(mbox_cmd, &bsg_req->rqst_data.h_vendor.vendor_cmd[1], | ||
684 | sizeof(uint32_t) * MBOX_REG_COUNT); | ||
685 | |||
686 | if (is_qla8032(ha) || is_qla8042(ha)) { | ||
687 | status = qla4_83xx_pre_loopback_config(ha, mbox_cmd); | ||
688 | if (status != QLA_SUCCESS) { | ||
689 | bsg_reply->result = DID_ERROR << 16; | ||
690 | goto exit_loopback_cmd; | ||
691 | } | ||
692 | |||
693 | status = qla4_83xx_wait_for_loopback_config_comp(ha, | ||
694 | wait_for_link); | ||
695 | if (status != QLA_SUCCESS) { | ||
696 | bsg_reply->result = DID_TIME_OUT << 16; | ||
697 | goto restore; | ||
698 | } | ||
699 | } | ||
700 | |||
701 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
702 | "%s: mbox_cmd: %08X %08X %08X %08X %08X %08X %08X %08X\n", | ||
703 | __func__, mbox_cmd[0], mbox_cmd[1], mbox_cmd[2], | ||
704 | mbox_cmd[3], mbox_cmd[4], mbox_cmd[5], mbox_cmd[6], | ||
705 | mbox_cmd[7])); | ||
706 | |||
707 | status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0], | ||
708 | &mbox_sts[0]); | ||
709 | |||
710 | if (status == QLA_SUCCESS) | ||
711 | bsg_reply->result = DID_OK << 16; | ||
712 | else | ||
713 | bsg_reply->result = DID_ERROR << 16; | ||
714 | |||
715 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
716 | "%s: mbox_sts: %08X %08X %08X %08X %08X %08X %08X %08X\n", | ||
717 | __func__, mbox_sts[0], mbox_sts[1], mbox_sts[2], | ||
718 | mbox_sts[3], mbox_sts[4], mbox_sts[5], mbox_sts[6], | ||
719 | mbox_sts[7])); | ||
720 | |||
721 | /* Send mbox_sts to application */ | ||
722 | bsg_job->reply_len = sizeof(struct iscsi_bsg_reply) + sizeof(mbox_sts); | ||
723 | rsp_ptr = ((uint8_t *)bsg_reply) + sizeof(struct iscsi_bsg_reply); | ||
724 | memcpy(rsp_ptr, mbox_sts, sizeof(mbox_sts)); | ||
725 | restore: | ||
726 | if (is_qla8032(ha) || is_qla8042(ha)) { | ||
727 | status = qla4_83xx_post_loopback_config(ha, mbox_cmd); | ||
728 | if (status != QLA_SUCCESS) { | ||
729 | bsg_reply->result = DID_ERROR << 16; | ||
730 | goto exit_loopback_cmd; | ||
731 | } | ||
732 | |||
733 | /* for pre_loopback_config() wait for LINK UP only | ||
734 | * if PHY LINK is UP */ | ||
735 | if (!(ha->addl_fw_state & FW_ADDSTATE_LINK_UP)) | ||
736 | wait_for_link = 0; | ||
737 | |||
738 | status = qla4_83xx_wait_for_loopback_config_comp(ha, | ||
739 | wait_for_link); | ||
740 | if (status != QLA_SUCCESS) { | ||
741 | bsg_reply->result = DID_TIME_OUT << 16; | ||
742 | goto exit_loopback_cmd; | ||
743 | } | ||
744 | } | ||
745 | exit_loopback_cmd: | ||
746 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
747 | "%s: bsg_reply->result = x%x, status = %s\n", | ||
748 | __func__, bsg_reply->result, STATUS(status))); | ||
749 | bsg_job_done(bsg_job, bsg_reply->result, | ||
750 | bsg_reply->reply_payload_rcv_len); | ||
751 | } | ||
752 | |||
753 | static int qla4xxx_execute_diag_test(struct bsg_job *bsg_job) | ||
754 | { | ||
755 | struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); | ||
756 | struct scsi_qla_host *ha = to_qla_host(host); | ||
757 | struct iscsi_bsg_request *bsg_req = bsg_job->request; | ||
758 | uint32_t diag_cmd; | ||
759 | int rval = -EINVAL; | ||
760 | |||
761 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__)); | ||
762 | |||
763 | diag_cmd = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; | ||
764 | if (diag_cmd == MBOX_CMD_DIAG_TEST) { | ||
765 | switch (bsg_req->rqst_data.h_vendor.vendor_cmd[2]) { | ||
766 | case QL_DIAG_CMD_TEST_DDR_SIZE: | ||
767 | case QL_DIAG_CMD_TEST_DDR_RW: | ||
768 | case QL_DIAG_CMD_TEST_ONCHIP_MEM_RW: | ||
769 | case QL_DIAG_CMD_TEST_NVRAM: | ||
770 | case QL_DIAG_CMD_TEST_FLASH_ROM: | ||
771 | case QL_DIAG_CMD_TEST_DMA_XFER: | ||
772 | case QL_DIAG_CMD_SELF_DDR_RW: | ||
773 | case QL_DIAG_CMD_SELF_ONCHIP_MEM_RW: | ||
774 | /* Execute diag test for adapter RAM/FLASH */ | ||
775 | ql4xxx_execute_diag_cmd(bsg_job); | ||
776 | /* Always return success as we want to sent bsg_reply | ||
777 | * to Application */ | ||
778 | rval = QLA_SUCCESS; | ||
779 | break; | ||
780 | |||
781 | case QL_DIAG_CMD_TEST_INT_LOOPBACK: | ||
782 | case QL_DIAG_CMD_TEST_EXT_LOOPBACK: | ||
783 | /* Execute diag test for Network */ | ||
784 | qla4xxx_execute_diag_loopback_cmd(bsg_job); | ||
785 | /* Always return success as we want to sent bsg_reply | ||
786 | * to Application */ | ||
787 | rval = QLA_SUCCESS; | ||
788 | break; | ||
789 | default: | ||
790 | ql4_printk(KERN_ERR, ha, "%s: Invalid diag test: 0x%x\n", | ||
791 | __func__, | ||
792 | bsg_req->rqst_data.h_vendor.vendor_cmd[2]); | ||
793 | } | ||
794 | } else if ((diag_cmd == MBOX_CMD_SET_LED_CONFIG) || | ||
795 | (diag_cmd == MBOX_CMD_GET_LED_CONFIG)) { | ||
796 | ql4xxx_execute_diag_cmd(bsg_job); | ||
797 | rval = QLA_SUCCESS; | ||
798 | } else { | ||
799 | ql4_printk(KERN_ERR, ha, "%s: Invalid diag cmd: 0x%x\n", | ||
800 | __func__, diag_cmd); | ||
801 | } | ||
802 | |||
803 | return rval; | ||
804 | } | ||
805 | |||
449 | /** | 806 | /** |
450 | * qla4xxx_process_vendor_specific - handle vendor specific bsg request | 807 | * qla4xxx_process_vendor_specific - handle vendor specific bsg request |
451 | * @job: iscsi_bsg_job to handle | 808 | * @job: iscsi_bsg_job to handle |
@@ -479,6 +836,9 @@ int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job) | |||
479 | case QLISCSI_VND_GET_ACB: | 836 | case QLISCSI_VND_GET_ACB: |
480 | return qla4xxx_bsg_get_acb(bsg_job); | 837 | return qla4xxx_bsg_get_acb(bsg_job); |
481 | 838 | ||
839 | case QLISCSI_VND_DIAG_TEST: | ||
840 | return qla4xxx_execute_diag_test(bsg_job); | ||
841 | |||
482 | default: | 842 | default: |
483 | ql4_printk(KERN_ERR, ha, "%s: invalid BSG vendor command: " | 843 | ql4_printk(KERN_ERR, ha, "%s: invalid BSG vendor command: " |
484 | "0x%x\n", __func__, bsg_req->msgcode); | 844 | "0x%x\n", __func__, bsg_req->msgcode); |
diff --git a/drivers/scsi/qla4xxx/ql4_bsg.h b/drivers/scsi/qla4xxx/ql4_bsg.h index c6a0364509fd..88c2401910c0 100644 --- a/drivers/scsi/qla4xxx/ql4_bsg.h +++ b/drivers/scsi/qla4xxx/ql4_bsg.h | |||
@@ -15,5 +15,18 @@ | |||
15 | #define QLISCSI_VND_UPDATE_NVRAM 5 | 15 | #define QLISCSI_VND_UPDATE_NVRAM 5 |
16 | #define QLISCSI_VND_RESTORE_DEFAULTS 6 | 16 | #define QLISCSI_VND_RESTORE_DEFAULTS 6 |
17 | #define QLISCSI_VND_GET_ACB 7 | 17 | #define QLISCSI_VND_GET_ACB 7 |
18 | #define QLISCSI_VND_DIAG_TEST 8 | ||
19 | |||
20 | /* QLISCSI_VND_DIAG_CMD sub code */ | ||
21 | #define QL_DIAG_CMD_TEST_DDR_SIZE 0x2 | ||
22 | #define QL_DIAG_CMD_TEST_DDR_RW 0x3 | ||
23 | #define QL_DIAG_CMD_TEST_ONCHIP_MEM_RW 0x4 | ||
24 | #define QL_DIAG_CMD_TEST_NVRAM 0x5 /* Only ISP4XXX */ | ||
25 | #define QL_DIAG_CMD_TEST_FLASH_ROM 0x6 | ||
26 | #define QL_DIAG_CMD_TEST_INT_LOOPBACK 0x7 | ||
27 | #define QL_DIAG_CMD_TEST_EXT_LOOPBACK 0x8 | ||
28 | #define QL_DIAG_CMD_TEST_DMA_XFER 0x9 /* Only ISP4XXX */ | ||
29 | #define QL_DIAG_CMD_SELF_DDR_RW 0xC | ||
30 | #define QL_DIAG_CMD_SELF_ONCHIP_MEM_RW 0xD | ||
18 | 31 | ||
19 | #endif | 32 | #endif |
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index e2be308c0d9e..aa67bb9a4426 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -73,6 +73,7 @@ | |||
73 | 73 | ||
74 | #define QLA_SUCCESS 0 | 74 | #define QLA_SUCCESS 0 |
75 | #define QLA_ERROR 1 | 75 | #define QLA_ERROR 1 |
76 | #define STATUS(status) status == QLA_ERROR ? "FAILED" : "SUCCEEDED" | ||
76 | 77 | ||
77 | /* | 78 | /* |
78 | * Data bit definitions | 79 | * Data bit definitions |
@@ -210,6 +211,8 @@ | |||
210 | #define MAX_RESET_HA_RETRIES 2 | 211 | #define MAX_RESET_HA_RETRIES 2 |
211 | #define FW_ALIVE_WAIT_TOV 3 | 212 | #define FW_ALIVE_WAIT_TOV 3 |
212 | #define IDC_EXTEND_TOV 8 | 213 | #define IDC_EXTEND_TOV 8 |
214 | #define IDC_COMP_TOV 5 | ||
215 | #define LINK_UP_COMP_TOV 30 | ||
213 | 216 | ||
214 | #define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) | 217 | #define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) |
215 | 218 | ||
@@ -822,6 +825,11 @@ struct scsi_qla_host { | |||
822 | uint32_t pf_bit; | 825 | uint32_t pf_bit; |
823 | struct qla4_83xx_idc_information idc_info; | 826 | struct qla4_83xx_idc_information idc_info; |
824 | struct addr_ctrl_blk *saved_acb; | 827 | struct addr_ctrl_blk *saved_acb; |
828 | int notify_idc_comp; | ||
829 | int notify_link_up_comp; | ||
830 | int idc_extend_tmo; | ||
831 | struct completion idc_comp; | ||
832 | struct completion link_up_comp; | ||
825 | }; | 833 | }; |
826 | 834 | ||
827 | struct ql4_task_data { | 835 | struct ql4_task_data { |
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index 306065275707..fef311d9caa3 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h | |||
@@ -410,6 +410,7 @@ struct qla_flt_region { | |||
410 | #define DDB_DS_LOGIN_IN_PROCESS 0x07 | 410 | #define DDB_DS_LOGIN_IN_PROCESS 0x07 |
411 | #define MBOX_CMD_GET_FW_STATE 0x0069 | 411 | #define MBOX_CMD_GET_FW_STATE 0x0069 |
412 | #define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A | 412 | #define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A |
413 | #define MBOX_CMD_DIAG_TEST 0x0075 | ||
413 | #define MBOX_CMD_GET_SYS_INFO 0x0078 | 414 | #define MBOX_CMD_GET_SYS_INFO 0x0078 |
414 | #define MBOX_CMD_GET_NVRAM 0x0078 /* For 40xx */ | 415 | #define MBOX_CMD_GET_NVRAM 0x0078 /* For 40xx */ |
415 | #define MBOX_CMD_SET_NVRAM 0x0079 /* For 40xx */ | 416 | #define MBOX_CMD_SET_NVRAM 0x0079 /* For 40xx */ |
@@ -425,8 +426,17 @@ struct qla_flt_region { | |||
425 | #define MBOX_CMD_GET_IP_ADDR_STATE 0x0091 | 426 | #define MBOX_CMD_GET_IP_ADDR_STATE 0x0091 |
426 | #define MBOX_CMD_SEND_IPV6_ROUTER_SOL 0x0092 | 427 | #define MBOX_CMD_SEND_IPV6_ROUTER_SOL 0x0092 |
427 | #define MBOX_CMD_GET_DB_ENTRY_CURRENT_IP_ADDR 0x0093 | 428 | #define MBOX_CMD_GET_DB_ENTRY_CURRENT_IP_ADDR 0x0093 |
429 | #define MBOX_CMD_SET_PORT_CONFIG 0x0122 | ||
430 | #define MBOX_CMD_GET_PORT_CONFIG 0x0123 | ||
431 | #define MBOX_CMD_SET_LED_CONFIG 0x0125 | ||
432 | #define MBOX_CMD_GET_LED_CONFIG 0x0126 | ||
428 | #define MBOX_CMD_MINIDUMP 0x0129 | 433 | #define MBOX_CMD_MINIDUMP 0x0129 |
429 | 434 | ||
435 | /* Port Config */ | ||
436 | #define ENABLE_INTERNAL_LOOPBACK 0x04 | ||
437 | #define ENABLE_EXTERNAL_LOOPBACK 0x08 | ||
438 | #define ENABLE_DCBX 0x10 | ||
439 | |||
430 | /* Minidump subcommand */ | 440 | /* Minidump subcommand */ |
431 | #define MINIDUMP_GET_SIZE_SUBCOMMAND 0x00 | 441 | #define MINIDUMP_GET_SIZE_SUBCOMMAND 0x00 |
432 | #define MINIDUMP_GET_TMPLT_SUBCOMMAND 0x01 | 442 | #define MINIDUMP_GET_TMPLT_SUBCOMMAND 0x01 |
@@ -535,10 +545,6 @@ struct qla_flt_region { | |||
535 | #define FLASH_OPT_COMMIT 2 | 545 | #define FLASH_OPT_COMMIT 2 |
536 | #define FLASH_OPT_RMW_COMMIT 3 | 546 | #define FLASH_OPT_RMW_COMMIT 3 |
537 | 547 | ||
538 | /* Loopback type */ | ||
539 | #define ENABLE_INTERNAL_LOOPBACK 0x04 | ||
540 | #define ENABLE_EXTERNAL_LOOPBACK 0x08 | ||
541 | |||
542 | /* generic defines to enable/disable params */ | 548 | /* generic defines to enable/disable params */ |
543 | #define QL4_PARAM_DISABLE 0 | 549 | #define QL4_PARAM_DISABLE 0 |
544 | #define QL4_PARAM_ENABLE 1 | 550 | #define QL4_PARAM_ENABLE 1 |
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index b8e87b33b48e..d67c50e0b896 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h | |||
@@ -277,6 +277,8 @@ int qla4_84xx_config_acb(struct scsi_qla_host *ha, int acb_config); | |||
277 | int qla4_83xx_ms_mem_write_128b(struct scsi_qla_host *ha, | 277 | int qla4_83xx_ms_mem_write_128b(struct scsi_qla_host *ha, |
278 | uint64_t addr, uint32_t *data, uint32_t count); | 278 | uint64_t addr, uint32_t *data, uint32_t count); |
279 | uint8_t qla4xxx_set_ipaddr_state(uint8_t fw_ipaddr_state); | 279 | uint8_t qla4xxx_set_ipaddr_state(uint8_t fw_ipaddr_state); |
280 | int qla4_83xx_get_port_config(struct scsi_qla_host *ha, uint32_t *config); | ||
281 | int qla4_83xx_set_port_config(struct scsi_qla_host *ha, uint32_t *config); | ||
280 | 282 | ||
281 | extern int ql4xextended_error_logging; | 283 | extern int ql4xextended_error_logging; |
282 | extern int ql4xdontresethba; | 284 | extern int ql4xdontresethba; |
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 66cc9c1ba53c..a3c8bc7706c2 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c | |||
@@ -650,6 +650,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
650 | int i; | 650 | int i; |
651 | uint32_t mbox_sts[MBOX_AEN_REG_COUNT]; | 651 | uint32_t mbox_sts[MBOX_AEN_REG_COUNT]; |
652 | __le32 __iomem *mailbox_out; | 652 | __le32 __iomem *mailbox_out; |
653 | uint32_t opcode = 0; | ||
653 | 654 | ||
654 | if (is_qla8032(ha) || is_qla8042(ha)) | 655 | if (is_qla8032(ha) || is_qla8042(ha)) |
655 | mailbox_out = &ha->qla4_83xx_reg->mailbox_out[0]; | 656 | mailbox_out = &ha->qla4_83xx_reg->mailbox_out[0]; |
@@ -728,6 +729,11 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
728 | qla4xxx_post_aen_work(ha, ISCSI_EVENT_LINKUP, | 729 | qla4xxx_post_aen_work(ha, ISCSI_EVENT_LINKUP, |
729 | sizeof(mbox_sts), | 730 | sizeof(mbox_sts), |
730 | (uint8_t *) mbox_sts); | 731 | (uint8_t *) mbox_sts); |
732 | |||
733 | if ((is_qla8032(ha) || is_qla8042(ha)) && | ||
734 | ha->notify_link_up_comp) | ||
735 | complete(&ha->link_up_comp); | ||
736 | |||
731 | break; | 737 | break; |
732 | 738 | ||
733 | case MBOX_ASTS_LINK_DOWN: | 739 | case MBOX_ASTS_LINK_DOWN: |
@@ -873,8 +879,6 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
873 | break; | 879 | break; |
874 | 880 | ||
875 | case MBOX_ASTS_IDC_REQUEST_NOTIFICATION: | 881 | case MBOX_ASTS_IDC_REQUEST_NOTIFICATION: |
876 | { | ||
877 | uint32_t opcode; | ||
878 | if (is_qla8032(ha) || is_qla8042(ha)) { | 882 | if (is_qla8032(ha) || is_qla8042(ha)) { |
879 | DEBUG2(ql4_printk(KERN_INFO, ha, | 883 | DEBUG2(ql4_printk(KERN_INFO, ha, |
880 | "scsi%ld: AEN %04x, mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3]=%08x, mbox_sts[4]=%08x\n", | 884 | "scsi%ld: AEN %04x, mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3]=%08x, mbox_sts[4]=%08x\n", |
@@ -894,7 +898,6 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
894 | } | 898 | } |
895 | } | 899 | } |
896 | break; | 900 | break; |
897 | } | ||
898 | 901 | ||
899 | case MBOX_ASTS_IDC_COMPLETE: | 902 | case MBOX_ASTS_IDC_COMPLETE: |
900 | if (is_qla8032(ha) || is_qla8042(ha)) { | 903 | if (is_qla8032(ha) || is_qla8042(ha)) { |
@@ -907,6 +910,14 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
907 | "scsi:%ld: AEN %04x IDC Complete notification\n", | 910 | "scsi:%ld: AEN %04x IDC Complete notification\n", |
908 | ha->host_no, mbox_sts[0])); | 911 | ha->host_no, mbox_sts[0])); |
909 | 912 | ||
913 | opcode = mbox_sts[1] >> 16; | ||
914 | if (ha->notify_idc_comp) | ||
915 | complete(&ha->idc_comp); | ||
916 | |||
917 | if ((opcode == MBOX_CMD_SET_PORT_CONFIG) || | ||
918 | (opcode == MBOX_CMD_PORT_RESET)) | ||
919 | ha->idc_info.info2 = mbox_sts[3]; | ||
920 | |||
910 | if (qla4_83xx_loopback_in_progress(ha)) { | 921 | if (qla4_83xx_loopback_in_progress(ha)) { |
911 | set_bit(AF_LOOPBACK, &ha->flags); | 922 | set_bit(AF_LOOPBACK, &ha->flags); |
912 | } else { | 923 | } else { |
@@ -939,6 +950,8 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
939 | DEBUG2(ql4_printk(KERN_INFO, ha, | 950 | DEBUG2(ql4_printk(KERN_INFO, ha, |
940 | "scsi%ld: AEN %04x Received IDC Extend Timeout notification\n", | 951 | "scsi%ld: AEN %04x Received IDC Extend Timeout notification\n", |
941 | ha->host_no, mbox_sts[0])); | 952 | ha->host_no, mbox_sts[0])); |
953 | /* new IDC timeout */ | ||
954 | ha->idc_extend_tmo = mbox_sts[1]; | ||
942 | break; | 955 | break; |
943 | 956 | ||
944 | case MBOX_ASTS_INITIALIZATION_FAILED: | 957 | case MBOX_ASTS_INITIALIZATION_FAILED: |
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 351793c0e18f..9ae8ca3b69f9 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c | |||
@@ -2416,3 +2416,46 @@ exit_config_acb: | |||
2416 | rval == QLA_SUCCESS ? "SUCCEEDED" : "FAILED")); | 2416 | rval == QLA_SUCCESS ? "SUCCEEDED" : "FAILED")); |
2417 | return rval; | 2417 | return rval; |
2418 | } | 2418 | } |
2419 | |||
2420 | int qla4_83xx_get_port_config(struct scsi_qla_host *ha, uint32_t *config) | ||
2421 | { | ||
2422 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | ||
2423 | uint32_t mbox_sts[MBOX_REG_COUNT]; | ||
2424 | int status; | ||
2425 | |||
2426 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | ||
2427 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | ||
2428 | |||
2429 | mbox_cmd[0] = MBOX_CMD_GET_PORT_CONFIG; | ||
2430 | |||
2431 | status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT, | ||
2432 | mbox_cmd, mbox_sts); | ||
2433 | if (status == QLA_SUCCESS) | ||
2434 | *config = mbox_sts[1]; | ||
2435 | else | ||
2436 | ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__, | ||
2437 | mbox_sts[0]); | ||
2438 | |||
2439 | return status; | ||
2440 | } | ||
2441 | |||
2442 | int qla4_83xx_set_port_config(struct scsi_qla_host *ha, uint32_t *config) | ||
2443 | { | ||
2444 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | ||
2445 | uint32_t mbox_sts[MBOX_REG_COUNT]; | ||
2446 | int status; | ||
2447 | |||
2448 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | ||
2449 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | ||
2450 | |||
2451 | mbox_cmd[0] = MBOX_CMD_SET_PORT_CONFIG; | ||
2452 | mbox_cmd[1] = *config; | ||
2453 | |||
2454 | status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT, | ||
2455 | mbox_cmd, mbox_sts); | ||
2456 | if (status != QLA_SUCCESS) | ||
2457 | ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__, | ||
2458 | mbox_sts[0]); | ||
2459 | |||
2460 | return status; | ||
2461 | } | ||
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 4706b8c0ec64..1d86f5bbd1d0 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -8400,6 +8400,9 @@ static int qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
8400 | mutex_init(&ha->chap_sem); | 8400 | mutex_init(&ha->chap_sem); |
8401 | init_completion(&ha->mbx_intr_comp); | 8401 | init_completion(&ha->mbx_intr_comp); |
8402 | init_completion(&ha->disable_acb_comp); | 8402 | init_completion(&ha->disable_acb_comp); |
8403 | init_completion(&ha->idc_comp); | ||
8404 | init_completion(&ha->link_up_comp); | ||
8405 | init_completion(&ha->disable_acb_comp); | ||
8403 | 8406 | ||
8404 | spin_lock_init(&ha->hardware_lock); | 8407 | spin_lock_init(&ha->hardware_lock); |
8405 | spin_lock_init(&ha->work_lock); | 8408 | spin_lock_init(&ha->work_lock); |