diff options
author | Jayamohan Kallickal <jayamohank@gmail.com> | 2013-09-28 18:35:58 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-10-25 04:58:10 -0400 |
commit | 3567f36a09d1095bb0fb97aa686f7eabc64b45d9 (patch) | |
tree | f67c0e92196d24b3928c9de02fdd7075594136d3 /drivers/scsi/be2iscsi | |
parent | 7626c06b1b4d2fe0b71a6d3ceb14e68ab02a75a6 (diff) |
[SCSI] be2iscsi: Fix AER handling in driver
Signed-off-by: Minh Tran <minhduc.tran@emulex.com>
Signed-off-by: John Soni Jose <sony.john-n@emulex.com>
Signed-off-by: Jayamohan Kallickal <jayamohan.kallickal@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/be2iscsi')
-rw-r--r-- | drivers/scsi/be2iscsi/be_cmds.c | 2 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_iscsi.c | 68 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.c | 220 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.h | 9 |
4 files changed, 270 insertions, 29 deletions
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index fce298ba4b41..3338391b64de 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c | |||
@@ -377,7 +377,7 @@ void beiscsi_async_link_state_process(struct beiscsi_hba *phba, | |||
377 | } else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) || | 377 | } else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) || |
378 | ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && | 378 | ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && |
379 | (evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) { | 379 | (evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) { |
380 | phba->state = BE_ADAPTER_UP; | 380 | phba->state = BE_ADAPTER_LINK_UP; |
381 | 381 | ||
382 | beiscsi_log(phba, KERN_ERR, | 382 | beiscsi_log(phba, KERN_ERR, |
383 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, | 383 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, |
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index e82ab8124958..ffadbee0b4d9 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c | |||
@@ -58,10 +58,15 @@ struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep, | |||
58 | } | 58 | } |
59 | beiscsi_ep = ep->dd_data; | 59 | beiscsi_ep = ep->dd_data; |
60 | phba = beiscsi_ep->phba; | 60 | phba = beiscsi_ep->phba; |
61 | shost = phba->shost; | ||
62 | 61 | ||
63 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | 62 | if (phba->state & BE_ADAPTER_PCI_ERR) { |
64 | "BS_%d : In beiscsi_session_create\n"); | 63 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, |
64 | "BS_%d : PCI_ERROR Recovery\n"); | ||
65 | return NULL; | ||
66 | } else { | ||
67 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | ||
68 | "BS_%d : In beiscsi_session_create\n"); | ||
69 | } | ||
65 | 70 | ||
66 | if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) { | 71 | if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) { |
67 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | 72 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, |
@@ -74,6 +79,7 @@ struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep, | |||
74 | cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn; | 79 | cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn; |
75 | } | 80 | } |
76 | 81 | ||
82 | shost = phba->shost; | ||
77 | cls_session = iscsi_session_setup(&beiscsi_iscsi_transport, | 83 | cls_session = iscsi_session_setup(&beiscsi_iscsi_transport, |
78 | shost, cmds_max, | 84 | shost, cmds_max, |
79 | sizeof(*beiscsi_sess), | 85 | sizeof(*beiscsi_sess), |
@@ -477,6 +483,12 @@ int be2iscsi_iface_set_param(struct Scsi_Host *shost, | |||
477 | uint32_t rm_len = dt_len; | 483 | uint32_t rm_len = dt_len; |
478 | int ret = 0 ; | 484 | int ret = 0 ; |
479 | 485 | ||
486 | if (phba->state & BE_ADAPTER_PCI_ERR) { | ||
487 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
488 | "BS_%d : In PCI_ERROR Recovery\n"); | ||
489 | return -EBUSY; | ||
490 | } | ||
491 | |||
480 | nla_for_each_attr(attrib, data, dt_len, rm_len) { | 492 | nla_for_each_attr(attrib, data, dt_len, rm_len) { |
481 | iface_param = nla_data(attrib); | 493 | iface_param = nla_data(attrib); |
482 | 494 | ||
@@ -588,6 +600,12 @@ int be2iscsi_iface_get_param(struct iscsi_iface *iface, | |||
588 | struct be_cmd_get_def_gateway_resp gateway; | 600 | struct be_cmd_get_def_gateway_resp gateway; |
589 | int len = -ENOSYS; | 601 | int len = -ENOSYS; |
590 | 602 | ||
603 | if (phba->state & BE_ADAPTER_PCI_ERR) { | ||
604 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
605 | "BS_%d : In PCI_ERROR Recovery\n"); | ||
606 | return -EBUSY; | ||
607 | } | ||
608 | |||
591 | switch (param) { | 609 | switch (param) { |
592 | case ISCSI_NET_PARAM_IPV4_ADDR: | 610 | case ISCSI_NET_PARAM_IPV4_ADDR: |
593 | case ISCSI_NET_PARAM_IPV4_SUBNET: | 611 | case ISCSI_NET_PARAM_IPV4_SUBNET: |
@@ -737,7 +755,7 @@ static void beiscsi_get_port_state(struct Scsi_Host *shost) | |||
737 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | 755 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
738 | struct iscsi_cls_host *ihost = shost->shost_data; | 756 | struct iscsi_cls_host *ihost = shost->shost_data; |
739 | 757 | ||
740 | ihost->port_state = (phba->state == BE_ADAPTER_UP) ? | 758 | ihost->port_state = (phba->state == BE_ADAPTER_LINK_UP) ? |
741 | ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN; | 759 | ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN; |
742 | } | 760 | } |
743 | 761 | ||
@@ -805,9 +823,16 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, | |||
805 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | 823 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
806 | int status = 0; | 824 | int status = 0; |
807 | 825 | ||
808 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | 826 | |
809 | "BS_%d : In beiscsi_get_host_param," | 827 | if (phba->state & BE_ADAPTER_PCI_ERR) { |
810 | " param= %d\n", param); | 828 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, |
829 | "BS_%d : In PCI_ERROR Recovery\n"); | ||
830 | return -EBUSY; | ||
831 | } else { | ||
832 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | ||
833 | "BS_%d : In beiscsi_get_host_param," | ||
834 | " param = %d\n", param); | ||
835 | } | ||
811 | 836 | ||
812 | switch (param) { | 837 | switch (param) { |
813 | case ISCSI_HOST_PARAM_HWADDRESS: | 838 | case ISCSI_HOST_PARAM_HWADDRESS: |
@@ -950,10 +975,19 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn) | |||
950 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | 975 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; |
951 | struct beiscsi_endpoint *beiscsi_ep; | 976 | struct beiscsi_endpoint *beiscsi_ep; |
952 | struct beiscsi_offload_params params; | 977 | struct beiscsi_offload_params params; |
978 | struct beiscsi_hba *phba; | ||
953 | 979 | ||
954 | beiscsi_log(beiscsi_conn->phba, KERN_INFO, | 980 | phba = ((struct beiscsi_conn *)conn->dd_data)->phba; |
955 | BEISCSI_LOG_CONFIG, | 981 | |
956 | "BS_%d : In beiscsi_conn_start\n"); | 982 | if (phba->state & BE_ADAPTER_PCI_ERR) { |
983 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
984 | "BS_%d : In PCI_ERROR Recovery\n"); | ||
985 | return -EBUSY; | ||
986 | } else { | ||
987 | beiscsi_log(beiscsi_conn->phba, KERN_INFO, | ||
988 | BEISCSI_LOG_CONFIG, | ||
989 | "BS_%d : In beiscsi_conn_start\n"); | ||
990 | } | ||
957 | 991 | ||
958 | memset(¶ms, 0, sizeof(struct beiscsi_offload_params)); | 992 | memset(¶ms, 0, sizeof(struct beiscsi_offload_params)); |
959 | beiscsi_ep = beiscsi_conn->ep; | 993 | beiscsi_ep = beiscsi_conn->ep; |
@@ -1178,7 +1212,12 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, | |||
1178 | return ERR_PTR(ret); | 1212 | return ERR_PTR(ret); |
1179 | } | 1213 | } |
1180 | 1214 | ||
1181 | if (phba->state != BE_ADAPTER_UP) { | 1215 | if (phba->state & BE_ADAPTER_PCI_ERR) { |
1216 | ret = -EBUSY; | ||
1217 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
1218 | "BS_%d : In PCI_ERROR Recovery\n"); | ||
1219 | return ERR_PTR(ret); | ||
1220 | } else if (phba->state & BE_ADAPTER_LINK_DOWN) { | ||
1182 | ret = -EBUSY; | 1221 | ret = -EBUSY; |
1183 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | 1222 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, |
1184 | "BS_%d : The Adapter Port state is Down!!!\n"); | 1223 | "BS_%d : The Adapter Port state is Down!!!\n"); |
@@ -1303,6 +1342,12 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) | |||
1303 | tcp_upload_flag = CONNECTION_UPLOAD_ABORT; | 1342 | tcp_upload_flag = CONNECTION_UPLOAD_ABORT; |
1304 | } | 1343 | } |
1305 | 1344 | ||
1345 | if (phba->state & BE_ADAPTER_PCI_ERR) { | ||
1346 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
1347 | "BS_%d : PCI_ERROR Recovery\n"); | ||
1348 | goto free_ep; | ||
1349 | } | ||
1350 | |||
1306 | tag = mgmt_invalidate_connection(phba, beiscsi_ep, | 1351 | tag = mgmt_invalidate_connection(phba, beiscsi_ep, |
1307 | beiscsi_ep->ep_cid, | 1352 | beiscsi_ep->ep_cid, |
1308 | mgmt_invalidate_flag, | 1353 | mgmt_invalidate_flag, |
@@ -1315,6 +1360,7 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) | |||
1315 | 1360 | ||
1316 | beiscsi_mccq_compl(phba, tag, NULL, NULL); | 1361 | beiscsi_mccq_compl(phba, tag, NULL, NULL); |
1317 | beiscsi_close_conn(beiscsi_ep, tcp_upload_flag); | 1362 | beiscsi_close_conn(beiscsi_ep, tcp_upload_flag); |
1363 | free_ep: | ||
1318 | beiscsi_free_ep(beiscsi_ep); | 1364 | beiscsi_free_ep(beiscsi_ep); |
1319 | beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid); | 1365 | beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid); |
1320 | iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); | 1366 | iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); |
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 8f300534fc32..d84ecc5317ff 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c | |||
@@ -5140,10 +5140,12 @@ void beiscsi_hba_attrs_init(struct beiscsi_hba *phba) | |||
5140 | /* | 5140 | /* |
5141 | * beiscsi_quiesce()- Cleanup Driver resources | 5141 | * beiscsi_quiesce()- Cleanup Driver resources |
5142 | * @phba: Instance Priv structure | 5142 | * @phba: Instance Priv structure |
5143 | * @unload_state:i Clean or EEH unload state | ||
5143 | * | 5144 | * |
5144 | * Free the OS and HW resources held by the driver | 5145 | * Free the OS and HW resources held by the driver |
5145 | **/ | 5146 | **/ |
5146 | static void beiscsi_quiesce(struct beiscsi_hba *phba) | 5147 | static void beiscsi_quiesce(struct beiscsi_hba *phba, |
5148 | uint32_t unload_state) | ||
5147 | { | 5149 | { |
5148 | struct hwi_controller *phwi_ctrlr; | 5150 | struct hwi_controller *phwi_ctrlr; |
5149 | struct hwi_context_memory *phwi_context; | 5151 | struct hwi_context_memory *phwi_context; |
@@ -5156,28 +5158,37 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba) | |||
5156 | if (phba->msix_enabled) { | 5158 | if (phba->msix_enabled) { |
5157 | for (i = 0; i <= phba->num_cpus; i++) { | 5159 | for (i = 0; i <= phba->num_cpus; i++) { |
5158 | msix_vec = phba->msix_entries[i].vector; | 5160 | msix_vec = phba->msix_entries[i].vector; |
5161 | synchronize_irq(msix_vec); | ||
5159 | free_irq(msix_vec, &phwi_context->be_eq[i]); | 5162 | free_irq(msix_vec, &phwi_context->be_eq[i]); |
5160 | kfree(phba->msi_name[i]); | 5163 | kfree(phba->msi_name[i]); |
5161 | } | 5164 | } |
5162 | } else | 5165 | } else |
5163 | if (phba->pcidev->irq) | 5166 | if (phba->pcidev->irq) { |
5167 | synchronize_irq(phba->pcidev->irq); | ||
5164 | free_irq(phba->pcidev->irq, phba); | 5168 | free_irq(phba->pcidev->irq, phba); |
5169 | } | ||
5165 | pci_disable_msix(phba->pcidev); | 5170 | pci_disable_msix(phba->pcidev); |
5166 | destroy_workqueue(phba->wq); | 5171 | |
5167 | if (blk_iopoll_enabled) | 5172 | if (blk_iopoll_enabled) |
5168 | for (i = 0; i < phba->num_cpus; i++) { | 5173 | for (i = 0; i < phba->num_cpus; i++) { |
5169 | pbe_eq = &phwi_context->be_eq[i]; | 5174 | pbe_eq = &phwi_context->be_eq[i]; |
5170 | blk_iopoll_disable(&pbe_eq->iopoll); | 5175 | blk_iopoll_disable(&pbe_eq->iopoll); |
5171 | } | 5176 | } |
5172 | 5177 | ||
5173 | beiscsi_clean_port(phba); | 5178 | if (unload_state == BEISCSI_CLEAN_UNLOAD) { |
5174 | beiscsi_free_mem(phba); | 5179 | destroy_workqueue(phba->wq); |
5180 | beiscsi_clean_port(phba); | ||
5181 | beiscsi_free_mem(phba); | ||
5175 | 5182 | ||
5176 | beiscsi_unmap_pci_function(phba); | 5183 | beiscsi_unmap_pci_function(phba); |
5177 | pci_free_consistent(phba->pcidev, | 5184 | pci_free_consistent(phba->pcidev, |
5178 | phba->ctrl.mbox_mem_alloced.size, | 5185 | phba->ctrl.mbox_mem_alloced.size, |
5179 | phba->ctrl.mbox_mem_alloced.va, | 5186 | phba->ctrl.mbox_mem_alloced.va, |
5180 | phba->ctrl.mbox_mem_alloced.dma); | 5187 | phba->ctrl.mbox_mem_alloced.dma); |
5188 | } else { | ||
5189 | hwi_purge_eq(phba); | ||
5190 | hwi_cleanup(phba); | ||
5191 | } | ||
5181 | 5192 | ||
5182 | cancel_delayed_work_sync(&phba->beiscsi_hw_check_task); | 5193 | cancel_delayed_work_sync(&phba->beiscsi_hw_check_task); |
5183 | } | 5194 | } |
@@ -5194,11 +5205,13 @@ static void beiscsi_remove(struct pci_dev *pcidev) | |||
5194 | } | 5205 | } |
5195 | 5206 | ||
5196 | beiscsi_destroy_def_ifaces(phba); | 5207 | beiscsi_destroy_def_ifaces(phba); |
5197 | beiscsi_quiesce(phba); | 5208 | beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); |
5198 | iscsi_boot_destroy_kset(phba->boot_kset); | 5209 | iscsi_boot_destroy_kset(phba->boot_kset); |
5199 | iscsi_host_remove(phba->shost); | 5210 | iscsi_host_remove(phba->shost); |
5200 | pci_dev_put(phba->pcidev); | 5211 | pci_dev_put(phba->pcidev); |
5201 | iscsi_host_free(phba->shost); | 5212 | iscsi_host_free(phba->shost); |
5213 | pci_disable_pcie_error_reporting(pcidev); | ||
5214 | pci_set_drvdata(pcidev, NULL); | ||
5202 | pci_disable_device(pcidev); | 5215 | pci_disable_device(pcidev); |
5203 | } | 5216 | } |
5204 | 5217 | ||
@@ -5213,7 +5226,7 @@ static void beiscsi_shutdown(struct pci_dev *pcidev) | |||
5213 | return; | 5226 | return; |
5214 | } | 5227 | } |
5215 | 5228 | ||
5216 | beiscsi_quiesce(phba); | 5229 | beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); |
5217 | pci_disable_device(pcidev); | 5230 | pci_disable_device(pcidev); |
5218 | } | 5231 | } |
5219 | 5232 | ||
@@ -5251,6 +5264,167 @@ beiscsi_hw_health_check(struct work_struct *work) | |||
5251 | msecs_to_jiffies(1000)); | 5264 | msecs_to_jiffies(1000)); |
5252 | } | 5265 | } |
5253 | 5266 | ||
5267 | |||
5268 | static pci_ers_result_t beiscsi_eeh_err_detected(struct pci_dev *pdev, | ||
5269 | pci_channel_state_t state) | ||
5270 | { | ||
5271 | struct beiscsi_hba *phba = NULL; | ||
5272 | |||
5273 | phba = (struct beiscsi_hba *)pci_get_drvdata(pdev); | ||
5274 | phba->state |= BE_ADAPTER_PCI_ERR; | ||
5275 | |||
5276 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
5277 | "BM_%d : EEH error detected\n"); | ||
5278 | |||
5279 | beiscsi_quiesce(phba, BEISCSI_EEH_UNLOAD); | ||
5280 | |||
5281 | if (state == pci_channel_io_perm_failure) { | ||
5282 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
5283 | "BM_%d : EEH : State PERM Failure"); | ||
5284 | return PCI_ERS_RESULT_DISCONNECT; | ||
5285 | } | ||
5286 | |||
5287 | pci_disable_device(pdev); | ||
5288 | |||
5289 | /* The error could cause the FW to trigger a flash debug dump. | ||
5290 | * Resetting the card while flash dump is in progress | ||
5291 | * can cause it not to recover; wait for it to finish. | ||
5292 | * Wait only for first function as it is needed only once per | ||
5293 | * adapter. | ||
5294 | **/ | ||
5295 | if (pdev->devfn == 0) | ||
5296 | ssleep(30); | ||
5297 | |||
5298 | return PCI_ERS_RESULT_NEED_RESET; | ||
5299 | } | ||
5300 | |||
5301 | static pci_ers_result_t beiscsi_eeh_reset(struct pci_dev *pdev) | ||
5302 | { | ||
5303 | struct beiscsi_hba *phba = NULL; | ||
5304 | int status = 0; | ||
5305 | |||
5306 | phba = (struct beiscsi_hba *)pci_get_drvdata(pdev); | ||
5307 | |||
5308 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
5309 | "BM_%d : EEH Reset\n"); | ||
5310 | |||
5311 | status = pci_enable_device(pdev); | ||
5312 | if (status) | ||
5313 | return PCI_ERS_RESULT_DISCONNECT; | ||
5314 | |||
5315 | pci_set_master(pdev); | ||
5316 | pci_set_power_state(pdev, PCI_D0); | ||
5317 | pci_restore_state(pdev); | ||
5318 | |||
5319 | /* Wait for the CHIP Reset to complete */ | ||
5320 | status = be_chk_reset_complete(phba); | ||
5321 | if (!status) { | ||
5322 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, | ||
5323 | "BM_%d : EEH Reset Completed\n"); | ||
5324 | } else { | ||
5325 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, | ||
5326 | "BM_%d : EEH Reset Completion Failure\n"); | ||
5327 | return PCI_ERS_RESULT_DISCONNECT; | ||
5328 | } | ||
5329 | |||
5330 | pci_cleanup_aer_uncorrect_error_status(pdev); | ||
5331 | return PCI_ERS_RESULT_RECOVERED; | ||
5332 | } | ||
5333 | |||
5334 | static void beiscsi_eeh_resume(struct pci_dev *pdev) | ||
5335 | { | ||
5336 | int ret = 0, i; | ||
5337 | struct be_eq_obj *pbe_eq; | ||
5338 | struct beiscsi_hba *phba = NULL; | ||
5339 | struct hwi_controller *phwi_ctrlr; | ||
5340 | struct hwi_context_memory *phwi_context; | ||
5341 | |||
5342 | phba = (struct beiscsi_hba *)pci_get_drvdata(pdev); | ||
5343 | pci_save_state(pdev); | ||
5344 | |||
5345 | if (enable_msix) | ||
5346 | find_num_cpus(phba); | ||
5347 | else | ||
5348 | phba->num_cpus = 1; | ||
5349 | |||
5350 | if (enable_msix) { | ||
5351 | beiscsi_msix_enable(phba); | ||
5352 | if (!phba->msix_enabled) | ||
5353 | phba->num_cpus = 1; | ||
5354 | } | ||
5355 | |||
5356 | ret = beiscsi_cmd_reset_function(phba); | ||
5357 | if (ret) { | ||
5358 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
5359 | "BM_%d : Reset Failed\n"); | ||
5360 | goto ret_err; | ||
5361 | } | ||
5362 | |||
5363 | ret = be_chk_reset_complete(phba); | ||
5364 | if (ret) { | ||
5365 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
5366 | "BM_%d : Failed to get out of reset.\n"); | ||
5367 | goto ret_err; | ||
5368 | } | ||
5369 | |||
5370 | beiscsi_get_params(phba); | ||
5371 | phba->shost->max_id = phba->params.cxns_per_ctrl; | ||
5372 | phba->shost->can_queue = phba->params.ios_per_ctrl; | ||
5373 | ret = hwi_init_controller(phba); | ||
5374 | |||
5375 | for (i = 0; i < MAX_MCC_CMD; i++) { | ||
5376 | init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]); | ||
5377 | phba->ctrl.mcc_tag[i] = i + 1; | ||
5378 | phba->ctrl.mcc_numtag[i + 1] = 0; | ||
5379 | phba->ctrl.mcc_tag_available++; | ||
5380 | } | ||
5381 | |||
5382 | phwi_ctrlr = phba->phwi_ctrlr; | ||
5383 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
5384 | |||
5385 | if (blk_iopoll_enabled) { | ||
5386 | for (i = 0; i < phba->num_cpus; i++) { | ||
5387 | pbe_eq = &phwi_context->be_eq[i]; | ||
5388 | blk_iopoll_init(&pbe_eq->iopoll, be_iopoll_budget, | ||
5389 | be_iopoll); | ||
5390 | blk_iopoll_enable(&pbe_eq->iopoll); | ||
5391 | } | ||
5392 | |||
5393 | i = (phba->msix_enabled) ? i : 0; | ||
5394 | /* Work item for MCC handling */ | ||
5395 | pbe_eq = &phwi_context->be_eq[i]; | ||
5396 | INIT_WORK(&pbe_eq->work_cqs, beiscsi_process_all_cqs); | ||
5397 | } else { | ||
5398 | if (phba->msix_enabled) { | ||
5399 | for (i = 0; i <= phba->num_cpus; i++) { | ||
5400 | pbe_eq = &phwi_context->be_eq[i]; | ||
5401 | INIT_WORK(&pbe_eq->work_cqs, | ||
5402 | beiscsi_process_all_cqs); | ||
5403 | } | ||
5404 | } else { | ||
5405 | pbe_eq = &phwi_context->be_eq[0]; | ||
5406 | INIT_WORK(&pbe_eq->work_cqs, | ||
5407 | beiscsi_process_all_cqs); | ||
5408 | } | ||
5409 | } | ||
5410 | |||
5411 | ret = beiscsi_init_irqs(phba); | ||
5412 | if (ret < 0) { | ||
5413 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
5414 | "BM_%d : beiscsi_eeh_resume - " | ||
5415 | "Failed to beiscsi_init_irqs\n"); | ||
5416 | goto ret_err; | ||
5417 | } | ||
5418 | |||
5419 | hwi_enable_intr(phba); | ||
5420 | phba->state &= ~BE_ADAPTER_PCI_ERR; | ||
5421 | |||
5422 | return; | ||
5423 | ret_err: | ||
5424 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
5425 | "BM_%d : AER EEH Resume Failed\n"); | ||
5426 | } | ||
5427 | |||
5254 | static int beiscsi_dev_probe(struct pci_dev *pcidev, | 5428 | static int beiscsi_dev_probe(struct pci_dev *pcidev, |
5255 | const struct pci_device_id *id) | 5429 | const struct pci_device_id *id) |
5256 | { | 5430 | { |
@@ -5258,7 +5432,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, | |||
5258 | struct hwi_controller *phwi_ctrlr; | 5432 | struct hwi_controller *phwi_ctrlr; |
5259 | struct hwi_context_memory *phwi_context; | 5433 | struct hwi_context_memory *phwi_context; |
5260 | struct be_eq_obj *pbe_eq; | 5434 | struct be_eq_obj *pbe_eq; |
5261 | int ret, i; | 5435 | int ret = 0, i; |
5262 | 5436 | ||
5263 | ret = beiscsi_enable_pci(pcidev); | 5437 | ret = beiscsi_enable_pci(pcidev); |
5264 | if (ret < 0) { | 5438 | if (ret < 0) { |
@@ -5274,6 +5448,15 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, | |||
5274 | goto disable_pci; | 5448 | goto disable_pci; |
5275 | } | 5449 | } |
5276 | 5450 | ||
5451 | /* Enable EEH reporting */ | ||
5452 | ret = pci_enable_pcie_error_reporting(pcidev); | ||
5453 | if (ret) | ||
5454 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, | ||
5455 | "BM_%d : PCIe Error Reporting " | ||
5456 | "Enabling Failed\n"); | ||
5457 | |||
5458 | pci_save_state(pcidev); | ||
5459 | |||
5277 | /* Initialize Driver configuration Paramters */ | 5460 | /* Initialize Driver configuration Paramters */ |
5278 | beiscsi_hba_attrs_init(phba); | 5461 | beiscsi_hba_attrs_init(phba); |
5279 | 5462 | ||
@@ -5359,7 +5542,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, | |||
5359 | goto free_port; | 5542 | goto free_port; |
5360 | } | 5543 | } |
5361 | 5544 | ||
5362 | for (i = 0; i < MAX_MCC_CMD ; i++) { | 5545 | for (i = 0; i < MAX_MCC_CMD; i++) { |
5363 | init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]); | 5546 | init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]); |
5364 | phba->ctrl.mcc_tag[i] = i + 1; | 5547 | phba->ctrl.mcc_tag[i] = i + 1; |
5365 | phba->ctrl.mcc_numtag[i + 1] = 0; | 5548 | phba->ctrl.mcc_numtag[i + 1] = 0; |
@@ -5463,6 +5646,12 @@ disable_pci: | |||
5463 | return ret; | 5646 | return ret; |
5464 | } | 5647 | } |
5465 | 5648 | ||
5649 | static struct pci_error_handlers beiscsi_eeh_handlers = { | ||
5650 | .error_detected = beiscsi_eeh_err_detected, | ||
5651 | .slot_reset = beiscsi_eeh_reset, | ||
5652 | .resume = beiscsi_eeh_resume, | ||
5653 | }; | ||
5654 | |||
5466 | struct iscsi_transport beiscsi_iscsi_transport = { | 5655 | struct iscsi_transport beiscsi_iscsi_transport = { |
5467 | .owner = THIS_MODULE, | 5656 | .owner = THIS_MODULE, |
5468 | .name = DRV_NAME, | 5657 | .name = DRV_NAME, |
@@ -5501,7 +5690,8 @@ static struct pci_driver beiscsi_pci_driver = { | |||
5501 | .probe = beiscsi_dev_probe, | 5690 | .probe = beiscsi_dev_probe, |
5502 | .remove = beiscsi_remove, | 5691 | .remove = beiscsi_remove, |
5503 | .shutdown = beiscsi_shutdown, | 5692 | .shutdown = beiscsi_shutdown, |
5504 | .id_table = beiscsi_pci_id_table | 5693 | .id_table = beiscsi_pci_id_table, |
5694 | .err_handler = &beiscsi_eeh_handlers | ||
5505 | }; | 5695 | }; |
5506 | 5696 | ||
5507 | 5697 | ||
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index a8ae6b82c3e1..aace072e033e 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/in.h> | 26 | #include <linux/in.h> |
27 | #include <linux/ctype.h> | 27 | #include <linux/ctype.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/aer.h> | ||
29 | #include <scsi/scsi.h> | 30 | #include <scsi/scsi.h> |
30 | #include <scsi/scsi_cmnd.h> | 31 | #include <scsi/scsi_cmnd.h> |
31 | #include <scsi/scsi_device.h> | 32 | #include <scsi/scsi_device.h> |
@@ -96,8 +97,12 @@ | |||
96 | 97 | ||
97 | #define INVALID_SESS_HANDLE 0xFFFFFFFF | 98 | #define INVALID_SESS_HANDLE 0xFFFFFFFF |
98 | 99 | ||
99 | #define BE_ADAPTER_UP 0x00000000 | 100 | #define BE_ADAPTER_LINK_UP 0x001 |
100 | #define BE_ADAPTER_LINK_DOWN 0x00000001 | 101 | #define BE_ADAPTER_LINK_DOWN 0x002 |
102 | #define BE_ADAPTER_PCI_ERR 0x004 | ||
103 | |||
104 | #define BEISCSI_CLEAN_UNLOAD 0x01 | ||
105 | #define BEISCSI_EEH_UNLOAD 0x02 | ||
101 | /** | 106 | /** |
102 | * hardware needs the async PDU buffers to be posted in multiples of 8 | 107 | * hardware needs the async PDU buffers to be posted in multiples of 8 |
103 | * So have atleast 8 of them by default | 108 | * So have atleast 8 of them by default |