aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/bfa/bfad.c
diff options
context:
space:
mode:
authorKrishna Gudipati <kgudipat@brocade.com>2010-03-03 20:44:02 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-03-04 05:47:02 -0500
commite67143243a1a6b47e1bdcda189ffac46d2a8744d (patch)
tree03a14641d29ec2d93eedcc921af7200c62f2e723 /drivers/scsi/bfa/bfad.c
parenta046bf0559018ba3d16c412fc4e1aa2be5f11f36 (diff)
[SCSI] bfa: Resume BFA operations after firmware mismatch is resolved.
bfad.c & bfad_drv.h: * Created a kernel thread from pci_probe that does the bfad start operations after BFA init done on a firmware mismatch. * The kernel thread on a fw mismatch waits for an event from IOC call back and is woken up from bfa_cb_init() on BFA init success. * In normal cases of no firmware mismatch this thread is terminated in pci_probe. bfa_fcs_lport.c, fabric.c, fcs_lport.h & vport.c: * Split the lport init to attach time and init time code, so that proper config attributes are set after firmware mismatch. bfa_iocfc.c: * Handle an IOC timer issue, where the IOC timer would expire before the init completion and send Init fail event to the driver, however IOC init continues and completes successfully at the later stage. The bfa and driver were not handling this kind of deferred init completion. Signed-off-by: Krishna Gudipati <kgudipat@brocade.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
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);