diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_base.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.c | 695 |
1 files changed, 541 insertions, 154 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 83035bd1c489..beda04a8404b 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c | |||
@@ -42,7 +42,6 @@ | |||
42 | * USA. | 42 | * USA. |
43 | */ | 43 | */ |
44 | 44 | ||
45 | #include <linux/version.h> | ||
46 | #include <linux/kernel.h> | 45 | #include <linux/kernel.h> |
47 | #include <linux/module.h> | 46 | #include <linux/module.h> |
48 | #include <linux/errno.h> | 47 | #include <linux/errno.h> |
@@ -82,6 +81,15 @@ static int missing_delay[2] = {-1, -1}; | |||
82 | module_param_array(missing_delay, int, NULL, 0); | 81 | module_param_array(missing_delay, int, NULL, 0); |
83 | MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay"); | 82 | MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay"); |
84 | 83 | ||
84 | static int mpt2sas_fwfault_debug; | ||
85 | MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault " | ||
86 | "and halt firmware - (default=0)"); | ||
87 | |||
88 | static int disable_discovery = -1; | ||
89 | module_param(disable_discovery, int, 0); | ||
90 | MODULE_PARM_DESC(disable_discovery, " disable discovery "); | ||
91 | |||
92 | |||
85 | /* diag_buffer_enable is bitwise | 93 | /* diag_buffer_enable is bitwise |
86 | * bit 0 set = TRACE | 94 | * bit 0 set = TRACE |
87 | * bit 1 set = SNAPSHOT | 95 | * bit 1 set = SNAPSHOT |
@@ -94,14 +102,6 @@ module_param(diag_buffer_enable, int, 0); | |||
94 | MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers " | 102 | MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers " |
95 | "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)"); | 103 | "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)"); |
96 | 104 | ||
97 | static int mpt2sas_fwfault_debug; | ||
98 | MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault " | ||
99 | "and halt firmware - (default=0)"); | ||
100 | |||
101 | static int disable_discovery = -1; | ||
102 | module_param(disable_discovery, int, 0); | ||
103 | MODULE_PARM_DESC(disable_discovery, " disable discovery "); | ||
104 | |||
105 | /** | 105 | /** |
106 | * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug. | 106 | * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug. |
107 | * | 107 | * |
@@ -692,6 +692,7 @@ mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
692 | memcpy(ioc->base_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); | 692 | memcpy(ioc->base_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); |
693 | } | 693 | } |
694 | ioc->base_cmds.status &= ~MPT2_CMD_PENDING; | 694 | ioc->base_cmds.status &= ~MPT2_CMD_PENDING; |
695 | |||
695 | complete(&ioc->base_cmds.done); | 696 | complete(&ioc->base_cmds.done); |
696 | return 1; | 697 | return 1; |
697 | } | 698 | } |
@@ -834,25 +835,31 @@ union reply_descriptor { | |||
834 | static irqreturn_t | 835 | static irqreturn_t |
835 | _base_interrupt(int irq, void *bus_id) | 836 | _base_interrupt(int irq, void *bus_id) |
836 | { | 837 | { |
838 | struct adapter_reply_queue *reply_q = bus_id; | ||
837 | union reply_descriptor rd; | 839 | union reply_descriptor rd; |
838 | u32 completed_cmds; | 840 | u32 completed_cmds; |
839 | u8 request_desript_type; | 841 | u8 request_desript_type; |
840 | u16 smid; | 842 | u16 smid; |
841 | u8 cb_idx; | 843 | u8 cb_idx; |
842 | u32 reply; | 844 | u32 reply; |
843 | u8 msix_index; | 845 | u8 msix_index = reply_q->msix_index; |
844 | struct MPT2SAS_ADAPTER *ioc = bus_id; | 846 | struct MPT2SAS_ADAPTER *ioc = reply_q->ioc; |
845 | Mpi2ReplyDescriptorsUnion_t *rpf; | 847 | Mpi2ReplyDescriptorsUnion_t *rpf; |
846 | u8 rc; | 848 | u8 rc; |
847 | 849 | ||
848 | if (ioc->mask_interrupts) | 850 | if (ioc->mask_interrupts) |
849 | return IRQ_NONE; | 851 | return IRQ_NONE; |
850 | 852 | ||
851 | rpf = &ioc->reply_post_free[ioc->reply_post_host_index]; | 853 | if (!atomic_add_unless(&reply_q->busy, 1, 1)) |
854 | return IRQ_NONE; | ||
855 | |||
856 | rpf = &reply_q->reply_post_free[reply_q->reply_post_host_index]; | ||
852 | request_desript_type = rpf->Default.ReplyFlags | 857 | request_desript_type = rpf->Default.ReplyFlags |
853 | & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; | 858 | & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; |
854 | if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) | 859 | if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) { |
860 | atomic_dec(&reply_q->busy); | ||
855 | return IRQ_NONE; | 861 | return IRQ_NONE; |
862 | } | ||
856 | 863 | ||
857 | completed_cmds = 0; | 864 | completed_cmds = 0; |
858 | cb_idx = 0xFF; | 865 | cb_idx = 0xFF; |
@@ -861,9 +868,7 @@ _base_interrupt(int irq, void *bus_id) | |||
861 | if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX) | 868 | if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX) |
862 | goto out; | 869 | goto out; |
863 | reply = 0; | 870 | reply = 0; |
864 | cb_idx = 0xFF; | ||
865 | smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1); | 871 | smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1); |
866 | msix_index = rpf->Default.MSIxIndex; | ||
867 | if (request_desript_type == | 872 | if (request_desript_type == |
868 | MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) { | 873 | MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) { |
869 | reply = le32_to_cpu | 874 | reply = le32_to_cpu |
@@ -907,32 +912,86 @@ _base_interrupt(int irq, void *bus_id) | |||
907 | next: | 912 | next: |
908 | 913 | ||
909 | rpf->Words = cpu_to_le64(ULLONG_MAX); | 914 | rpf->Words = cpu_to_le64(ULLONG_MAX); |
910 | ioc->reply_post_host_index = (ioc->reply_post_host_index == | 915 | reply_q->reply_post_host_index = |
916 | (reply_q->reply_post_host_index == | ||
911 | (ioc->reply_post_queue_depth - 1)) ? 0 : | 917 | (ioc->reply_post_queue_depth - 1)) ? 0 : |
912 | ioc->reply_post_host_index + 1; | 918 | reply_q->reply_post_host_index + 1; |
913 | request_desript_type = | 919 | request_desript_type = |
914 | ioc->reply_post_free[ioc->reply_post_host_index].Default. | 920 | reply_q->reply_post_free[reply_q->reply_post_host_index]. |
915 | ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; | 921 | Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; |
916 | completed_cmds++; | 922 | completed_cmds++; |
917 | if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) | 923 | if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) |
918 | goto out; | 924 | goto out; |
919 | if (!ioc->reply_post_host_index) | 925 | if (!reply_q->reply_post_host_index) |
920 | rpf = ioc->reply_post_free; | 926 | rpf = reply_q->reply_post_free; |
921 | else | 927 | else |
922 | rpf++; | 928 | rpf++; |
923 | } while (1); | 929 | } while (1); |
924 | 930 | ||
925 | out: | 931 | out: |
926 | 932 | ||
927 | if (!completed_cmds) | 933 | if (!completed_cmds) { |
934 | atomic_dec(&reply_q->busy); | ||
928 | return IRQ_NONE; | 935 | return IRQ_NONE; |
929 | 936 | } | |
930 | wmb(); | 937 | wmb(); |
931 | writel(ioc->reply_post_host_index, &ioc->chip->ReplyPostHostIndex); | 938 | if (ioc->is_warpdrive) { |
939 | writel(reply_q->reply_post_host_index, | ||
940 | ioc->reply_post_host_index[msix_index]); | ||
941 | atomic_dec(&reply_q->busy); | ||
942 | return IRQ_HANDLED; | ||
943 | } | ||
944 | writel(reply_q->reply_post_host_index | (msix_index << | ||
945 | MPI2_RPHI_MSIX_INDEX_SHIFT), &ioc->chip->ReplyPostHostIndex); | ||
946 | atomic_dec(&reply_q->busy); | ||
932 | return IRQ_HANDLED; | 947 | return IRQ_HANDLED; |
933 | } | 948 | } |
934 | 949 | ||
935 | /** | 950 | /** |
951 | * _base_is_controller_msix_enabled - is controller support muli-reply queues | ||
952 | * @ioc: per adapter object | ||
953 | * | ||
954 | */ | ||
955 | static inline int | ||
956 | _base_is_controller_msix_enabled(struct MPT2SAS_ADAPTER *ioc) | ||
957 | { | ||
958 | return (ioc->facts.IOCCapabilities & | ||
959 | MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable; | ||
960 | } | ||
961 | |||
962 | /** | ||
963 | * mpt2sas_base_flush_reply_queues - flushing the MSIX reply queues | ||
964 | * @ioc: per adapter object | ||
965 | * Context: ISR conext | ||
966 | * | ||
967 | * Called when a Task Management request has completed. We want | ||
968 | * to flush the other reply queues so all the outstanding IO has been | ||
969 | * completed back to OS before we process the TM completetion. | ||
970 | * | ||
971 | * Return nothing. | ||
972 | */ | ||
973 | void | ||
974 | mpt2sas_base_flush_reply_queues(struct MPT2SAS_ADAPTER *ioc) | ||
975 | { | ||
976 | struct adapter_reply_queue *reply_q; | ||
977 | |||
978 | /* If MSIX capability is turned off | ||
979 | * then multi-queues are not enabled | ||
980 | */ | ||
981 | if (!_base_is_controller_msix_enabled(ioc)) | ||
982 | return; | ||
983 | |||
984 | list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { | ||
985 | if (ioc->shost_recovery) | ||
986 | return; | ||
987 | /* TMs are on msix_index == 0 */ | ||
988 | if (reply_q->msix_index == 0) | ||
989 | continue; | ||
990 | _base_interrupt(reply_q->vector, (void *)reply_q); | ||
991 | } | ||
992 | } | ||
993 | |||
994 | /** | ||
936 | * mpt2sas_base_release_callback_handler - clear interrupt callback handler | 995 | * mpt2sas_base_release_callback_handler - clear interrupt callback handler |
937 | * @cb_idx: callback index | 996 | * @cb_idx: callback index |
938 | * | 997 | * |
@@ -1082,74 +1141,171 @@ _base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev) | |||
1082 | } | 1141 | } |
1083 | 1142 | ||
1084 | /** | 1143 | /** |
1085 | * _base_save_msix_table - backup msix vector table | 1144 | * _base_check_enable_msix - checks MSIX capabable. |
1086 | * @ioc: per adapter object | 1145 | * @ioc: per adapter object |
1087 | * | 1146 | * |
1088 | * This address an errata where diag reset clears out the table | 1147 | * Check to see if card is capable of MSIX, and set number |
1148 | * of available msix vectors | ||
1089 | */ | 1149 | */ |
1090 | static void | 1150 | static int |
1091 | _base_save_msix_table(struct MPT2SAS_ADAPTER *ioc) | 1151 | _base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc) |
1092 | { | 1152 | { |
1093 | int i; | 1153 | int base; |
1154 | u16 message_control; | ||
1094 | 1155 | ||
1095 | if (!ioc->msix_enable || ioc->msix_table_backup == NULL) | ||
1096 | return; | ||
1097 | 1156 | ||
1098 | for (i = 0; i < ioc->msix_vector_count; i++) | 1157 | base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX); |
1099 | ioc->msix_table_backup[i] = ioc->msix_table[i]; | 1158 | if (!base) { |
1159 | dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not " | ||
1160 | "supported\n", ioc->name)); | ||
1161 | return -EINVAL; | ||
1162 | } | ||
1163 | |||
1164 | /* get msix vector count */ | ||
1165 | /* NUMA_IO not supported for older controllers */ | ||
1166 | if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2004 || | ||
1167 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 || | ||
1168 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_1 || | ||
1169 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_2 || | ||
1170 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_3 || | ||
1171 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_1 || | ||
1172 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_2) | ||
1173 | ioc->msix_vector_count = 1; | ||
1174 | else { | ||
1175 | pci_read_config_word(ioc->pdev, base + 2, &message_control); | ||
1176 | ioc->msix_vector_count = (message_control & 0x3FF) + 1; | ||
1177 | } | ||
1178 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "msix is supported, " | ||
1179 | "vector_count(%d)\n", ioc->name, ioc->msix_vector_count)); | ||
1180 | |||
1181 | return 0; | ||
1100 | } | 1182 | } |
1101 | 1183 | ||
1102 | /** | 1184 | /** |
1103 | * _base_restore_msix_table - this restores the msix vector table | 1185 | * _base_free_irq - free irq |
1104 | * @ioc: per adapter object | 1186 | * @ioc: per adapter object |
1105 | * | 1187 | * |
1188 | * Freeing respective reply_queue from the list. | ||
1106 | */ | 1189 | */ |
1107 | static void | 1190 | static void |
1108 | _base_restore_msix_table(struct MPT2SAS_ADAPTER *ioc) | 1191 | _base_free_irq(struct MPT2SAS_ADAPTER *ioc) |
1109 | { | 1192 | { |
1110 | int i; | 1193 | struct adapter_reply_queue *reply_q, *next; |
1111 | 1194 | ||
1112 | if (!ioc->msix_enable || ioc->msix_table_backup == NULL) | 1195 | if (list_empty(&ioc->reply_queue_list)) |
1113 | return; | 1196 | return; |
1114 | 1197 | ||
1115 | for (i = 0; i < ioc->msix_vector_count; i++) | 1198 | list_for_each_entry_safe(reply_q, next, &ioc->reply_queue_list, list) { |
1116 | ioc->msix_table[i] = ioc->msix_table_backup[i]; | 1199 | list_del(&reply_q->list); |
1200 | synchronize_irq(reply_q->vector); | ||
1201 | free_irq(reply_q->vector, reply_q); | ||
1202 | kfree(reply_q); | ||
1203 | } | ||
1117 | } | 1204 | } |
1118 | 1205 | ||
1119 | /** | 1206 | /** |
1120 | * _base_check_enable_msix - checks MSIX capabable. | 1207 | * _base_request_irq - request irq |
1121 | * @ioc: per adapter object | 1208 | * @ioc: per adapter object |
1209 | * @index: msix index into vector table | ||
1210 | * @vector: irq vector | ||
1122 | * | 1211 | * |
1123 | * Check to see if card is capable of MSIX, and set number | 1212 | * Inserting respective reply_queue into the list. |
1124 | * of available msix vectors | ||
1125 | */ | 1213 | */ |
1126 | static int | 1214 | static int |
1127 | _base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc) | 1215 | _base_request_irq(struct MPT2SAS_ADAPTER *ioc, u8 index, u32 vector) |
1128 | { | 1216 | { |
1129 | int base; | 1217 | struct adapter_reply_queue *reply_q; |
1130 | u16 message_control; | 1218 | int r; |
1131 | u32 msix_table_offset; | ||
1132 | 1219 | ||
1133 | base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX); | 1220 | reply_q = kzalloc(sizeof(struct adapter_reply_queue), GFP_KERNEL); |
1134 | if (!base) { | 1221 | if (!reply_q) { |
1135 | dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not " | 1222 | printk(MPT2SAS_ERR_FMT "unable to allocate memory %d!\n", |
1136 | "supported\n", ioc->name)); | 1223 | ioc->name, (int)sizeof(struct adapter_reply_queue)); |
1137 | return -EINVAL; | 1224 | return -ENOMEM; |
1225 | } | ||
1226 | reply_q->ioc = ioc; | ||
1227 | reply_q->msix_index = index; | ||
1228 | reply_q->vector = vector; | ||
1229 | atomic_set(&reply_q->busy, 0); | ||
1230 | if (ioc->msix_enable) | ||
1231 | snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-msix%d", | ||
1232 | MPT2SAS_DRIVER_NAME, ioc->id, index); | ||
1233 | else | ||
1234 | snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d", | ||
1235 | MPT2SAS_DRIVER_NAME, ioc->id); | ||
1236 | r = request_irq(vector, _base_interrupt, IRQF_SHARED, reply_q->name, | ||
1237 | reply_q); | ||
1238 | if (r) { | ||
1239 | printk(MPT2SAS_ERR_FMT "unable to allocate interrupt %d!\n", | ||
1240 | reply_q->name, vector); | ||
1241 | kfree(reply_q); | ||
1242 | return -EBUSY; | ||
1138 | } | 1243 | } |
1139 | 1244 | ||
1140 | /* get msix vector count */ | 1245 | INIT_LIST_HEAD(&reply_q->list); |
1141 | pci_read_config_word(ioc->pdev, base + 2, &message_control); | 1246 | list_add_tail(&reply_q->list, &ioc->reply_queue_list); |
1142 | ioc->msix_vector_count = (message_control & 0x3FF) + 1; | 1247 | return 0; |
1248 | } | ||
1143 | 1249 | ||
1144 | /* get msix table */ | 1250 | /** |
1145 | pci_read_config_dword(ioc->pdev, base + 4, &msix_table_offset); | 1251 | * _base_assign_reply_queues - assigning msix index for each cpu |
1146 | msix_table_offset &= 0xFFFFFFF8; | 1252 | * @ioc: per adapter object |
1147 | ioc->msix_table = (u32 *)((void *)ioc->chip + msix_table_offset); | 1253 | * |
1254 | * The enduser would need to set the affinity via /proc/irq/#/smp_affinity | ||
1255 | * | ||
1256 | * It would nice if we could call irq_set_affinity, however it is not | ||
1257 | * an exported symbol | ||
1258 | */ | ||
1259 | static void | ||
1260 | _base_assign_reply_queues(struct MPT2SAS_ADAPTER *ioc) | ||
1261 | { | ||
1262 | struct adapter_reply_queue *reply_q; | ||
1263 | int cpu_id; | ||
1264 | int cpu_grouping, loop, grouping, grouping_mod; | ||
1148 | 1265 | ||
1149 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "msix is supported, " | 1266 | if (!_base_is_controller_msix_enabled(ioc)) |
1150 | "vector_count(%d), table_offset(0x%08x), table(%p)\n", ioc->name, | 1267 | return; |
1151 | ioc->msix_vector_count, msix_table_offset, ioc->msix_table)); | 1268 | |
1152 | return 0; | 1269 | memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz); |
1270 | /* when there are more cpus than available msix vectors, | ||
1271 | * then group cpus togeather on same irq | ||
1272 | */ | ||
1273 | if (ioc->cpu_count > ioc->msix_vector_count) { | ||
1274 | grouping = ioc->cpu_count / ioc->msix_vector_count; | ||
1275 | grouping_mod = ioc->cpu_count % ioc->msix_vector_count; | ||
1276 | if (grouping < 2 || (grouping == 2 && !grouping_mod)) | ||
1277 | cpu_grouping = 2; | ||
1278 | else if (grouping < 4 || (grouping == 4 && !grouping_mod)) | ||
1279 | cpu_grouping = 4; | ||
1280 | else if (grouping < 8 || (grouping == 8 && !grouping_mod)) | ||
1281 | cpu_grouping = 8; | ||
1282 | else | ||
1283 | cpu_grouping = 16; | ||
1284 | } else | ||
1285 | cpu_grouping = 0; | ||
1286 | |||
1287 | loop = 0; | ||
1288 | reply_q = list_entry(ioc->reply_queue_list.next, | ||
1289 | struct adapter_reply_queue, list); | ||
1290 | for_each_online_cpu(cpu_id) { | ||
1291 | if (!cpu_grouping) { | ||
1292 | ioc->cpu_msix_table[cpu_id] = reply_q->msix_index; | ||
1293 | reply_q = list_entry(reply_q->list.next, | ||
1294 | struct adapter_reply_queue, list); | ||
1295 | } else { | ||
1296 | if (loop < cpu_grouping) { | ||
1297 | ioc->cpu_msix_table[cpu_id] = | ||
1298 | reply_q->msix_index; | ||
1299 | loop++; | ||
1300 | } else { | ||
1301 | reply_q = list_entry(reply_q->list.next, | ||
1302 | struct adapter_reply_queue, list); | ||
1303 | ioc->cpu_msix_table[cpu_id] = | ||
1304 | reply_q->msix_index; | ||
1305 | loop = 1; | ||
1306 | } | ||
1307 | } | ||
1308 | } | ||
1153 | } | 1309 | } |
1154 | 1310 | ||
1155 | /** | 1311 | /** |
@@ -1162,8 +1318,6 @@ _base_disable_msix(struct MPT2SAS_ADAPTER *ioc) | |||
1162 | { | 1318 | { |
1163 | if (ioc->msix_enable) { | 1319 | if (ioc->msix_enable) { |
1164 | pci_disable_msix(ioc->pdev); | 1320 | pci_disable_msix(ioc->pdev); |
1165 | kfree(ioc->msix_table_backup); | ||
1166 | ioc->msix_table_backup = NULL; | ||
1167 | ioc->msix_enable = 0; | 1321 | ioc->msix_enable = 0; |
1168 | } | 1322 | } |
1169 | } | 1323 | } |
@@ -1176,10 +1330,13 @@ _base_disable_msix(struct MPT2SAS_ADAPTER *ioc) | |||
1176 | static int | 1330 | static int |
1177 | _base_enable_msix(struct MPT2SAS_ADAPTER *ioc) | 1331 | _base_enable_msix(struct MPT2SAS_ADAPTER *ioc) |
1178 | { | 1332 | { |
1179 | struct msix_entry entries; | 1333 | struct msix_entry *entries, *a; |
1180 | int r; | 1334 | int r; |
1335 | int i; | ||
1181 | u8 try_msix = 0; | 1336 | u8 try_msix = 0; |
1182 | 1337 | ||
1338 | INIT_LIST_HEAD(&ioc->reply_queue_list); | ||
1339 | |||
1183 | if (msix_disable == -1 || msix_disable == 0) | 1340 | if (msix_disable == -1 || msix_disable == 0) |
1184 | try_msix = 1; | 1341 | try_msix = 1; |
1185 | 1342 | ||
@@ -1189,51 +1346,48 @@ _base_enable_msix(struct MPT2SAS_ADAPTER *ioc) | |||
1189 | if (_base_check_enable_msix(ioc) != 0) | 1346 | if (_base_check_enable_msix(ioc) != 0) |
1190 | goto try_ioapic; | 1347 | goto try_ioapic; |
1191 | 1348 | ||
1192 | ioc->msix_table_backup = kcalloc(ioc->msix_vector_count, | 1349 | ioc->reply_queue_count = min_t(u8, ioc->cpu_count, |
1193 | sizeof(u32), GFP_KERNEL); | 1350 | ioc->msix_vector_count); |
1194 | if (!ioc->msix_table_backup) { | 1351 | |
1195 | dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation for " | 1352 | entries = kcalloc(ioc->reply_queue_count, sizeof(struct msix_entry), |
1196 | "msix_table_backup failed!!!\n", ioc->name)); | 1353 | GFP_KERNEL); |
1354 | if (!entries) { | ||
1355 | dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "kcalloc " | ||
1356 | "failed @ at %s:%d/%s() !!!\n", ioc->name, __FILE__, | ||
1357 | __LINE__, __func__)); | ||
1197 | goto try_ioapic; | 1358 | goto try_ioapic; |
1198 | } | 1359 | } |
1199 | 1360 | ||
1200 | memset(&entries, 0, sizeof(struct msix_entry)); | 1361 | for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++) |
1201 | r = pci_enable_msix(ioc->pdev, &entries, 1); | 1362 | a->entry = i; |
1363 | |||
1364 | r = pci_enable_msix(ioc->pdev, entries, ioc->reply_queue_count); | ||
1202 | if (r) { | 1365 | if (r) { |
1203 | dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "pci_enable_msix " | 1366 | dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "pci_enable_msix " |
1204 | "failed (r=%d) !!!\n", ioc->name, r)); | 1367 | "failed (r=%d) !!!\n", ioc->name, r)); |
1368 | kfree(entries); | ||
1205 | goto try_ioapic; | 1369 | goto try_ioapic; |
1206 | } | 1370 | } |
1207 | 1371 | ||
1208 | r = request_irq(entries.vector, _base_interrupt, IRQF_SHARED, | 1372 | ioc->msix_enable = 1; |
1209 | ioc->name, ioc); | 1373 | for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++) { |
1210 | if (r) { | 1374 | r = _base_request_irq(ioc, i, a->vector); |
1211 | dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "unable to allocate " | 1375 | if (r) { |
1212 | "interrupt %d !!!\n", ioc->name, entries.vector)); | 1376 | _base_free_irq(ioc); |
1213 | pci_disable_msix(ioc->pdev); | 1377 | _base_disable_msix(ioc); |
1214 | goto try_ioapic; | 1378 | kfree(entries); |
1379 | goto try_ioapic; | ||
1380 | } | ||
1215 | } | 1381 | } |
1216 | 1382 | ||
1217 | ioc->pci_irq = entries.vector; | 1383 | kfree(entries); |
1218 | ioc->msix_enable = 1; | ||
1219 | return 0; | 1384 | return 0; |
1220 | 1385 | ||
1221 | /* failback to io_apic interrupt routing */ | 1386 | /* failback to io_apic interrupt routing */ |
1222 | try_ioapic: | 1387 | try_ioapic: |
1223 | 1388 | ||
1224 | r = request_irq(ioc->pdev->irq, _base_interrupt, IRQF_SHARED, | 1389 | r = _base_request_irq(ioc, 0, ioc->pdev->irq); |
1225 | ioc->name, ioc); | ||
1226 | if (r) { | ||
1227 | printk(MPT2SAS_ERR_FMT "unable to allocate interrupt %d!\n", | ||
1228 | ioc->name, ioc->pdev->irq); | ||
1229 | r = -EBUSY; | ||
1230 | goto out_fail; | ||
1231 | } | ||
1232 | |||
1233 | ioc->pci_irq = ioc->pdev->irq; | ||
1234 | return 0; | ||
1235 | 1390 | ||
1236 | out_fail: | ||
1237 | return r; | 1391 | return r; |
1238 | } | 1392 | } |
1239 | 1393 | ||
@@ -1252,6 +1406,7 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) | |||
1252 | int i, r = 0; | 1406 | int i, r = 0; |
1253 | u64 pio_chip = 0; | 1407 | u64 pio_chip = 0; |
1254 | u64 chip_phys = 0; | 1408 | u64 chip_phys = 0; |
1409 | struct adapter_reply_queue *reply_q; | ||
1255 | 1410 | ||
1256 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", | 1411 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", |
1257 | ioc->name, __func__)); | 1412 | ioc->name, __func__)); |
@@ -1314,9 +1469,11 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) | |||
1314 | if (r) | 1469 | if (r) |
1315 | goto out_fail; | 1470 | goto out_fail; |
1316 | 1471 | ||
1317 | printk(MPT2SAS_INFO_FMT "%s: IRQ %d\n", | 1472 | list_for_each_entry(reply_q, &ioc->reply_queue_list, list) |
1318 | ioc->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" : | 1473 | printk(MPT2SAS_INFO_FMT "%s: IRQ %d\n", |
1319 | "IO-APIC enabled"), ioc->pci_irq); | 1474 | reply_q->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" : |
1475 | "IO-APIC enabled"), reply_q->vector); | ||
1476 | |||
1320 | printk(MPT2SAS_INFO_FMT "iomem(0x%016llx), mapped(0x%p), size(%d)\n", | 1477 | printk(MPT2SAS_INFO_FMT "iomem(0x%016llx), mapped(0x%p), size(%d)\n", |
1321 | ioc->name, (unsigned long long)chip_phys, ioc->chip, memap_sz); | 1478 | ioc->name, (unsigned long long)chip_phys, ioc->chip, memap_sz); |
1322 | printk(MPT2SAS_INFO_FMT "ioport(0x%016llx), size(%d)\n", | 1479 | printk(MPT2SAS_INFO_FMT "ioport(0x%016llx), size(%d)\n", |
@@ -1331,7 +1488,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) | |||
1331 | if (ioc->chip_phys) | 1488 | if (ioc->chip_phys) |
1332 | iounmap(ioc->chip); | 1489 | iounmap(ioc->chip); |
1333 | ioc->chip_phys = 0; | 1490 | ioc->chip_phys = 0; |
1334 | ioc->pci_irq = -1; | ||
1335 | pci_release_selected_regions(ioc->pdev, ioc->bars); | 1491 | pci_release_selected_regions(ioc->pdev, ioc->bars); |
1336 | pci_disable_pcie_error_reporting(pdev); | 1492 | pci_disable_pcie_error_reporting(pdev); |
1337 | pci_disable_device(pdev); | 1493 | pci_disable_device(pdev); |
@@ -1578,6 +1734,12 @@ static inline void _base_writeq(__u64 b, volatile void __iomem *addr, | |||
1578 | } | 1734 | } |
1579 | #endif | 1735 | #endif |
1580 | 1736 | ||
1737 | static inline u8 | ||
1738 | _base_get_msix_index(struct MPT2SAS_ADAPTER *ioc) | ||
1739 | { | ||
1740 | return ioc->cpu_msix_table[smp_processor_id()]; | ||
1741 | } | ||
1742 | |||
1581 | /** | 1743 | /** |
1582 | * mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware | 1744 | * mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware |
1583 | * @ioc: per adapter object | 1745 | * @ioc: per adapter object |
@@ -1594,7 +1756,7 @@ mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u16 handle) | |||
1594 | 1756 | ||
1595 | 1757 | ||
1596 | descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; | 1758 | descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; |
1597 | descriptor.SCSIIO.MSIxIndex = 0; /* TODO */ | 1759 | descriptor.SCSIIO.MSIxIndex = _base_get_msix_index(ioc); |
1598 | descriptor.SCSIIO.SMID = cpu_to_le16(smid); | 1760 | descriptor.SCSIIO.SMID = cpu_to_le16(smid); |
1599 | descriptor.SCSIIO.DevHandle = cpu_to_le16(handle); | 1761 | descriptor.SCSIIO.DevHandle = cpu_to_le16(handle); |
1600 | descriptor.SCSIIO.LMID = 0; | 1762 | descriptor.SCSIIO.LMID = 0; |
@@ -1618,7 +1780,7 @@ mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid) | |||
1618 | 1780 | ||
1619 | descriptor.HighPriority.RequestFlags = | 1781 | descriptor.HighPriority.RequestFlags = |
1620 | MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; | 1782 | MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; |
1621 | descriptor.HighPriority.MSIxIndex = 0; /* TODO */ | 1783 | descriptor.HighPriority.MSIxIndex = 0; |
1622 | descriptor.HighPriority.SMID = cpu_to_le16(smid); | 1784 | descriptor.HighPriority.SMID = cpu_to_le16(smid); |
1623 | descriptor.HighPriority.LMID = 0; | 1785 | descriptor.HighPriority.LMID = 0; |
1624 | descriptor.HighPriority.Reserved1 = 0; | 1786 | descriptor.HighPriority.Reserved1 = 0; |
@@ -1640,7 +1802,7 @@ mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid) | |||
1640 | u64 *request = (u64 *)&descriptor; | 1802 | u64 *request = (u64 *)&descriptor; |
1641 | 1803 | ||
1642 | descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; | 1804 | descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; |
1643 | descriptor.Default.MSIxIndex = 0; /* TODO */ | 1805 | descriptor.Default.MSIxIndex = _base_get_msix_index(ioc); |
1644 | descriptor.Default.SMID = cpu_to_le16(smid); | 1806 | descriptor.Default.SMID = cpu_to_le16(smid); |
1645 | descriptor.Default.LMID = 0; | 1807 | descriptor.Default.LMID = 0; |
1646 | descriptor.Default.DescriptorTypeDependent = 0; | 1808 | descriptor.Default.DescriptorTypeDependent = 0; |
@@ -1665,7 +1827,7 @@ mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid, | |||
1665 | 1827 | ||
1666 | descriptor.SCSITarget.RequestFlags = | 1828 | descriptor.SCSITarget.RequestFlags = |
1667 | MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET; | 1829 | MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET; |
1668 | descriptor.SCSITarget.MSIxIndex = 0; /* TODO */ | 1830 | descriptor.SCSITarget.MSIxIndex = _base_get_msix_index(ioc); |
1669 | descriptor.SCSITarget.SMID = cpu_to_le16(smid); | 1831 | descriptor.SCSITarget.SMID = cpu_to_le16(smid); |
1670 | descriptor.SCSITarget.LMID = 0; | 1832 | descriptor.SCSITarget.LMID = 0; |
1671 | descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index); | 1833 | descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index); |
@@ -2172,7 +2334,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
2172 | u16 max_sge_elements; | 2334 | u16 max_sge_elements; |
2173 | u16 num_of_reply_frames; | 2335 | u16 num_of_reply_frames; |
2174 | u16 chains_needed_per_io; | 2336 | u16 chains_needed_per_io; |
2175 | u32 sz, total_sz; | 2337 | u32 sz, total_sz, reply_post_free_sz; |
2176 | u32 retry_sz; | 2338 | u32 retry_sz; |
2177 | u16 max_request_credit; | 2339 | u16 max_request_credit; |
2178 | int i; | 2340 | int i; |
@@ -2499,7 +2661,12 @@ chain_done: | |||
2499 | total_sz += sz; | 2661 | total_sz += sz; |
2500 | 2662 | ||
2501 | /* reply post queue, 16 byte align */ | 2663 | /* reply post queue, 16 byte align */ |
2502 | sz = ioc->reply_post_queue_depth * sizeof(Mpi2DefaultReplyDescriptor_t); | 2664 | reply_post_free_sz = ioc->reply_post_queue_depth * |
2665 | sizeof(Mpi2DefaultReplyDescriptor_t); | ||
2666 | if (_base_is_controller_msix_enabled(ioc)) | ||
2667 | sz = reply_post_free_sz * ioc->reply_queue_count; | ||
2668 | else | ||
2669 | sz = reply_post_free_sz; | ||
2503 | ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool", | 2670 | ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool", |
2504 | ioc->pdev, sz, 16, 0); | 2671 | ioc->pdev, sz, 16, 0); |
2505 | if (!ioc->reply_post_free_dma_pool) { | 2672 | if (!ioc->reply_post_free_dma_pool) { |
@@ -3187,6 +3354,7 @@ _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
3187 | facts->MaxChainDepth = mpi_reply.MaxChainDepth; | 3354 | facts->MaxChainDepth = mpi_reply.MaxChainDepth; |
3188 | facts->WhoInit = mpi_reply.WhoInit; | 3355 | facts->WhoInit = mpi_reply.WhoInit; |
3189 | facts->NumberOfPorts = mpi_reply.NumberOfPorts; | 3356 | facts->NumberOfPorts = mpi_reply.NumberOfPorts; |
3357 | facts->MaxMSIxVectors = mpi_reply.MaxMSIxVectors; | ||
3190 | facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit); | 3358 | facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit); |
3191 | facts->MaxReplyDescriptorPostQueueDepth = | 3359 | facts->MaxReplyDescriptorPostQueueDepth = |
3192 | le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth); | 3360 | le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth); |
@@ -3244,7 +3412,8 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
3244 | mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION); | 3412 | mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION); |
3245 | mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION); | 3413 | mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION); |
3246 | 3414 | ||
3247 | 3415 | if (_base_is_controller_msix_enabled(ioc)) | |
3416 | mpi_request.HostMSIxVectors = ioc->reply_queue_count; | ||
3248 | mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4); | 3417 | mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4); |
3249 | mpi_request.ReplyDescriptorPostQueueDepth = | 3418 | mpi_request.ReplyDescriptorPostQueueDepth = |
3250 | cpu_to_le16(ioc->reply_post_queue_depth); | 3419 | cpu_to_le16(ioc->reply_post_queue_depth); |
@@ -3303,6 +3472,58 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
3303 | } | 3472 | } |
3304 | 3473 | ||
3305 | /** | 3474 | /** |
3475 | * mpt2sas_port_enable_done - command completion routine for port enable | ||
3476 | * @ioc: per adapter object | ||
3477 | * @smid: system request message index | ||
3478 | * @msix_index: MSIX table index supplied by the OS | ||
3479 | * @reply: reply message frame(lower 32bit addr) | ||
3480 | * | ||
3481 | * Return 1 meaning mf should be freed from _base_interrupt | ||
3482 | * 0 means the mf is freed from this function. | ||
3483 | */ | ||
3484 | u8 | ||
3485 | mpt2sas_port_enable_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | ||
3486 | u32 reply) | ||
3487 | { | ||
3488 | MPI2DefaultReply_t *mpi_reply; | ||
3489 | u16 ioc_status; | ||
3490 | |||
3491 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
3492 | if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK) | ||
3493 | return 1; | ||
3494 | |||
3495 | if (ioc->port_enable_cmds.status == MPT2_CMD_NOT_USED) | ||
3496 | return 1; | ||
3497 | |||
3498 | ioc->port_enable_cmds.status |= MPT2_CMD_COMPLETE; | ||
3499 | if (mpi_reply) { | ||
3500 | ioc->port_enable_cmds.status |= MPT2_CMD_REPLY_VALID; | ||
3501 | memcpy(ioc->port_enable_cmds.reply, mpi_reply, | ||
3502 | mpi_reply->MsgLength*4); | ||
3503 | } | ||
3504 | ioc->port_enable_cmds.status &= ~MPT2_CMD_PENDING; | ||
3505 | |||
3506 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; | ||
3507 | |||
3508 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) | ||
3509 | ioc->port_enable_failed = 1; | ||
3510 | |||
3511 | if (ioc->is_driver_loading) { | ||
3512 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { | ||
3513 | mpt2sas_port_enable_complete(ioc); | ||
3514 | return 1; | ||
3515 | } else { | ||
3516 | ioc->start_scan_failed = ioc_status; | ||
3517 | ioc->start_scan = 0; | ||
3518 | return 1; | ||
3519 | } | ||
3520 | } | ||
3521 | complete(&ioc->port_enable_cmds.done); | ||
3522 | return 1; | ||
3523 | } | ||
3524 | |||
3525 | |||
3526 | /** | ||
3306 | * _base_send_port_enable - send port_enable(discovery stuff) to firmware | 3527 | * _base_send_port_enable - send port_enable(discovery stuff) to firmware |
3307 | * @ioc: per adapter object | 3528 | * @ioc: per adapter object |
3308 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | 3529 | * @sleep_flag: CAN_SLEEP or NO_SLEEP |
@@ -3313,67 +3534,151 @@ static int | |||
3313 | _base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | 3534 | _base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) |
3314 | { | 3535 | { |
3315 | Mpi2PortEnableRequest_t *mpi_request; | 3536 | Mpi2PortEnableRequest_t *mpi_request; |
3316 | u32 ioc_state; | 3537 | Mpi2PortEnableReply_t *mpi_reply; |
3317 | unsigned long timeleft; | 3538 | unsigned long timeleft; |
3318 | int r = 0; | 3539 | int r = 0; |
3319 | u16 smid; | 3540 | u16 smid; |
3541 | u16 ioc_status; | ||
3320 | 3542 | ||
3321 | printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name); | 3543 | printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name); |
3322 | 3544 | ||
3323 | if (ioc->base_cmds.status & MPT2_CMD_PENDING) { | 3545 | if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) { |
3324 | printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n", | 3546 | printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n", |
3325 | ioc->name, __func__); | 3547 | ioc->name, __func__); |
3326 | return -EAGAIN; | 3548 | return -EAGAIN; |
3327 | } | 3549 | } |
3328 | 3550 | ||
3329 | smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx); | 3551 | smid = mpt2sas_base_get_smid(ioc, ioc->port_enable_cb_idx); |
3330 | if (!smid) { | 3552 | if (!smid) { |
3331 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | 3553 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", |
3332 | ioc->name, __func__); | 3554 | ioc->name, __func__); |
3333 | return -EAGAIN; | 3555 | return -EAGAIN; |
3334 | } | 3556 | } |
3335 | 3557 | ||
3336 | ioc->base_cmds.status = MPT2_CMD_PENDING; | 3558 | ioc->port_enable_cmds.status = MPT2_CMD_PENDING; |
3337 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | 3559 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); |
3338 | ioc->base_cmds.smid = smid; | 3560 | ioc->port_enable_cmds.smid = smid; |
3339 | memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t)); | 3561 | memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t)); |
3340 | mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; | 3562 | mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; |
3341 | mpi_request->VF_ID = 0; /* TODO */ | ||
3342 | mpi_request->VP_ID = 0; | ||
3343 | 3563 | ||
3564 | init_completion(&ioc->port_enable_cmds.done); | ||
3344 | mpt2sas_base_put_smid_default(ioc, smid); | 3565 | mpt2sas_base_put_smid_default(ioc, smid); |
3345 | init_completion(&ioc->base_cmds.done); | 3566 | timeleft = wait_for_completion_timeout(&ioc->port_enable_cmds.done, |
3346 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, | ||
3347 | 300*HZ); | 3567 | 300*HZ); |
3348 | if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { | 3568 | if (!(ioc->port_enable_cmds.status & MPT2_CMD_COMPLETE)) { |
3349 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", | 3569 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", |
3350 | ioc->name, __func__); | 3570 | ioc->name, __func__); |
3351 | _debug_dump_mf(mpi_request, | 3571 | _debug_dump_mf(mpi_request, |
3352 | sizeof(Mpi2PortEnableRequest_t)/4); | 3572 | sizeof(Mpi2PortEnableRequest_t)/4); |
3353 | if (ioc->base_cmds.status & MPT2_CMD_RESET) | 3573 | if (ioc->port_enable_cmds.status & MPT2_CMD_RESET) |
3354 | r = -EFAULT; | 3574 | r = -EFAULT; |
3355 | else | 3575 | else |
3356 | r = -ETIME; | 3576 | r = -ETIME; |
3357 | goto out; | 3577 | goto out; |
3358 | } else | 3578 | } |
3359 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: complete\n", | 3579 | mpi_reply = ioc->port_enable_cmds.reply; |
3360 | ioc->name, __func__)); | ||
3361 | 3580 | ||
3362 | ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_OPERATIONAL, | 3581 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; |
3363 | 60, sleep_flag); | 3582 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { |
3364 | if (ioc_state) { | 3583 | printk(MPT2SAS_ERR_FMT "%s: failed with (ioc_status=0x%08x)\n", |
3365 | printk(MPT2SAS_ERR_FMT "%s: failed going to operational state " | 3584 | ioc->name, __func__, ioc_status); |
3366 | " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state); | ||
3367 | r = -EFAULT; | 3585 | r = -EFAULT; |
3586 | goto out; | ||
3368 | } | 3587 | } |
3369 | out: | 3588 | out: |
3370 | ioc->base_cmds.status = MPT2_CMD_NOT_USED; | 3589 | ioc->port_enable_cmds.status = MPT2_CMD_NOT_USED; |
3371 | printk(MPT2SAS_INFO_FMT "port enable: %s\n", | 3590 | printk(MPT2SAS_INFO_FMT "port enable: %s\n", ioc->name, ((r == 0) ? |
3372 | ioc->name, ((r == 0) ? "SUCCESS" : "FAILED")); | 3591 | "SUCCESS" : "FAILED")); |
3373 | return r; | 3592 | return r; |
3374 | } | 3593 | } |
3375 | 3594 | ||
3376 | /** | 3595 | /** |
3596 | * mpt2sas_port_enable - initiate firmware discovery (don't wait for reply) | ||
3597 | * @ioc: per adapter object | ||
3598 | * | ||
3599 | * Returns 0 for success, non-zero for failure. | ||
3600 | */ | ||
3601 | int | ||
3602 | mpt2sas_port_enable(struct MPT2SAS_ADAPTER *ioc) | ||
3603 | { | ||
3604 | Mpi2PortEnableRequest_t *mpi_request; | ||
3605 | u16 smid; | ||
3606 | |||
3607 | printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name); | ||
3608 | |||
3609 | if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) { | ||
3610 | printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n", | ||
3611 | ioc->name, __func__); | ||
3612 | return -EAGAIN; | ||
3613 | } | ||
3614 | |||
3615 | smid = mpt2sas_base_get_smid(ioc, ioc->port_enable_cb_idx); | ||
3616 | if (!smid) { | ||
3617 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
3618 | ioc->name, __func__); | ||
3619 | return -EAGAIN; | ||
3620 | } | ||
3621 | |||
3622 | ioc->port_enable_cmds.status = MPT2_CMD_PENDING; | ||
3623 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
3624 | ioc->port_enable_cmds.smid = smid; | ||
3625 | memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t)); | ||
3626 | mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; | ||
3627 | |||
3628 | mpt2sas_base_put_smid_default(ioc, smid); | ||
3629 | return 0; | ||
3630 | } | ||
3631 | |||
3632 | /** | ||
3633 | * _base_determine_wait_on_discovery - desposition | ||
3634 | * @ioc: per adapter object | ||
3635 | * | ||
3636 | * Decide whether to wait on discovery to complete. Used to either | ||
3637 | * locate boot device, or report volumes ahead of physical devices. | ||
3638 | * | ||
3639 | * Returns 1 for wait, 0 for don't wait | ||
3640 | */ | ||
3641 | static int | ||
3642 | _base_determine_wait_on_discovery(struct MPT2SAS_ADAPTER *ioc) | ||
3643 | { | ||
3644 | /* We wait for discovery to complete if IR firmware is loaded. | ||
3645 | * The sas topology events arrive before PD events, so we need time to | ||
3646 | * turn on the bit in ioc->pd_handles to indicate PD | ||
3647 | * Also, it maybe required to report Volumes ahead of physical | ||
3648 | * devices when MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING is set. | ||
3649 | */ | ||
3650 | if (ioc->ir_firmware) | ||
3651 | return 1; | ||
3652 | |||
3653 | /* if no Bios, then we don't need to wait */ | ||
3654 | if (!ioc->bios_pg3.BiosVersion) | ||
3655 | return 0; | ||
3656 | |||
3657 | /* Bios is present, then we drop down here. | ||
3658 | * | ||
3659 | * If there any entries in the Bios Page 2, then we wait | ||
3660 | * for discovery to complete. | ||
3661 | */ | ||
3662 | |||
3663 | /* Current Boot Device */ | ||
3664 | if ((ioc->bios_pg2.CurrentBootDeviceForm & | ||
3665 | MPI2_BIOSPAGE2_FORM_MASK) == | ||
3666 | MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED && | ||
3667 | /* Request Boot Device */ | ||
3668 | (ioc->bios_pg2.ReqBootDeviceForm & | ||
3669 | MPI2_BIOSPAGE2_FORM_MASK) == | ||
3670 | MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED && | ||
3671 | /* Alternate Request Boot Device */ | ||
3672 | (ioc->bios_pg2.ReqAltBootDeviceForm & | ||
3673 | MPI2_BIOSPAGE2_FORM_MASK) == | ||
3674 | MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED) | ||
3675 | return 0; | ||
3676 | |||
3677 | return 1; | ||
3678 | } | ||
3679 | |||
3680 | |||
3681 | /** | ||
3377 | * _base_unmask_events - turn on notification for this event | 3682 | * _base_unmask_events - turn on notification for this event |
3378 | * @ioc: per adapter object | 3683 | * @ioc: per adapter object |
3379 | * @event: firmware event | 3684 | * @event: firmware event |
@@ -3513,9 +3818,6 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
3513 | u32 hcb_size; | 3818 | u32 hcb_size; |
3514 | 3819 | ||
3515 | printk(MPT2SAS_INFO_FMT "sending diag reset !!\n", ioc->name); | 3820 | printk(MPT2SAS_INFO_FMT "sending diag reset !!\n", ioc->name); |
3516 | |||
3517 | _base_save_msix_table(ioc); | ||
3518 | |||
3519 | drsprintk(ioc, printk(MPT2SAS_INFO_FMT "clear interrupts\n", | 3821 | drsprintk(ioc, printk(MPT2SAS_INFO_FMT "clear interrupts\n", |
3520 | ioc->name)); | 3822 | ioc->name)); |
3521 | 3823 | ||
@@ -3611,7 +3913,6 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
3611 | goto out; | 3913 | goto out; |
3612 | } | 3914 | } |
3613 | 3915 | ||
3614 | _base_restore_msix_table(ioc); | ||
3615 | printk(MPT2SAS_INFO_FMT "diag reset: SUCCESS\n", ioc->name); | 3916 | printk(MPT2SAS_INFO_FMT "diag reset: SUCCESS\n", ioc->name); |
3616 | return 0; | 3917 | return 0; |
3617 | 3918 | ||
@@ -3692,6 +3993,9 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
3692 | u16 smid; | 3993 | u16 smid; |
3693 | struct _tr_list *delayed_tr, *delayed_tr_next; | 3994 | struct _tr_list *delayed_tr, *delayed_tr_next; |
3694 | u8 hide_flag; | 3995 | u8 hide_flag; |
3996 | struct adapter_reply_queue *reply_q; | ||
3997 | long reply_post_free; | ||
3998 | u32 reply_post_free_sz; | ||
3695 | 3999 | ||
3696 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | 4000 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, |
3697 | __func__)); | 4001 | __func__)); |
@@ -3757,21 +4061,46 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
3757 | ioc->reply_sz) | 4061 | ioc->reply_sz) |
3758 | ioc->reply_free[i] = cpu_to_le32(reply_address); | 4062 | ioc->reply_free[i] = cpu_to_le32(reply_address); |
3759 | 4063 | ||
4064 | /* initialize reply queues */ | ||
4065 | _base_assign_reply_queues(ioc); | ||
4066 | |||
3760 | /* initialize Reply Post Free Queue */ | 4067 | /* initialize Reply Post Free Queue */ |
3761 | for (i = 0; i < ioc->reply_post_queue_depth; i++) | 4068 | reply_post_free = (long)ioc->reply_post_free; |
3762 | ioc->reply_post_free[i].Words = cpu_to_le64(ULLONG_MAX); | 4069 | reply_post_free_sz = ioc->reply_post_queue_depth * |
4070 | sizeof(Mpi2DefaultReplyDescriptor_t); | ||
4071 | list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { | ||
4072 | reply_q->reply_post_host_index = 0; | ||
4073 | reply_q->reply_post_free = (Mpi2ReplyDescriptorsUnion_t *) | ||
4074 | reply_post_free; | ||
4075 | for (i = 0; i < ioc->reply_post_queue_depth; i++) | ||
4076 | reply_q->reply_post_free[i].Words = | ||
4077 | cpu_to_le64(ULLONG_MAX); | ||
4078 | if (!_base_is_controller_msix_enabled(ioc)) | ||
4079 | goto skip_init_reply_post_free_queue; | ||
4080 | reply_post_free += reply_post_free_sz; | ||
4081 | } | ||
4082 | skip_init_reply_post_free_queue: | ||
3763 | 4083 | ||
3764 | r = _base_send_ioc_init(ioc, sleep_flag); | 4084 | r = _base_send_ioc_init(ioc, sleep_flag); |
3765 | if (r) | 4085 | if (r) |
3766 | return r; | 4086 | return r; |
3767 | 4087 | ||
3768 | /* initialize the index's */ | 4088 | /* initialize reply free host index */ |
3769 | ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1; | 4089 | ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1; |
3770 | ioc->reply_post_host_index = 0; | ||
3771 | writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex); | 4090 | writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex); |
3772 | writel(0, &ioc->chip->ReplyPostHostIndex); | 4091 | |
4092 | /* initialize reply post host index */ | ||
4093 | list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { | ||
4094 | writel(reply_q->msix_index << MPI2_RPHI_MSIX_INDEX_SHIFT, | ||
4095 | &ioc->chip->ReplyPostHostIndex); | ||
4096 | if (!_base_is_controller_msix_enabled(ioc)) | ||
4097 | goto skip_init_reply_post_host_index; | ||
4098 | } | ||
4099 | |||
4100 | skip_init_reply_post_host_index: | ||
3773 | 4101 | ||
3774 | _base_unmask_interrupts(ioc); | 4102 | _base_unmask_interrupts(ioc); |
4103 | |||
3775 | r = _base_event_notification(ioc, sleep_flag); | 4104 | r = _base_event_notification(ioc, sleep_flag); |
3776 | if (r) | 4105 | if (r) |
3777 | return r; | 4106 | return r; |
@@ -3779,7 +4108,18 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
3779 | if (sleep_flag == CAN_SLEEP) | 4108 | if (sleep_flag == CAN_SLEEP) |
3780 | _base_static_config_pages(ioc); | 4109 | _base_static_config_pages(ioc); |
3781 | 4110 | ||
3782 | if (ioc->wait_for_port_enable_to_complete && ioc->is_warpdrive) { | 4111 | |
4112 | if (ioc->is_driver_loading) { | ||
4113 | |||
4114 | |||
4115 | |||
4116 | ioc->wait_for_discovery_to_complete = | ||
4117 | _base_determine_wait_on_discovery(ioc); | ||
4118 | return r; /* scan_start and scan_finished support */ | ||
4119 | } | ||
4120 | |||
4121 | |||
4122 | if (ioc->wait_for_discovery_to_complete && ioc->is_warpdrive) { | ||
3783 | if (ioc->manu_pg10.OEMIdentifier == 0x80) { | 4123 | if (ioc->manu_pg10.OEMIdentifier == 0x80) { |
3784 | hide_flag = (u8) (ioc->manu_pg10.OEMSpecificFlags0 & | 4124 | hide_flag = (u8) (ioc->manu_pg10.OEMSpecificFlags0 & |
3785 | MFG_PAGE10_HIDE_SSDS_MASK); | 4125 | MFG_PAGE10_HIDE_SSDS_MASK); |
@@ -3788,13 +4128,6 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
3788 | } | 4128 | } |
3789 | } | 4129 | } |
3790 | 4130 | ||
3791 | if (ioc->wait_for_port_enable_to_complete) { | ||
3792 | if (diag_buffer_enable != 0) | ||
3793 | mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable); | ||
3794 | if (disable_discovery > 0) | ||
3795 | return r; | ||
3796 | } | ||
3797 | |||
3798 | r = _base_send_port_enable(ioc, sleep_flag); | 4131 | r = _base_send_port_enable(ioc, sleep_flag); |
3799 | if (r) | 4132 | if (r) |
3800 | return r; | 4133 | return r; |
@@ -3820,14 +4153,10 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc) | |||
3820 | ioc->shost_recovery = 1; | 4153 | ioc->shost_recovery = 1; |
3821 | _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); | 4154 | _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); |
3822 | ioc->shost_recovery = 0; | 4155 | ioc->shost_recovery = 0; |
3823 | if (ioc->pci_irq) { | 4156 | _base_free_irq(ioc); |
3824 | synchronize_irq(pdev->irq); | ||
3825 | free_irq(ioc->pci_irq, ioc); | ||
3826 | } | ||
3827 | _base_disable_msix(ioc); | 4157 | _base_disable_msix(ioc); |
3828 | if (ioc->chip_phys) | 4158 | if (ioc->chip_phys) |
3829 | iounmap(ioc->chip); | 4159 | iounmap(ioc->chip); |
3830 | ioc->pci_irq = -1; | ||
3831 | ioc->chip_phys = 0; | 4160 | ioc->chip_phys = 0; |
3832 | pci_release_selected_regions(ioc->pdev, ioc->bars); | 4161 | pci_release_selected_regions(ioc->pdev, ioc->bars); |
3833 | pci_disable_pcie_error_reporting(pdev); | 4162 | pci_disable_pcie_error_reporting(pdev); |
@@ -3845,14 +4174,50 @@ int | |||
3845 | mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | 4174 | mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) |
3846 | { | 4175 | { |
3847 | int r, i; | 4176 | int r, i; |
4177 | int cpu_id, last_cpu_id = 0; | ||
3848 | 4178 | ||
3849 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | 4179 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, |
3850 | __func__)); | 4180 | __func__)); |
3851 | 4181 | ||
4182 | /* setup cpu_msix_table */ | ||
4183 | ioc->cpu_count = num_online_cpus(); | ||
4184 | for_each_online_cpu(cpu_id) | ||
4185 | last_cpu_id = cpu_id; | ||
4186 | ioc->cpu_msix_table_sz = last_cpu_id + 1; | ||
4187 | ioc->cpu_msix_table = kzalloc(ioc->cpu_msix_table_sz, GFP_KERNEL); | ||
4188 | ioc->reply_queue_count = 1; | ||
4189 | if (!ioc->cpu_msix_table) { | ||
4190 | dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation for " | ||
4191 | "cpu_msix_table failed!!!\n", ioc->name)); | ||
4192 | r = -ENOMEM; | ||
4193 | goto out_free_resources; | ||
4194 | } | ||
4195 | |||
4196 | if (ioc->is_warpdrive) { | ||
4197 | ioc->reply_post_host_index = kcalloc(ioc->cpu_msix_table_sz, | ||
4198 | sizeof(resource_size_t *), GFP_KERNEL); | ||
4199 | if (!ioc->reply_post_host_index) { | ||
4200 | dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation " | ||
4201 | "for cpu_msix_table failed!!!\n", ioc->name)); | ||
4202 | r = -ENOMEM; | ||
4203 | goto out_free_resources; | ||
4204 | } | ||
4205 | } | ||
4206 | |||
3852 | r = mpt2sas_base_map_resources(ioc); | 4207 | r = mpt2sas_base_map_resources(ioc); |
3853 | if (r) | 4208 | if (r) |
3854 | return r; | 4209 | return r; |
3855 | 4210 | ||
4211 | if (ioc->is_warpdrive) { | ||
4212 | ioc->reply_post_host_index[0] = | ||
4213 | (resource_size_t *)&ioc->chip->ReplyPostHostIndex; | ||
4214 | |||
4215 | for (i = 1; i < ioc->cpu_msix_table_sz; i++) | ||
4216 | ioc->reply_post_host_index[i] = (resource_size_t *) | ||
4217 | ((u8 *)&ioc->chip->Doorbell + (0x4000 + ((i - 1) | ||
4218 | * 4))); | ||
4219 | } | ||
4220 | |||
3856 | pci_set_drvdata(ioc->pdev, ioc->shost); | 4221 | pci_set_drvdata(ioc->pdev, ioc->shost); |
3857 | r = _base_get_ioc_facts(ioc, CAN_SLEEP); | 4222 | r = _base_get_ioc_facts(ioc, CAN_SLEEP); |
3858 | if (r) | 4223 | if (r) |
@@ -3899,6 +4264,10 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3899 | ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | 4264 | ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); |
3900 | ioc->base_cmds.status = MPT2_CMD_NOT_USED; | 4265 | ioc->base_cmds.status = MPT2_CMD_NOT_USED; |
3901 | 4266 | ||
4267 | /* port_enable command bits */ | ||
4268 | ioc->port_enable_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | ||
4269 | ioc->port_enable_cmds.status = MPT2_CMD_NOT_USED; | ||
4270 | |||
3902 | /* transport internal command bits */ | 4271 | /* transport internal command bits */ |
3903 | ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | 4272 | ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); |
3904 | ioc->transport_cmds.status = MPT2_CMD_NOT_USED; | 4273 | ioc->transport_cmds.status = MPT2_CMD_NOT_USED; |
@@ -3940,8 +4309,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3940 | goto out_free_resources; | 4309 | goto out_free_resources; |
3941 | } | 4310 | } |
3942 | 4311 | ||
3943 | init_completion(&ioc->shost_recovery_done); | ||
3944 | |||
3945 | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) | 4312 | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) |
3946 | ioc->event_masks[i] = -1; | 4313 | ioc->event_masks[i] = -1; |
3947 | 4314 | ||
@@ -3964,7 +4331,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3964 | _base_update_missing_delay(ioc, missing_delay[0], | 4331 | _base_update_missing_delay(ioc, missing_delay[0], |
3965 | missing_delay[1]); | 4332 | missing_delay[1]); |
3966 | 4333 | ||
3967 | mpt2sas_base_start_watchdog(ioc); | ||
3968 | return 0; | 4334 | return 0; |
3969 | 4335 | ||
3970 | out_free_resources: | 4336 | out_free_resources: |
@@ -3973,12 +4339,16 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3973 | mpt2sas_base_free_resources(ioc); | 4339 | mpt2sas_base_free_resources(ioc); |
3974 | _base_release_memory_pools(ioc); | 4340 | _base_release_memory_pools(ioc); |
3975 | pci_set_drvdata(ioc->pdev, NULL); | 4341 | pci_set_drvdata(ioc->pdev, NULL); |
4342 | kfree(ioc->cpu_msix_table); | ||
4343 | if (ioc->is_warpdrive) | ||
4344 | kfree(ioc->reply_post_host_index); | ||
3976 | kfree(ioc->pd_handles); | 4345 | kfree(ioc->pd_handles); |
3977 | kfree(ioc->tm_cmds.reply); | 4346 | kfree(ioc->tm_cmds.reply); |
3978 | kfree(ioc->transport_cmds.reply); | 4347 | kfree(ioc->transport_cmds.reply); |
3979 | kfree(ioc->scsih_cmds.reply); | 4348 | kfree(ioc->scsih_cmds.reply); |
3980 | kfree(ioc->config_cmds.reply); | 4349 | kfree(ioc->config_cmds.reply); |
3981 | kfree(ioc->base_cmds.reply); | 4350 | kfree(ioc->base_cmds.reply); |
4351 | kfree(ioc->port_enable_cmds.reply); | ||
3982 | kfree(ioc->ctl_cmds.reply); | 4352 | kfree(ioc->ctl_cmds.reply); |
3983 | kfree(ioc->ctl_cmds.sense); | 4353 | kfree(ioc->ctl_cmds.sense); |
3984 | kfree(ioc->pfacts); | 4354 | kfree(ioc->pfacts); |
@@ -4010,11 +4380,15 @@ mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) | |||
4010 | mpt2sas_base_free_resources(ioc); | 4380 | mpt2sas_base_free_resources(ioc); |
4011 | _base_release_memory_pools(ioc); | 4381 | _base_release_memory_pools(ioc); |
4012 | pci_set_drvdata(ioc->pdev, NULL); | 4382 | pci_set_drvdata(ioc->pdev, NULL); |
4383 | kfree(ioc->cpu_msix_table); | ||
4384 | if (ioc->is_warpdrive) | ||
4385 | kfree(ioc->reply_post_host_index); | ||
4013 | kfree(ioc->pd_handles); | 4386 | kfree(ioc->pd_handles); |
4014 | kfree(ioc->pfacts); | 4387 | kfree(ioc->pfacts); |
4015 | kfree(ioc->ctl_cmds.reply); | 4388 | kfree(ioc->ctl_cmds.reply); |
4016 | kfree(ioc->ctl_cmds.sense); | 4389 | kfree(ioc->ctl_cmds.sense); |
4017 | kfree(ioc->base_cmds.reply); | 4390 | kfree(ioc->base_cmds.reply); |
4391 | kfree(ioc->port_enable_cmds.reply); | ||
4018 | kfree(ioc->tm_cmds.reply); | 4392 | kfree(ioc->tm_cmds.reply); |
4019 | kfree(ioc->transport_cmds.reply); | 4393 | kfree(ioc->transport_cmds.reply); |
4020 | kfree(ioc->scsih_cmds.reply); | 4394 | kfree(ioc->scsih_cmds.reply); |
@@ -4056,6 +4430,20 @@ _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) | |||
4056 | mpt2sas_base_free_smid(ioc, ioc->base_cmds.smid); | 4430 | mpt2sas_base_free_smid(ioc, ioc->base_cmds.smid); |
4057 | complete(&ioc->base_cmds.done); | 4431 | complete(&ioc->base_cmds.done); |
4058 | } | 4432 | } |
4433 | if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) { | ||
4434 | ioc->port_enable_failed = 1; | ||
4435 | ioc->port_enable_cmds.status |= MPT2_CMD_RESET; | ||
4436 | mpt2sas_base_free_smid(ioc, ioc->port_enable_cmds.smid); | ||
4437 | if (ioc->is_driver_loading) { | ||
4438 | ioc->start_scan_failed = | ||
4439 | MPI2_IOCSTATUS_INTERNAL_ERROR; | ||
4440 | ioc->start_scan = 0; | ||
4441 | ioc->port_enable_cmds.status = | ||
4442 | MPT2_CMD_NOT_USED; | ||
4443 | } else | ||
4444 | complete(&ioc->port_enable_cmds.done); | ||
4445 | |||
4446 | } | ||
4059 | if (ioc->config_cmds.status & MPT2_CMD_PENDING) { | 4447 | if (ioc->config_cmds.status & MPT2_CMD_PENDING) { |
4060 | ioc->config_cmds.status |= MPT2_CMD_RESET; | 4448 | ioc->config_cmds.status |= MPT2_CMD_RESET; |
4061 | mpt2sas_base_free_smid(ioc, ioc->config_cmds.smid); | 4449 | mpt2sas_base_free_smid(ioc, ioc->config_cmds.smid); |
@@ -4121,7 +4509,6 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, | |||
4121 | { | 4509 | { |
4122 | int r; | 4510 | int r; |
4123 | unsigned long flags; | 4511 | unsigned long flags; |
4124 | u8 pe_complete = ioc->wait_for_port_enable_to_complete; | ||
4125 | 4512 | ||
4126 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, | 4513 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, |
4127 | __func__)); | 4514 | __func__)); |
@@ -4168,7 +4555,8 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, | |||
4168 | /* If this hard reset is called while port enable is active, then | 4555 | /* If this hard reset is called while port enable is active, then |
4169 | * there is no reason to call make_ioc_operational | 4556 | * there is no reason to call make_ioc_operational |
4170 | */ | 4557 | */ |
4171 | if (pe_complete) { | 4558 | if (ioc->is_driver_loading && ioc->port_enable_failed) { |
4559 | ioc->remove_host = 1; | ||
4172 | r = -EFAULT; | 4560 | r = -EFAULT; |
4173 | goto out; | 4561 | goto out; |
4174 | } | 4562 | } |
@@ -4182,7 +4570,6 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, | |||
4182 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | 4570 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); |
4183 | ioc->ioc_reset_in_progress_status = r; | 4571 | ioc->ioc_reset_in_progress_status = r; |
4184 | ioc->shost_recovery = 0; | 4572 | ioc->shost_recovery = 0; |
4185 | complete(&ioc->shost_recovery_done); | ||
4186 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | 4573 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); |
4187 | mutex_unlock(&ioc->reset_in_progress_mutex); | 4574 | mutex_unlock(&ioc->reset_in_progress_mutex); |
4188 | 4575 | ||