diff options
Diffstat (limited to 'drivers/scsi/bfa/bfad.c')
-rw-r--r-- | drivers/scsi/bfa/bfad.c | 189 |
1 files changed, 149 insertions, 40 deletions
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 965dfb575e5a..4ccaeaecd14c 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" |
@@ -97,6 +98,8 @@ bfad_fc4_probe(struct bfad_s *bfad) | |||
97 | 98 | ||
98 | if (ipfc_enable) | 99 | if (ipfc_enable) |
99 | bfad_ipfc_probe(bfad); | 100 | bfad_ipfc_probe(bfad); |
101 | |||
102 | bfad->bfad_flags |= BFAD_FC4_PROBE_DONE; | ||
100 | ext: | 103 | ext: |
101 | return rc; | 104 | return rc; |
102 | } | 105 | } |
@@ -108,6 +111,7 @@ bfad_fc4_probe_undo(struct bfad_s *bfad) | |||
108 | bfad_tm_probe_undo(bfad); | 111 | bfad_tm_probe_undo(bfad); |
109 | if (ipfc_enable) | 112 | if (ipfc_enable) |
110 | bfad_ipfc_probe_undo(bfad); | 113 | bfad_ipfc_probe_undo(bfad); |
114 | bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE; | ||
111 | } | 115 | } |
112 | 116 | ||
113 | static void | 117 | static void |
@@ -175,9 +179,19 @@ bfa_cb_init(void *drv, bfa_status_t init_status) | |||
175 | { | 179 | { |
176 | struct bfad_s *bfad = drv; | 180 | struct bfad_s *bfad = drv; |
177 | 181 | ||
178 | if (init_status == BFA_STATUS_OK) | 182 | if (init_status == BFA_STATUS_OK) { |
179 | bfad->bfad_flags |= BFAD_HAL_INIT_DONE; | 183 | bfad->bfad_flags |= BFAD_HAL_INIT_DONE; |
180 | 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 | |||
181 | complete(&bfad->comp); | 195 | complete(&bfad->comp); |
182 | } | 196 | } |
183 | 197 | ||
@@ -749,7 +763,13 @@ bfad_drv_init(struct bfad_s *bfad) | |||
749 | bfa_fcs_trc_init(&bfad->bfa_fcs, bfad->trcmod); | 763 | bfa_fcs_trc_init(&bfad->bfa_fcs, bfad->trcmod); |
750 | bfa_fcs_aen_init(&bfad->bfa_fcs, bfad->aen); | 764 | bfa_fcs_aen_init(&bfad->bfa_fcs, bfad->aen); |
751 | bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE); | 765 | bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE); |
752 | bfa_fcs_init(&bfad->bfa_fcs); | 766 | |
767 | /* Do FCS init only when HAL init is done */ | ||
768 | if ((bfad->bfad_flags & BFAD_HAL_INIT_DONE)) { | ||
769 | bfa_fcs_init(&bfad->bfa_fcs); | ||
770 | bfad->bfad_flags |= BFAD_FCS_INIT_DONE; | ||
771 | } | ||
772 | |||
753 | bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info); | 773 | bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info); |
754 | bfa_fcs_set_fdmi_param(&bfad->bfa_fcs, fdmi_enable); | 774 | bfa_fcs_set_fdmi_param(&bfad->bfa_fcs, fdmi_enable); |
755 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | 775 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); |
@@ -767,12 +787,22 @@ out_hal_mem_alloc_failure: | |||
767 | void | 787 | void |
768 | bfad_drv_uninit(struct bfad_s *bfad) | 788 | bfad_drv_uninit(struct bfad_s *bfad) |
769 | { | 789 | { |
790 | unsigned long flags; | ||
791 | |||
792 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
793 | init_completion(&bfad->comp); | ||
794 | bfa_stop(&bfad->bfa); | ||
795 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
796 | wait_for_completion(&bfad->comp); | ||
797 | |||
770 | del_timer_sync(&bfad->hal_tmo); | 798 | del_timer_sync(&bfad->hal_tmo); |
771 | bfa_isr_disable(&bfad->bfa); | 799 | bfa_isr_disable(&bfad->bfa); |
772 | bfa_detach(&bfad->bfa); | 800 | bfa_detach(&bfad->bfa); |
773 | bfad_remove_intr(bfad); | 801 | bfad_remove_intr(bfad); |
774 | bfa_assert(list_empty(&bfad->file_q)); | 802 | bfa_assert(list_empty(&bfad->file_q)); |
775 | bfad_hal_mem_release(bfad); | 803 | bfad_hal_mem_release(bfad); |
804 | |||
805 | bfad->bfad_flags &= ~BFAD_DRV_INIT_DONE; | ||
776 | } | 806 | } |
777 | 807 | ||
778 | void | 808 | void |
@@ -863,6 +893,86 @@ bfad_drv_log_level_set(struct bfad_s *bfad) | |||
863 | bfa_log_set_level_all(&bfad->log_data, log_level); | 893 | bfa_log_set_level_all(&bfad->log_data, log_level); |
864 | } | 894 | } |
865 | 895 | ||
896 | bfa_status_t | ||
897 | bfad_start_ops(struct bfad_s *bfad) | ||
898 | { | ||
899 | int retval; | ||
900 | |||
901 | /* PPORT FCS config */ | ||
902 | bfad_fcs_port_cfg(bfad); | ||
903 | |||
904 | retval = bfad_cfg_pport(bfad, BFA_PORT_ROLE_FCP_IM); | ||
905 | if (retval != BFA_STATUS_OK) | ||
906 | goto out_cfg_pport_failure; | ||
907 | |||
908 | /* BFAD level FC4 (IM/TM/IPFC) specific resource allocation */ | ||
909 | retval = bfad_fc4_probe(bfad); | ||
910 | if (retval != BFA_STATUS_OK) { | ||
911 | printk(KERN_WARNING "bfad_fc4_probe failed\n"); | ||
912 | goto out_fc4_probe_failure; | ||
913 | } | ||
914 | |||
915 | bfad_drv_start(bfad); | ||
916 | |||
917 | /* | ||
918 | * If bfa_linkup_delay is set to -1 default; try to retrive the | ||
919 | * value using the bfad_os_get_linkup_delay(); else use the | ||
920 | * passed in module param value as the bfa_linkup_delay. | ||
921 | */ | ||
922 | if (bfa_linkup_delay < 0) { | ||
923 | |||
924 | bfa_linkup_delay = bfad_os_get_linkup_delay(bfad); | ||
925 | bfad_os_rport_online_wait(bfad); | ||
926 | bfa_linkup_delay = -1; | ||
927 | |||
928 | } else { | ||
929 | bfad_os_rport_online_wait(bfad); | ||
930 | } | ||
931 | |||
932 | bfa_log(bfad->logmod, BFA_LOG_LINUX_DEVICE_CLAIMED, bfad->pci_name); | ||
933 | |||
934 | return BFA_STATUS_OK; | ||
935 | |||
936 | out_fc4_probe_failure: | ||
937 | bfad_fc4_probe_undo(bfad); | ||
938 | bfad_uncfg_pport(bfad); | ||
939 | out_cfg_pport_failure: | ||
940 | return BFA_STATUS_FAILED; | ||
941 | } | ||
942 | |||
943 | int | ||
944 | bfad_worker (void *ptr) | ||
945 | { | ||
946 | struct bfad_s *bfad; | ||
947 | unsigned long flags; | ||
948 | |||
949 | bfad = (struct bfad_s *)ptr; | ||
950 | |||
951 | while (!kthread_should_stop()) { | ||
952 | |||
953 | /* Check if the FCS init is done from bfad_drv_init; | ||
954 | * if not done do FCS init and set the flag. | ||
955 | */ | ||
956 | if (!(bfad->bfad_flags & BFAD_FCS_INIT_DONE)) { | ||
957 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
958 | bfa_fcs_init(&bfad->bfa_fcs); | ||
959 | bfad->bfad_flags |= BFAD_FCS_INIT_DONE; | ||
960 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
961 | } | ||
962 | |||
963 | /* Start the bfad operations after HAL init done */ | ||
964 | bfad_start_ops(bfad); | ||
965 | |||
966 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
967 | bfad->bfad_tsk = NULL; | ||
968 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
969 | |||
970 | break; | ||
971 | } | ||
972 | |||
973 | return 0; | ||
974 | } | ||
975 | |||
866 | /* | 976 | /* |
867 | * PCI_entry PCI driver entries * { | 977 | * PCI_entry PCI driver entries * { |
868 | */ | 978 | */ |
@@ -937,57 +1047,39 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
937 | bfad->ref_count = 0; | 1047 | bfad->ref_count = 0; |
938 | bfad->pport.bfad = bfad; | 1048 | bfad->pport.bfad = bfad; |
939 | 1049 | ||
1050 | bfad->bfad_tsk = kthread_create(bfad_worker, (void *) bfad, "%s", | ||
1051 | "bfad_worker"); | ||
1052 | if (IS_ERR(bfad->bfad_tsk)) { | ||
1053 | printk(KERN_INFO "bfad[%d]: Kernel thread" | ||
1054 | " creation failed!\n", | ||
1055 | bfad->inst_no); | ||
1056 | goto out_kthread_create_failure; | ||
1057 | } | ||
1058 | |||
940 | retval = bfad_drv_init(bfad); | 1059 | retval = bfad_drv_init(bfad); |
941 | if (retval != BFA_STATUS_OK) | 1060 | if (retval != BFA_STATUS_OK) |
942 | goto out_drv_init_failure; | 1061 | goto out_drv_init_failure; |
943 | if (!(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) { | 1062 | if (!(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) { |
1063 | bfad->bfad_flags |= BFAD_HAL_INIT_FAIL; | ||
944 | printk(KERN_WARNING "bfad%d: hal init failed\n", bfad->inst_no); | 1064 | printk(KERN_WARNING "bfad%d: hal init failed\n", bfad->inst_no); |
945 | goto ok; | 1065 | goto ok; |
946 | } | 1066 | } |
947 | 1067 | ||
948 | /* | 1068 | retval = bfad_start_ops(bfad); |
949 | * PPORT FCS config | ||
950 | */ | ||
951 | bfad_fcs_port_cfg(bfad); | ||
952 | |||
953 | retval = bfad_cfg_pport(bfad, BFA_PORT_ROLE_FCP_IM); | ||
954 | if (retval != BFA_STATUS_OK) | 1069 | if (retval != BFA_STATUS_OK) |
955 | goto out_cfg_pport_failure; | 1070 | goto out_start_ops_failure; |
956 | 1071 | ||
957 | /* | 1072 | kthread_stop(bfad->bfad_tsk); |
958 | * BFAD level FC4 (IM/TM/IPFC) specific resource allocation | 1073 | bfad->bfad_tsk = NULL; |
959 | */ | ||
960 | retval = bfad_fc4_probe(bfad); | ||
961 | if (retval != BFA_STATUS_OK) { | ||
962 | printk(KERN_WARNING "bfad_fc4_probe failed\n"); | ||
963 | goto out_fc4_probe_failure; | ||
964 | } | ||
965 | |||
966 | bfad_drv_start(bfad); | ||
967 | 1074 | ||
968 | /* | ||
969 | * If bfa_linkup_delay is set to -1 default; try to retrive the | ||
970 | * value using the bfad_os_get_linkup_delay(); else use the | ||
971 | * passed in module param value as the bfa_linkup_delay. | ||
972 | */ | ||
973 | if (bfa_linkup_delay < 0) { | ||
974 | bfa_linkup_delay = bfad_os_get_linkup_delay(bfad); | ||
975 | bfad_os_rport_online_wait(bfad); | ||
976 | bfa_linkup_delay = -1; | ||
977 | } else { | ||
978 | bfad_os_rport_online_wait(bfad); | ||
979 | } | ||
980 | |||
981 | bfa_log(bfad->logmod, BFA_LOG_LINUX_DEVICE_CLAIMED, bfad->pci_name); | ||
982 | ok: | 1075 | ok: |
983 | return 0; | 1076 | return 0; |
984 | 1077 | ||
985 | out_fc4_probe_failure: | 1078 | out_start_ops_failure: |
986 | bfad_fc4_probe_undo(bfad); | ||
987 | bfad_uncfg_pport(bfad); | ||
988 | out_cfg_pport_failure: | ||
989 | bfad_drv_uninit(bfad); | 1079 | bfad_drv_uninit(bfad); |
990 | out_drv_init_failure: | 1080 | out_drv_init_failure: |
1081 | kthread_stop(bfad->bfad_tsk); | ||
1082 | out_kthread_create_failure: | ||
991 | mutex_lock(&bfad_mutex); | 1083 | mutex_lock(&bfad_mutex); |
992 | bfad_inst--; | 1084 | bfad_inst--; |
993 | list_del(&bfad->list_entry); | 1085 | list_del(&bfad->list_entry); |
@@ -1012,6 +1104,11 @@ bfad_pci_remove(struct pci_dev *pdev) | |||
1012 | 1104 | ||
1013 | bfa_trc(bfad, bfad->inst_no); | 1105 | bfa_trc(bfad, bfad->inst_no); |
1014 | 1106 | ||
1107 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
1108 | if (bfad->bfad_tsk != NULL) | ||
1109 | kthread_stop(bfad->bfad_tsk); | ||
1110 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
1111 | |||
1015 | if ((bfad->bfad_flags & BFAD_DRV_INIT_DONE) | 1112 | if ((bfad->bfad_flags & BFAD_DRV_INIT_DONE) |
1016 | && !(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) { | 1113 | && !(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) { |
1017 | 1114 | ||
@@ -1028,13 +1125,25 @@ bfad_pci_remove(struct pci_dev *pdev) | |||
1028 | goto remove_sysfs; | 1125 | goto remove_sysfs; |
1029 | } | 1126 | } |
1030 | 1127 | ||
1031 | if (bfad->bfad_flags & BFAD_HAL_START_DONE) | 1128 | if (bfad->bfad_flags & BFAD_HAL_START_DONE) { |
1032 | bfad_drv_stop(bfad); | 1129 | bfad_drv_stop(bfad); |
1130 | } else if (bfad->bfad_flags & BFAD_DRV_INIT_DONE) { | ||
1131 | /* Invoking bfa_stop() before bfa_detach | ||
1132 | * when HAL and DRV init are success | ||
1133 | * but HAL start did not occur. | ||
1134 | */ | ||
1135 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
1136 | init_completion(&bfad->comp); | ||
1137 | bfa_stop(&bfad->bfa); | ||
1138 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
1139 | wait_for_completion(&bfad->comp); | ||
1140 | } | ||
1033 | 1141 | ||
1034 | bfad_remove_intr(bfad); | 1142 | bfad_remove_intr(bfad); |
1035 | |||
1036 | del_timer_sync(&bfad->hal_tmo); | 1143 | del_timer_sync(&bfad->hal_tmo); |
1037 | bfad_fc4_probe_undo(bfad); | 1144 | |
1145 | if (bfad->bfad_flags & BFAD_FC4_PROBE_DONE) | ||
1146 | bfad_fc4_probe_undo(bfad); | ||
1038 | 1147 | ||
1039 | if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE) | 1148 | if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE) |
1040 | bfad_uncfg_pport(bfad); | 1149 | bfad_uncfg_pport(bfad); |