aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/bfa/bfad.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/bfa/bfad.c')
-rw-r--r--drivers/scsi/bfa/bfad.c189
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;
100ext: 103ext:
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
113static void 117static 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:
767void 787void
768bfad_drv_uninit(struct bfad_s *bfad) 788bfad_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
778void 808void
@@ -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
896bfa_status_t
897bfad_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
936out_fc4_probe_failure:
937 bfad_fc4_probe_undo(bfad);
938 bfad_uncfg_pport(bfad);
939out_cfg_pport_failure:
940 return BFA_STATUS_FAILED;
941}
942
943int
944bfad_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);
982ok: 1075ok:
983 return 0; 1076 return 0;
984 1077
985out_fc4_probe_failure: 1078out_start_ops_failure:
986 bfad_fc4_probe_undo(bfad);
987 bfad_uncfg_pport(bfad);
988out_cfg_pport_failure:
989 bfad_drv_uninit(bfad); 1079 bfad_drv_uninit(bfad);
990out_drv_init_failure: 1080out_drv_init_failure:
1081 kthread_stop(bfad->bfad_tsk);
1082out_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);