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