diff options
Diffstat (limited to 'drivers/scsi/bfa/bfad.c')
-rw-r--r-- | drivers/scsi/bfa/bfad.c | 208 |
1 files changed, 156 insertions, 52 deletions
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index b52b773d49d9..6bff08ea4029 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/kthread.h> | ||
23 | #include "bfad_drv.h" | 24 | #include "bfad_drv.h" |
24 | #include "bfad_im.h" | 25 | #include "bfad_im.h" |
25 | #include "bfad_tm.h" | 26 | #include "bfad_tm.h" |
@@ -53,6 +54,7 @@ static int log_level = BFA_LOG_WARNING; | |||
53 | static int ioc_auto_recover = BFA_TRUE; | 54 | static int ioc_auto_recover = BFA_TRUE; |
54 | static int ipfc_enable = BFA_FALSE; | 55 | static int ipfc_enable = BFA_FALSE; |
55 | static int ipfc_mtu = -1; | 56 | static int ipfc_mtu = -1; |
57 | static int fdmi_enable = BFA_TRUE; | ||
56 | int bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH; | 58 | int bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH; |
57 | int bfa_linkup_delay = -1; | 59 | int bfa_linkup_delay = -1; |
58 | 60 | ||
@@ -74,6 +76,7 @@ module_param(log_level, int, S_IRUGO | S_IWUSR); | |||
74 | module_param(ioc_auto_recover, int, S_IRUGO | S_IWUSR); | 76 | module_param(ioc_auto_recover, int, S_IRUGO | S_IWUSR); |
75 | module_param(ipfc_enable, int, S_IRUGO | S_IWUSR); | 77 | module_param(ipfc_enable, int, S_IRUGO | S_IWUSR); |
76 | module_param(ipfc_mtu, int, S_IRUGO | S_IWUSR); | 78 | module_param(ipfc_mtu, int, S_IRUGO | S_IWUSR); |
79 | module_param(fdmi_enable, int, S_IRUGO | S_IWUSR); | ||
77 | module_param(bfa_linkup_delay, int, S_IRUGO | S_IWUSR); | 80 | module_param(bfa_linkup_delay, int, S_IRUGO | S_IWUSR); |
78 | 81 | ||
79 | /* | 82 | /* |
@@ -95,6 +98,8 @@ bfad_fc4_probe(struct bfad_s *bfad) | |||
95 | 98 | ||
96 | if (ipfc_enable) | 99 | if (ipfc_enable) |
97 | bfad_ipfc_probe(bfad); | 100 | bfad_ipfc_probe(bfad); |
101 | |||
102 | bfad->bfad_flags |= BFAD_FC4_PROBE_DONE; | ||
98 | ext: | 103 | ext: |
99 | return rc; | 104 | return rc; |
100 | } | 105 | } |
@@ -106,6 +111,7 @@ bfad_fc4_probe_undo(struct bfad_s *bfad) | |||
106 | bfad_tm_probe_undo(bfad); | 111 | bfad_tm_probe_undo(bfad); |
107 | if (ipfc_enable) | 112 | if (ipfc_enable) |
108 | bfad_ipfc_probe_undo(bfad); | 113 | bfad_ipfc_probe_undo(bfad); |
114 | bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE; | ||
109 | } | 115 | } |
110 | 116 | ||
111 | static void | 117 | static void |
@@ -173,9 +179,19 @@ bfa_cb_init(void *drv, bfa_status_t init_status) | |||
173 | { | 179 | { |
174 | struct bfad_s *bfad = drv; | 180 | struct bfad_s *bfad = drv; |
175 | 181 | ||
176 | if (init_status == BFA_STATUS_OK) | 182 | if (init_status == BFA_STATUS_OK) { |
177 | bfad->bfad_flags |= BFAD_HAL_INIT_DONE; | 183 | bfad->bfad_flags |= BFAD_HAL_INIT_DONE; |
178 | 184 | ||
185 | /* If BFAD_HAL_INIT_FAIL flag is set: | ||
186 | * Wake up the kernel thread to start | ||
187 | * the bfad operations after HAL init done | ||
188 | */ | ||
189 | if ((bfad->bfad_flags & BFAD_HAL_INIT_FAIL)) { | ||
190 | bfad->bfad_flags &= ~BFAD_HAL_INIT_FAIL; | ||
191 | wake_up_process(bfad->bfad_tsk); | ||
192 | } | ||
193 | } | ||
194 | |||
179 | complete(&bfad->comp); | 195 | complete(&bfad->comp); |
180 | } | 196 | } |
181 | 197 | ||
@@ -648,7 +664,7 @@ bfad_fcs_port_cfg(struct bfad_s *bfad) | |||
648 | 664 | ||
649 | sprintf(symname, "%s-%d", BFAD_DRIVER_NAME, bfad->inst_no); | 665 | sprintf(symname, "%s-%d", BFAD_DRIVER_NAME, bfad->inst_no); |
650 | memcpy(port_cfg.sym_name.symname, symname, strlen(symname)); | 666 | memcpy(port_cfg.sym_name.symname, symname, strlen(symname)); |
651 | bfa_pport_get_attr(&bfad->bfa, &attr); | 667 | bfa_fcport_get_attr(&bfad->bfa, &attr); |
652 | port_cfg.nwwn = attr.nwwn; | 668 | port_cfg.nwwn = attr.nwwn; |
653 | port_cfg.pwwn = attr.pwwn; | 669 | port_cfg.pwwn = attr.pwwn; |
654 | 670 | ||
@@ -661,7 +677,6 @@ bfad_drv_init(struct bfad_s *bfad) | |||
661 | bfa_status_t rc; | 677 | bfa_status_t rc; |
662 | unsigned long flags; | 678 | unsigned long flags; |
663 | struct bfa_fcs_driver_info_s driver_info; | 679 | struct bfa_fcs_driver_info_s driver_info; |
664 | int i; | ||
665 | 680 | ||
666 | bfad->cfg_data.rport_del_timeout = rport_del_timeout; | 681 | bfad->cfg_data.rport_del_timeout = rport_del_timeout; |
667 | bfad->cfg_data.lun_queue_depth = bfa_lun_queue_depth; | 682 | bfad->cfg_data.lun_queue_depth = bfa_lun_queue_depth; |
@@ -681,12 +696,7 @@ bfad_drv_init(struct bfad_s *bfad) | |||
681 | bfa_init_log(&bfad->bfa, bfad->logmod); | 696 | bfa_init_log(&bfad->bfa, bfad->logmod); |
682 | bfa_init_trc(&bfad->bfa, bfad->trcmod); | 697 | bfa_init_trc(&bfad->bfa, bfad->trcmod); |
683 | bfa_init_aen(&bfad->bfa, bfad->aen); | 698 | bfa_init_aen(&bfad->bfa, bfad->aen); |
684 | INIT_LIST_HEAD(&bfad->file_q); | 699 | memset(bfad->file_map, 0, sizeof(bfad->file_map)); |
685 | INIT_LIST_HEAD(&bfad->file_free_q); | ||
686 | for (i = 0; i < BFAD_AEN_MAX_APPS; i++) { | ||
687 | bfa_q_qe_init(&bfad->file_buf[i].qe); | ||
688 | list_add_tail(&bfad->file_buf[i].qe, &bfad->file_free_q); | ||
689 | } | ||
690 | bfa_init_plog(&bfad->bfa, &bfad->plog_buf); | 700 | bfa_init_plog(&bfad->bfa, &bfad->plog_buf); |
691 | bfa_plog_init(&bfad->plog_buf); | 701 | bfa_plog_init(&bfad->plog_buf); |
692 | bfa_plog_str(&bfad->plog_buf, BFA_PL_MID_DRVR, BFA_PL_EID_DRIVER_START, | 702 | bfa_plog_str(&bfad->plog_buf, BFA_PL_MID_DRVR, BFA_PL_EID_DRIVER_START, |
@@ -746,8 +756,16 @@ bfad_drv_init(struct bfad_s *bfad) | |||
746 | bfa_fcs_log_init(&bfad->bfa_fcs, bfad->logmod); | 756 | bfa_fcs_log_init(&bfad->bfa_fcs, bfad->logmod); |
747 | bfa_fcs_trc_init(&bfad->bfa_fcs, bfad->trcmod); | 757 | bfa_fcs_trc_init(&bfad->bfa_fcs, bfad->trcmod); |
748 | bfa_fcs_aen_init(&bfad->bfa_fcs, bfad->aen); | 758 | bfa_fcs_aen_init(&bfad->bfa_fcs, bfad->aen); |
749 | bfa_fcs_init(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE); | 759 | bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE); |
760 | |||
761 | /* Do FCS init only when HAL init is done */ | ||
762 | if ((bfad->bfad_flags & BFAD_HAL_INIT_DONE)) { | ||
763 | bfa_fcs_init(&bfad->bfa_fcs); | ||
764 | bfad->bfad_flags |= BFAD_FCS_INIT_DONE; | ||
765 | } | ||
766 | |||
750 | bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info); | 767 | bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info); |
768 | bfa_fcs_set_fdmi_param(&bfad->bfa_fcs, fdmi_enable); | ||
751 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | 769 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); |
752 | 770 | ||
753 | bfad->bfad_flags |= BFAD_DRV_INIT_DONE; | 771 | bfad->bfad_flags |= BFAD_DRV_INIT_DONE; |
@@ -763,12 +781,21 @@ out_hal_mem_alloc_failure: | |||
763 | void | 781 | void |
764 | bfad_drv_uninit(struct bfad_s *bfad) | 782 | bfad_drv_uninit(struct bfad_s *bfad) |
765 | { | 783 | { |
784 | unsigned long flags; | ||
785 | |||
786 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
787 | init_completion(&bfad->comp); | ||
788 | bfa_stop(&bfad->bfa); | ||
789 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
790 | wait_for_completion(&bfad->comp); | ||
791 | |||
766 | del_timer_sync(&bfad->hal_tmo); | 792 | del_timer_sync(&bfad->hal_tmo); |
767 | bfa_isr_disable(&bfad->bfa); | 793 | bfa_isr_disable(&bfad->bfa); |
768 | bfa_detach(&bfad->bfa); | 794 | bfa_detach(&bfad->bfa); |
769 | bfad_remove_intr(bfad); | 795 | bfad_remove_intr(bfad); |
770 | bfa_assert(list_empty(&bfad->file_q)); | ||
771 | bfad_hal_mem_release(bfad); | 796 | bfad_hal_mem_release(bfad); |
797 | |||
798 | bfad->bfad_flags &= ~BFAD_DRV_INIT_DONE; | ||
772 | } | 799 | } |
773 | 800 | ||
774 | void | 801 | void |
@@ -859,6 +886,86 @@ bfad_drv_log_level_set(struct bfad_s *bfad) | |||
859 | bfa_log_set_level_all(&bfad->log_data, log_level); | 886 | bfa_log_set_level_all(&bfad->log_data, log_level); |
860 | } | 887 | } |
861 | 888 | ||
889 | bfa_status_t | ||
890 | bfad_start_ops(struct bfad_s *bfad) | ||
891 | { | ||
892 | int retval; | ||
893 | |||
894 | /* PPORT FCS config */ | ||
895 | bfad_fcs_port_cfg(bfad); | ||
896 | |||
897 | retval = bfad_cfg_pport(bfad, BFA_PORT_ROLE_FCP_IM); | ||
898 | if (retval != BFA_STATUS_OK) | ||
899 | goto out_cfg_pport_failure; | ||
900 | |||
901 | /* BFAD level FC4 (IM/TM/IPFC) specific resource allocation */ | ||
902 | retval = bfad_fc4_probe(bfad); | ||
903 | if (retval != BFA_STATUS_OK) { | ||
904 | printk(KERN_WARNING "bfad_fc4_probe failed\n"); | ||
905 | goto out_fc4_probe_failure; | ||
906 | } | ||
907 | |||
908 | bfad_drv_start(bfad); | ||
909 | |||
910 | /* | ||
911 | * If bfa_linkup_delay is set to -1 default; try to retrive the | ||
912 | * value using the bfad_os_get_linkup_delay(); else use the | ||
913 | * passed in module param value as the bfa_linkup_delay. | ||
914 | */ | ||
915 | if (bfa_linkup_delay < 0) { | ||
916 | |||
917 | bfa_linkup_delay = bfad_os_get_linkup_delay(bfad); | ||
918 | bfad_os_rport_online_wait(bfad); | ||
919 | bfa_linkup_delay = -1; | ||
920 | |||
921 | } else { | ||
922 | bfad_os_rport_online_wait(bfad); | ||
923 | } | ||
924 | |||
925 | bfa_log(bfad->logmod, BFA_LOG_LINUX_DEVICE_CLAIMED, bfad->pci_name); | ||
926 | |||
927 | return BFA_STATUS_OK; | ||
928 | |||
929 | out_fc4_probe_failure: | ||
930 | bfad_fc4_probe_undo(bfad); | ||
931 | bfad_uncfg_pport(bfad); | ||
932 | out_cfg_pport_failure: | ||
933 | return BFA_STATUS_FAILED; | ||
934 | } | ||
935 | |||
936 | int | ||
937 | bfad_worker (void *ptr) | ||
938 | { | ||
939 | struct bfad_s *bfad; | ||
940 | unsigned long flags; | ||
941 | |||
942 | bfad = (struct bfad_s *)ptr; | ||
943 | |||
944 | while (!kthread_should_stop()) { | ||
945 | |||
946 | /* Check if the FCS init is done from bfad_drv_init; | ||
947 | * if not done do FCS init and set the flag. | ||
948 | */ | ||
949 | if (!(bfad->bfad_flags & BFAD_FCS_INIT_DONE)) { | ||
950 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
951 | bfa_fcs_init(&bfad->bfa_fcs); | ||
952 | bfad->bfad_flags |= BFAD_FCS_INIT_DONE; | ||
953 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
954 | } | ||
955 | |||
956 | /* Start the bfad operations after HAL init done */ | ||
957 | bfad_start_ops(bfad); | ||
958 | |||
959 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
960 | bfad->bfad_tsk = NULL; | ||
961 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
962 | |||
963 | break; | ||
964 | } | ||
965 | |||
966 | return 0; | ||
967 | } | ||
968 | |||
862 | /* | 969 | /* |
863 | * PCI_entry PCI driver entries * { | 970 | * PCI_entry PCI driver entries * { |
864 | */ | 971 | */ |
@@ -871,7 +978,6 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
871 | { | 978 | { |
872 | struct bfad_s *bfad; | 979 | struct bfad_s *bfad; |
873 | int error = -ENODEV, retval; | 980 | int error = -ENODEV, retval; |
874 | char buf[16]; | ||
875 | 981 | ||
876 | /* | 982 | /* |
877 | * For single port cards - only claim function 0 | 983 | * For single port cards - only claim function 0 |
@@ -902,8 +1008,7 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
902 | bfa_trc(bfad, bfad_inst); | 1008 | bfa_trc(bfad, bfad_inst); |
903 | 1009 | ||
904 | bfad->logmod = &bfad->log_data; | 1010 | bfad->logmod = &bfad->log_data; |
905 | sprintf(buf, "%d", bfad_inst); | 1011 | bfa_log_init(bfad->logmod, (char *)pci_name(pdev), bfa_os_printf); |
906 | bfa_log_init(bfad->logmod, buf, bfa_os_printf); | ||
907 | 1012 | ||
908 | bfad_drv_log_level_set(bfad); | 1013 | bfad_drv_log_level_set(bfad); |
909 | 1014 | ||
@@ -933,57 +1038,39 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
933 | bfad->ref_count = 0; | 1038 | bfad->ref_count = 0; |
934 | bfad->pport.bfad = bfad; | 1039 | bfad->pport.bfad = bfad; |
935 | 1040 | ||
1041 | bfad->bfad_tsk = kthread_create(bfad_worker, (void *) bfad, "%s", | ||
1042 | "bfad_worker"); | ||
1043 | if (IS_ERR(bfad->bfad_tsk)) { | ||
1044 | printk(KERN_INFO "bfad[%d]: Kernel thread" | ||
1045 | " creation failed!\n", | ||
1046 | bfad->inst_no); | ||
1047 | goto out_kthread_create_failure; | ||
1048 | } | ||
1049 | |||
936 | retval = bfad_drv_init(bfad); | 1050 | retval = bfad_drv_init(bfad); |
937 | if (retval != BFA_STATUS_OK) | 1051 | if (retval != BFA_STATUS_OK) |
938 | goto out_drv_init_failure; | 1052 | goto out_drv_init_failure; |
939 | if (!(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) { | 1053 | if (!(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) { |
1054 | bfad->bfad_flags |= BFAD_HAL_INIT_FAIL; | ||
940 | printk(KERN_WARNING "bfad%d: hal init failed\n", bfad->inst_no); | 1055 | printk(KERN_WARNING "bfad%d: hal init failed\n", bfad->inst_no); |
941 | goto ok; | 1056 | goto ok; |
942 | } | 1057 | } |
943 | 1058 | ||
944 | /* | 1059 | retval = bfad_start_ops(bfad); |
945 | * PPORT FCS config | ||
946 | */ | ||
947 | bfad_fcs_port_cfg(bfad); | ||
948 | |||
949 | retval = bfad_cfg_pport(bfad, BFA_PORT_ROLE_FCP_IM); | ||
950 | if (retval != BFA_STATUS_OK) | 1060 | if (retval != BFA_STATUS_OK) |
951 | goto out_cfg_pport_failure; | 1061 | goto out_start_ops_failure; |
952 | |||
953 | /* | ||
954 | * BFAD level FC4 (IM/TM/IPFC) specific resource allocation | ||
955 | */ | ||
956 | retval = bfad_fc4_probe(bfad); | ||
957 | if (retval != BFA_STATUS_OK) { | ||
958 | printk(KERN_WARNING "bfad_fc4_probe failed\n"); | ||
959 | goto out_fc4_probe_failure; | ||
960 | } | ||
961 | 1062 | ||
962 | bfad_drv_start(bfad); | 1063 | kthread_stop(bfad->bfad_tsk); |
963 | 1064 | bfad->bfad_tsk = NULL; | |
964 | /* | ||
965 | * If bfa_linkup_delay is set to -1 default; try to retrive the | ||
966 | * value using the bfad_os_get_linkup_delay(); else use the | ||
967 | * passed in module param value as the bfa_linkup_delay. | ||
968 | */ | ||
969 | if (bfa_linkup_delay < 0) { | ||
970 | bfa_linkup_delay = bfad_os_get_linkup_delay(bfad); | ||
971 | bfad_os_rport_online_wait(bfad); | ||
972 | bfa_linkup_delay = -1; | ||
973 | } else { | ||
974 | bfad_os_rport_online_wait(bfad); | ||
975 | } | ||
976 | 1065 | ||
977 | bfa_log(bfad->logmod, BFA_LOG_LINUX_DEVICE_CLAIMED, bfad->pci_name); | ||
978 | ok: | 1066 | ok: |
979 | return 0; | 1067 | return 0; |
980 | 1068 | ||
981 | out_fc4_probe_failure: | 1069 | out_start_ops_failure: |
982 | bfad_fc4_probe_undo(bfad); | ||
983 | bfad_uncfg_pport(bfad); | ||
984 | out_cfg_pport_failure: | ||
985 | bfad_drv_uninit(bfad); | 1070 | bfad_drv_uninit(bfad); |
986 | out_drv_init_failure: | 1071 | out_drv_init_failure: |
1072 | kthread_stop(bfad->bfad_tsk); | ||
1073 | out_kthread_create_failure: | ||
987 | mutex_lock(&bfad_mutex); | 1074 | mutex_lock(&bfad_mutex); |
988 | bfad_inst--; | 1075 | bfad_inst--; |
989 | list_del(&bfad->list_entry); | 1076 | list_del(&bfad->list_entry); |
@@ -1008,6 +1095,11 @@ bfad_pci_remove(struct pci_dev *pdev) | |||
1008 | 1095 | ||
1009 | bfa_trc(bfad, bfad->inst_no); | 1096 | bfa_trc(bfad, bfad->inst_no); |
1010 | 1097 | ||
1098 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
1099 | if (bfad->bfad_tsk != NULL) | ||
1100 | kthread_stop(bfad->bfad_tsk); | ||
1101 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
1102 | |||
1011 | if ((bfad->bfad_flags & BFAD_DRV_INIT_DONE) | 1103 | if ((bfad->bfad_flags & BFAD_DRV_INIT_DONE) |
1012 | && !(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) { | 1104 | && !(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) { |
1013 | 1105 | ||
@@ -1024,13 +1116,25 @@ bfad_pci_remove(struct pci_dev *pdev) | |||
1024 | goto remove_sysfs; | 1116 | goto remove_sysfs; |
1025 | } | 1117 | } |
1026 | 1118 | ||
1027 | if (bfad->bfad_flags & BFAD_HAL_START_DONE) | 1119 | if (bfad->bfad_flags & BFAD_HAL_START_DONE) { |
1028 | bfad_drv_stop(bfad); | 1120 | bfad_drv_stop(bfad); |
1121 | } else if (bfad->bfad_flags & BFAD_DRV_INIT_DONE) { | ||
1122 | /* Invoking bfa_stop() before bfa_detach | ||
1123 | * when HAL and DRV init are success | ||
1124 | * but HAL start did not occur. | ||
1125 | */ | ||
1126 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
1127 | init_completion(&bfad->comp); | ||
1128 | bfa_stop(&bfad->bfa); | ||
1129 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
1130 | wait_for_completion(&bfad->comp); | ||
1131 | } | ||
1029 | 1132 | ||
1030 | bfad_remove_intr(bfad); | 1133 | bfad_remove_intr(bfad); |
1031 | |||
1032 | del_timer_sync(&bfad->hal_tmo); | 1134 | del_timer_sync(&bfad->hal_tmo); |
1033 | bfad_fc4_probe_undo(bfad); | 1135 | |
1136 | if (bfad->bfad_flags & BFAD_FC4_PROBE_DONE) | ||
1137 | bfad_fc4_probe_undo(bfad); | ||
1034 | 1138 | ||
1035 | if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE) | 1139 | if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE) |
1036 | bfad_uncfg_pport(bfad); | 1140 | bfad_uncfg_pport(bfad); |