| .. | .. |
|---|
| 879 | 879 | goto qc24_fail_command; |
|---|
| 880 | 880 | } |
|---|
| 881 | 881 | |
|---|
| 882 | | - if (!fcport) { |
|---|
| 883 | | - cmd->result = DID_NO_CONNECT << 16; |
|---|
| 882 | + if (!fcport || fcport->deleted) { |
|---|
| 883 | + cmd->result = DID_IMM_RETRY << 16; |
|---|
| 884 | 884 | goto qc24_fail_command; |
|---|
| 885 | 885 | } |
|---|
| 886 | 886 | |
|---|
| .. | .. |
|---|
| 961 | 961 | goto qc24_fail_command; |
|---|
| 962 | 962 | } |
|---|
| 963 | 963 | |
|---|
| 964 | | - if (!fcport) { |
|---|
| 964 | + if (!qpair->online) { |
|---|
| 965 | + ql_dbg(ql_dbg_io, vha, 0x3077, |
|---|
| 966 | + "qpair not online. eeh_busy=%d.\n", ha->flags.eeh_busy); |
|---|
| 965 | 967 | cmd->result = DID_NO_CONNECT << 16; |
|---|
| 968 | + goto qc24_fail_command; |
|---|
| 969 | + } |
|---|
| 970 | + |
|---|
| 971 | + if (!fcport || fcport->deleted) { |
|---|
| 972 | + cmd->result = DID_IMM_RETRY << 16; |
|---|
| 966 | 973 | goto qc24_fail_command; |
|---|
| 967 | 974 | } |
|---|
| 968 | 975 | |
|---|
| .. | .. |
|---|
| 1190 | 1197 | return return_status; |
|---|
| 1191 | 1198 | } |
|---|
| 1192 | 1199 | |
|---|
| 1193 | | -#define ISP_REG_DISCONNECT 0xffffffffU |
|---|
| 1194 | | -/************************************************************************** |
|---|
| 1195 | | -* qla2x00_isp_reg_stat |
|---|
| 1196 | | -* |
|---|
| 1197 | | -* Description: |
|---|
| 1198 | | -* Read the host status register of ISP before aborting the command. |
|---|
| 1199 | | -* |
|---|
| 1200 | | -* Input: |
|---|
| 1201 | | -* ha = pointer to host adapter structure. |
|---|
| 1202 | | -* |
|---|
| 1203 | | -* |
|---|
| 1204 | | -* Returns: |
|---|
| 1205 | | -* Either true or false. |
|---|
| 1206 | | -* |
|---|
| 1207 | | -* Note: Return true if there is register disconnect. |
|---|
| 1208 | | -**************************************************************************/ |
|---|
| 1209 | | -static inline |
|---|
| 1210 | | -uint32_t qla2x00_isp_reg_stat(struct qla_hw_data *ha) |
|---|
| 1211 | | -{ |
|---|
| 1212 | | - struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; |
|---|
| 1213 | | - struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82; |
|---|
| 1214 | | - |
|---|
| 1215 | | - if (IS_P3P_TYPE(ha)) |
|---|
| 1216 | | - return ((rd_reg_dword(®82->host_int)) == ISP_REG_DISCONNECT); |
|---|
| 1217 | | - else |
|---|
| 1218 | | - return ((rd_reg_dword(®->host_status)) == |
|---|
| 1219 | | - ISP_REG_DISCONNECT); |
|---|
| 1220 | | -} |
|---|
| 1221 | | - |
|---|
| 1222 | 1200 | /************************************************************************** |
|---|
| 1223 | 1201 | * qla2xxx_eh_abort |
|---|
| 1224 | 1202 | * |
|---|
| .. | .. |
|---|
| 1253 | 1231 | if (qla2x00_isp_reg_stat(ha)) { |
|---|
| 1254 | 1232 | ql_log(ql_log_info, vha, 0x8042, |
|---|
| 1255 | 1233 | "PCI/Register disconnect, exiting.\n"); |
|---|
| 1234 | + qla_pci_set_eeh_busy(vha); |
|---|
| 1256 | 1235 | return FAILED; |
|---|
| 1257 | 1236 | } |
|---|
| 1258 | 1237 | |
|---|
| .. | .. |
|---|
| 1444 | 1423 | if (qla2x00_isp_reg_stat(ha)) { |
|---|
| 1445 | 1424 | ql_log(ql_log_info, vha, 0x803e, |
|---|
| 1446 | 1425 | "PCI/Register disconnect, exiting.\n"); |
|---|
| 1426 | + qla_pci_set_eeh_busy(vha); |
|---|
| 1447 | 1427 | return FAILED; |
|---|
| 1448 | 1428 | } |
|---|
| 1449 | 1429 | |
|---|
| .. | .. |
|---|
| 1460 | 1440 | if (qla2x00_isp_reg_stat(ha)) { |
|---|
| 1461 | 1441 | ql_log(ql_log_info, vha, 0x803f, |
|---|
| 1462 | 1442 | "PCI/Register disconnect, exiting.\n"); |
|---|
| 1443 | + qla_pci_set_eeh_busy(vha); |
|---|
| 1463 | 1444 | return FAILED; |
|---|
| 1464 | 1445 | } |
|---|
| 1465 | 1446 | |
|---|
| .. | .. |
|---|
| 1495 | 1476 | if (qla2x00_isp_reg_stat(ha)) { |
|---|
| 1496 | 1477 | ql_log(ql_log_info, vha, 0x8040, |
|---|
| 1497 | 1478 | "PCI/Register disconnect, exiting.\n"); |
|---|
| 1479 | + qla_pci_set_eeh_busy(vha); |
|---|
| 1498 | 1480 | return FAILED; |
|---|
| 1499 | 1481 | } |
|---|
| 1500 | 1482 | |
|---|
| .. | .. |
|---|
| 1572 | 1554 | if (qla2x00_isp_reg_stat(ha)) { |
|---|
| 1573 | 1555 | ql_log(ql_log_info, vha, 0x8041, |
|---|
| 1574 | 1556 | "PCI/Register disconnect, exiting.\n"); |
|---|
| 1575 | | - schedule_work(&ha->board_disable); |
|---|
| 1557 | + qla_pci_set_eeh_busy(vha); |
|---|
| 1576 | 1558 | return SUCCESS; |
|---|
| 1577 | 1559 | } |
|---|
| 1578 | 1560 | |
|---|
| .. | .. |
|---|
| 1762 | 1744 | for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) { |
|---|
| 1763 | 1745 | sp = req->outstanding_cmds[cnt]; |
|---|
| 1764 | 1746 | if (sp) { |
|---|
| 1747 | + /* |
|---|
| 1748 | + * perform lockless completion during driver unload |
|---|
| 1749 | + */ |
|---|
| 1750 | + if (qla2x00_chip_is_down(vha)) { |
|---|
| 1751 | + req->outstanding_cmds[cnt] = NULL; |
|---|
| 1752 | + spin_unlock_irqrestore(qp->qp_lock_ptr, flags); |
|---|
| 1753 | + sp->done(sp, res); |
|---|
| 1754 | + spin_lock_irqsave(qp->qp_lock_ptr, flags); |
|---|
| 1755 | + continue; |
|---|
| 1756 | + } |
|---|
| 1757 | + |
|---|
| 1765 | 1758 | switch (sp->cmd_type) { |
|---|
| 1766 | 1759 | case TYPE_SRB: |
|---|
| 1767 | 1760 | qla2x00_abort_srb(qp, sp, res, &flags); |
|---|
| .. | .. |
|---|
| 2855 | 2848 | ha->max_exchg = FW_MAX_EXCHANGES_CNT; |
|---|
| 2856 | 2849 | atomic_set(&ha->num_pend_mbx_stage1, 0); |
|---|
| 2857 | 2850 | atomic_set(&ha->num_pend_mbx_stage2, 0); |
|---|
| 2858 | | - atomic_set(&ha->num_pend_mbx_stage3, 0); |
|---|
| 2859 | 2851 | atomic_set(&ha->zio_threshold, DEFAULT_ZIO_THRESHOLD); |
|---|
| 2860 | 2852 | ha->last_zio_threshold = DEFAULT_ZIO_THRESHOLD; |
|---|
| 2861 | 2853 | |
|---|
| .. | .. |
|---|
| 3130 | 3122 | host->max_id = ha->max_fibre_devices; |
|---|
| 3131 | 3123 | host->cmd_per_lun = 3; |
|---|
| 3132 | 3124 | host->unique_id = host->host_no; |
|---|
| 3125 | + |
|---|
| 3126 | + if (ql2xenabledif && ql2xenabledif != 2) { |
|---|
| 3127 | + ql_log(ql_log_warn, base_vha, 0x302d, |
|---|
| 3128 | + "Invalid value for ql2xenabledif, resetting it to default (2)\n"); |
|---|
| 3129 | + ql2xenabledif = 2; |
|---|
| 3130 | + } |
|---|
| 3131 | + |
|---|
| 3133 | 3132 | if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) |
|---|
| 3134 | 3133 | host->max_cmd_len = 32; |
|---|
| 3135 | 3134 | else |
|---|
| .. | .. |
|---|
| 3362 | 3361 | base_vha->flags.difdix_supported = 1; |
|---|
| 3363 | 3362 | ql_dbg(ql_dbg_init, base_vha, 0x00f1, |
|---|
| 3364 | 3363 | "Registering for DIF/DIX type 1 and 3 protection.\n"); |
|---|
| 3365 | | - if (ql2xenabledif == 1) |
|---|
| 3366 | | - prot = SHOST_DIX_TYPE0_PROTECTION; |
|---|
| 3367 | 3364 | if (ql2xprotmask) |
|---|
| 3368 | 3365 | scsi_host_set_prot(host, ql2xprotmask); |
|---|
| 3369 | 3366 | else |
|---|
| .. | .. |
|---|
| 4866 | 4863 | } |
|---|
| 4867 | 4864 | INIT_DELAYED_WORK(&vha->scan.scan_work, qla_scan_work_fn); |
|---|
| 4868 | 4865 | |
|---|
| 4869 | | - sprintf(vha->host_str, "%s_%lu", QLA2XXX_DRIVER_NAME, vha->host_no); |
|---|
| 4866 | + snprintf(vha->host_str, sizeof(vha->host_str), "%s_%lu", |
|---|
| 4867 | + QLA2XXX_DRIVER_NAME, vha->host_no); |
|---|
| 4870 | 4868 | ql_dbg(ql_dbg_init, vha, 0x0041, |
|---|
| 4871 | 4869 | "Allocated the host=%p hw=%p vha=%p dev_name=%s", |
|---|
| 4872 | 4870 | vha->host, vha->hw, vha, |
|---|
| .. | .. |
|---|
| 6660 | 6658 | |
|---|
| 6661 | 6659 | schedule(); |
|---|
| 6662 | 6660 | |
|---|
| 6661 | + if (test_and_clear_bit(DO_EEH_RECOVERY, &base_vha->dpc_flags)) |
|---|
| 6662 | + qla_pci_set_eeh_busy(base_vha); |
|---|
| 6663 | + |
|---|
| 6663 | 6664 | if (!base_vha->flags.init_done || ha->flags.mbox_busy) |
|---|
| 6664 | 6665 | goto end_loop; |
|---|
| 6665 | 6666 | |
|---|
| .. | .. |
|---|
| 6899 | 6900 | } |
|---|
| 6900 | 6901 | } |
|---|
| 6901 | 6902 | loop_resync_check: |
|---|
| 6902 | | - if (test_and_clear_bit(LOOP_RESYNC_NEEDED, |
|---|
| 6903 | + if (!qla2x00_reset_active(base_vha) && |
|---|
| 6904 | + test_and_clear_bit(LOOP_RESYNC_NEEDED, |
|---|
| 6903 | 6905 | &base_vha->dpc_flags)) { |
|---|
| 6904 | | - |
|---|
| 6906 | + /* |
|---|
| 6907 | + * Allow abort_isp to complete before moving on to scanning. |
|---|
| 6908 | + */ |
|---|
| 6905 | 6909 | ql_dbg(ql_dbg_dpc, base_vha, 0x400f, |
|---|
| 6906 | 6910 | "Loop resync scheduled.\n"); |
|---|
| 6907 | 6911 | |
|---|
| .. | .. |
|---|
| 6953 | 6957 | mutex_unlock(&ha->mq_lock); |
|---|
| 6954 | 6958 | } |
|---|
| 6955 | 6959 | |
|---|
| 6956 | | - if (test_and_clear_bit(SET_NVME_ZIO_THRESHOLD_NEEDED, |
|---|
| 6957 | | - &base_vha->dpc_flags)) { |
|---|
| 6958 | | - ql_log(ql_log_info, base_vha, 0xffffff, |
|---|
| 6959 | | - "nvme: SET ZIO Activity exchange threshold to %d.\n", |
|---|
| 6960 | | - ha->nvme_last_rptd_aen); |
|---|
| 6961 | | - if (qla27xx_set_zio_threshold(base_vha, |
|---|
| 6962 | | - ha->nvme_last_rptd_aen)) { |
|---|
| 6963 | | - ql_log(ql_log_info, base_vha, 0xffffff, |
|---|
| 6964 | | - "nvme: Unable to SET ZIO Activity exchange threshold to %d.\n", |
|---|
| 6965 | | - ha->nvme_last_rptd_aen); |
|---|
| 6966 | | - } |
|---|
| 6967 | | - } |
|---|
| 6968 | | - |
|---|
| 6969 | 6960 | if (test_and_clear_bit(SET_ZIO_THRESHOLD_NEEDED, |
|---|
| 6970 | | - &base_vha->dpc_flags)) { |
|---|
| 6961 | + &base_vha->dpc_flags)) { |
|---|
| 6962 | + u16 threshold = ha->nvme_last_rptd_aen + ha->last_zio_threshold; |
|---|
| 6963 | + |
|---|
| 6964 | + if (threshold > ha->orig_fw_xcb_count) |
|---|
| 6965 | + threshold = ha->orig_fw_xcb_count; |
|---|
| 6966 | + |
|---|
| 6971 | 6967 | ql_log(ql_log_info, base_vha, 0xffffff, |
|---|
| 6972 | | - "SET ZIO Activity exchange threshold to %d.\n", |
|---|
| 6973 | | - ha->last_zio_threshold); |
|---|
| 6974 | | - qla27xx_set_zio_threshold(base_vha, |
|---|
| 6975 | | - ha->last_zio_threshold); |
|---|
| 6968 | + "SET ZIO Activity exchange threshold to %d.\n", |
|---|
| 6969 | + threshold); |
|---|
| 6970 | + if (qla27xx_set_zio_threshold(base_vha, threshold)) { |
|---|
| 6971 | + ql_log(ql_log_info, base_vha, 0xffffff, |
|---|
| 6972 | + "Unable to SET ZIO Activity exchange threshold to %d.\n", |
|---|
| 6973 | + threshold); |
|---|
| 6974 | + } |
|---|
| 6976 | 6975 | } |
|---|
| 6977 | 6976 | |
|---|
| 6978 | 6977 | if (!IS_QLAFX00(ha)) |
|---|
| .. | .. |
|---|
| 7145 | 7144 | |
|---|
| 7146 | 7145 | /* if the loop has been down for 4 minutes, reinit adapter */ |
|---|
| 7147 | 7146 | if (atomic_dec_and_test(&vha->loop_down_timer) != 0) { |
|---|
| 7148 | | - if (!(vha->device_flags & DFLG_NO_CABLE)) { |
|---|
| 7147 | + if (!(vha->device_flags & DFLG_NO_CABLE) && !vha->vp_idx) { |
|---|
| 7149 | 7148 | ql_log(ql_log_warn, vha, 0x6009, |
|---|
| 7150 | 7149 | "Loop down - aborting ISP.\n"); |
|---|
| 7151 | 7150 | |
|---|
| .. | .. |
|---|
| 7190 | 7189 | index = atomic_read(&ha->nvme_active_aen_cnt); |
|---|
| 7191 | 7190 | if (!vha->vp_idx && |
|---|
| 7192 | 7191 | (index != ha->nvme_last_rptd_aen) && |
|---|
| 7193 | | - (index >= DEFAULT_ZIO_THRESHOLD) && |
|---|
| 7194 | 7192 | ha->zio_mode == QLA_ZIO_MODE_6 && |
|---|
| 7195 | 7193 | !ha->flags.host_shutting_down) { |
|---|
| 7194 | + ha->nvme_last_rptd_aen = atomic_read(&ha->nvme_active_aen_cnt); |
|---|
| 7196 | 7195 | ql_log(ql_log_info, vha, 0x3002, |
|---|
| 7197 | 7196 | "nvme: Sched: Set ZIO exchange threshold to %d.\n", |
|---|
| 7198 | 7197 | ha->nvme_last_rptd_aen); |
|---|
| 7199 | | - ha->nvme_last_rptd_aen = atomic_read(&ha->nvme_active_aen_cnt); |
|---|
| 7200 | | - set_bit(SET_NVME_ZIO_THRESHOLD_NEEDED, &vha->dpc_flags); |
|---|
| 7198 | + set_bit(SET_ZIO_THRESHOLD_NEEDED, &vha->dpc_flags); |
|---|
| 7201 | 7199 | start_dpc++; |
|---|
| 7202 | 7200 | } |
|---|
| 7203 | 7201 | |
|---|
| .. | .. |
|---|
| 7370 | 7368 | int i; |
|---|
| 7371 | 7369 | unsigned long flags; |
|---|
| 7372 | 7370 | |
|---|
| 7371 | + ql_dbg(ql_dbg_aer, vha, 0x9000, |
|---|
| 7372 | + "%s\n", __func__); |
|---|
| 7373 | 7373 | ha->chip_reset++; |
|---|
| 7374 | 7374 | |
|---|
| 7375 | 7375 | ha->base_qpair->chip_reset = ha->chip_reset; |
|---|
| .. | .. |
|---|
| 7379 | 7379 | ha->base_qpair->chip_reset; |
|---|
| 7380 | 7380 | } |
|---|
| 7381 | 7381 | |
|---|
| 7382 | | - /* purge MBox commands */ |
|---|
| 7383 | | - if (atomic_read(&ha->num_pend_mbx_stage3)) { |
|---|
| 7384 | | - clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); |
|---|
| 7385 | | - complete(&ha->mbx_intr_comp); |
|---|
| 7386 | | - } |
|---|
| 7387 | | - |
|---|
| 7388 | | - i = 0; |
|---|
| 7389 | | - |
|---|
| 7390 | | - while (atomic_read(&ha->num_pend_mbx_stage3) || |
|---|
| 7391 | | - atomic_read(&ha->num_pend_mbx_stage2) || |
|---|
| 7392 | | - atomic_read(&ha->num_pend_mbx_stage1)) { |
|---|
| 7393 | | - msleep(20); |
|---|
| 7394 | | - i++; |
|---|
| 7395 | | - if (i > 50) |
|---|
| 7396 | | - break; |
|---|
| 7397 | | - } |
|---|
| 7398 | | - |
|---|
| 7399 | | - ha->flags.purge_mbox = 0; |
|---|
| 7382 | + /* |
|---|
| 7383 | + * purge mailbox might take a while. Slot Reset/chip reset |
|---|
| 7384 | + * will take care of the purge |
|---|
| 7385 | + */ |
|---|
| 7400 | 7386 | |
|---|
| 7401 | 7387 | mutex_lock(&ha->mq_lock); |
|---|
| 7388 | + ha->base_qpair->online = 0; |
|---|
| 7402 | 7389 | list_for_each_entry(qpair, &base_vha->qp_list, qp_list_elem) |
|---|
| 7403 | 7390 | qpair->online = 0; |
|---|
| 7391 | + wmb(); |
|---|
| 7404 | 7392 | mutex_unlock(&ha->mq_lock); |
|---|
| 7405 | 7393 | |
|---|
| 7406 | 7394 | qla2x00_mark_all_devices_lost(vha); |
|---|
| .. | .. |
|---|
| 7437 | 7425 | { |
|---|
| 7438 | 7426 | scsi_qla_host_t *vha = pci_get_drvdata(pdev); |
|---|
| 7439 | 7427 | struct qla_hw_data *ha = vha->hw; |
|---|
| 7428 | + pci_ers_result_t ret = PCI_ERS_RESULT_NEED_RESET; |
|---|
| 7440 | 7429 | |
|---|
| 7441 | | - ql_dbg(ql_dbg_aer, vha, 0x9000, |
|---|
| 7442 | | - "PCI error detected, state %x.\n", state); |
|---|
| 7430 | + ql_log(ql_log_warn, vha, 0x9000, |
|---|
| 7431 | + "PCI error detected, state %x.\n", state); |
|---|
| 7432 | + ha->pci_error_state = QLA_PCI_ERR_DETECTED; |
|---|
| 7443 | 7433 | |
|---|
| 7444 | 7434 | if (!atomic_read(&pdev->enable_cnt)) { |
|---|
| 7445 | 7435 | ql_log(ql_log_info, vha, 0xffff, |
|---|
| 7446 | 7436 | "PCI device is disabled,state %x\n", state); |
|---|
| 7447 | | - return PCI_ERS_RESULT_NEED_RESET; |
|---|
| 7437 | + ret = PCI_ERS_RESULT_NEED_RESET; |
|---|
| 7438 | + goto out; |
|---|
| 7448 | 7439 | } |
|---|
| 7449 | 7440 | |
|---|
| 7450 | 7441 | switch (state) { |
|---|
| .. | .. |
|---|
| 7454 | 7445 | set_bit(QPAIR_ONLINE_CHECK_NEEDED, &vha->dpc_flags); |
|---|
| 7455 | 7446 | qla2xxx_wake_dpc(vha); |
|---|
| 7456 | 7447 | } |
|---|
| 7457 | | - return PCI_ERS_RESULT_CAN_RECOVER; |
|---|
| 7448 | + ret = PCI_ERS_RESULT_CAN_RECOVER; |
|---|
| 7449 | + break; |
|---|
| 7458 | 7450 | case pci_channel_io_frozen: |
|---|
| 7459 | | - ha->flags.eeh_busy = 1; |
|---|
| 7460 | | - qla_pci_error_cleanup(vha); |
|---|
| 7461 | | - return PCI_ERS_RESULT_NEED_RESET; |
|---|
| 7451 | + qla_pci_set_eeh_busy(vha); |
|---|
| 7452 | + ret = PCI_ERS_RESULT_NEED_RESET; |
|---|
| 7453 | + break; |
|---|
| 7462 | 7454 | case pci_channel_io_perm_failure: |
|---|
| 7463 | 7455 | ha->flags.pci_channel_io_perm_failure = 1; |
|---|
| 7464 | 7456 | qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16); |
|---|
| .. | .. |
|---|
| 7466 | 7458 | set_bit(QPAIR_ONLINE_CHECK_NEEDED, &vha->dpc_flags); |
|---|
| 7467 | 7459 | qla2xxx_wake_dpc(vha); |
|---|
| 7468 | 7460 | } |
|---|
| 7469 | | - return PCI_ERS_RESULT_DISCONNECT; |
|---|
| 7461 | + ret = PCI_ERS_RESULT_DISCONNECT; |
|---|
| 7470 | 7462 | } |
|---|
| 7471 | | - return PCI_ERS_RESULT_NEED_RESET; |
|---|
| 7463 | +out: |
|---|
| 7464 | + ql_dbg(ql_dbg_aer, vha, 0x600d, |
|---|
| 7465 | + "PCI error detected returning [%x].\n", ret); |
|---|
| 7466 | + return ret; |
|---|
| 7472 | 7467 | } |
|---|
| 7473 | 7468 | |
|---|
| 7474 | 7469 | static pci_ers_result_t |
|---|
| .. | .. |
|---|
| 7482 | 7477 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
|---|
| 7483 | 7478 | struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24; |
|---|
| 7484 | 7479 | |
|---|
| 7480 | + ql_log(ql_log_warn, base_vha, 0x9000, |
|---|
| 7481 | + "mmio enabled\n"); |
|---|
| 7482 | + |
|---|
| 7483 | + ha->pci_error_state = QLA_PCI_MMIO_ENABLED; |
|---|
| 7485 | 7484 | if (IS_QLA82XX(ha)) |
|---|
| 7486 | 7485 | return PCI_ERS_RESULT_RECOVERED; |
|---|
| 7487 | 7486 | |
|---|
| .. | .. |
|---|
| 7505 | 7504 | ql_log(ql_log_info, base_vha, 0x9003, |
|---|
| 7506 | 7505 | "RISC paused -- mmio_enabled, Dumping firmware.\n"); |
|---|
| 7507 | 7506 | qla2xxx_dump_fw(base_vha); |
|---|
| 7508 | | - |
|---|
| 7509 | | - return PCI_ERS_RESULT_NEED_RESET; |
|---|
| 7510 | | - } else |
|---|
| 7511 | | - return PCI_ERS_RESULT_RECOVERED; |
|---|
| 7507 | + } |
|---|
| 7508 | + /* set PCI_ERS_RESULT_NEED_RESET to trigger call to qla2xxx_pci_slot_reset */ |
|---|
| 7509 | + ql_dbg(ql_dbg_aer, base_vha, 0x600d, |
|---|
| 7510 | + "mmio enabled returning.\n"); |
|---|
| 7511 | + return PCI_ERS_RESULT_NEED_RESET; |
|---|
| 7512 | 7512 | } |
|---|
| 7513 | 7513 | |
|---|
| 7514 | 7514 | static pci_ers_result_t |
|---|
| .. | .. |
|---|
| 7520 | 7520 | int rc; |
|---|
| 7521 | 7521 | struct qla_qpair *qpair = NULL; |
|---|
| 7522 | 7522 | |
|---|
| 7523 | | - ql_dbg(ql_dbg_aer, base_vha, 0x9004, |
|---|
| 7524 | | - "Slot Reset.\n"); |
|---|
| 7523 | + ql_log(ql_log_warn, base_vha, 0x9004, |
|---|
| 7524 | + "Slot Reset.\n"); |
|---|
| 7525 | 7525 | |
|---|
| 7526 | + ha->pci_error_state = QLA_PCI_SLOT_RESET; |
|---|
| 7526 | 7527 | /* Workaround: qla2xxx driver which access hardware earlier |
|---|
| 7527 | 7528 | * needs error state to be pci_channel_io_online. |
|---|
| 7528 | 7529 | * Otherwise mailbox command timesout. |
|---|
| .. | .. |
|---|
| 7556 | 7557 | qpair->online = 1; |
|---|
| 7557 | 7558 | mutex_unlock(&ha->mq_lock); |
|---|
| 7558 | 7559 | |
|---|
| 7560 | + ha->flags.eeh_busy = 0; |
|---|
| 7559 | 7561 | base_vha->flags.online = 1; |
|---|
| 7560 | 7562 | set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); |
|---|
| 7561 | | - if (ha->isp_ops->abort_isp(base_vha) == QLA_SUCCESS) |
|---|
| 7562 | | - ret = PCI_ERS_RESULT_RECOVERED; |
|---|
| 7563 | + ha->isp_ops->abort_isp(base_vha); |
|---|
| 7563 | 7564 | clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); |
|---|
| 7564 | 7565 | |
|---|
| 7566 | + if (qla2x00_isp_reg_stat(ha)) { |
|---|
| 7567 | + ha->flags.eeh_busy = 1; |
|---|
| 7568 | + qla_pci_error_cleanup(base_vha); |
|---|
| 7569 | + ql_log(ql_log_warn, base_vha, 0x9005, |
|---|
| 7570 | + "Device unable to recover from PCI error.\n"); |
|---|
| 7571 | + } else { |
|---|
| 7572 | + ret = PCI_ERS_RESULT_RECOVERED; |
|---|
| 7573 | + } |
|---|
| 7565 | 7574 | |
|---|
| 7566 | 7575 | exit_slot_reset: |
|---|
| 7567 | 7576 | ql_dbg(ql_dbg_aer, base_vha, 0x900e, |
|---|
| 7568 | | - "slot_reset return %x.\n", ret); |
|---|
| 7577 | + "Slot Reset returning %x.\n", ret); |
|---|
| 7569 | 7578 | |
|---|
| 7570 | 7579 | return ret; |
|---|
| 7571 | 7580 | } |
|---|
| .. | .. |
|---|
| 7577 | 7586 | struct qla_hw_data *ha = base_vha->hw; |
|---|
| 7578 | 7587 | int ret; |
|---|
| 7579 | 7588 | |
|---|
| 7580 | | - ql_dbg(ql_dbg_aer, base_vha, 0x900f, |
|---|
| 7581 | | - "pci_resume.\n"); |
|---|
| 7589 | + ql_log(ql_log_warn, base_vha, 0x900f, |
|---|
| 7590 | + "Pci Resume.\n"); |
|---|
| 7582 | 7591 | |
|---|
| 7583 | | - ha->flags.eeh_busy = 0; |
|---|
| 7584 | 7592 | |
|---|
| 7585 | 7593 | ret = qla2x00_wait_for_hba_online(base_vha); |
|---|
| 7586 | 7594 | if (ret != QLA_SUCCESS) { |
|---|
| 7587 | 7595 | ql_log(ql_log_fatal, base_vha, 0x9002, |
|---|
| 7588 | 7596 | "The device failed to resume I/O from slot/link_reset.\n"); |
|---|
| 7589 | 7597 | } |
|---|
| 7598 | + ha->pci_error_state = QLA_PCI_RESUME; |
|---|
| 7599 | + ql_dbg(ql_dbg_aer, base_vha, 0x600d, |
|---|
| 7600 | + "Pci Resume returning.\n"); |
|---|
| 7601 | +} |
|---|
| 7602 | + |
|---|
| 7603 | +void qla_pci_set_eeh_busy(struct scsi_qla_host *vha) |
|---|
| 7604 | +{ |
|---|
| 7605 | + struct qla_hw_data *ha = vha->hw; |
|---|
| 7606 | + struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); |
|---|
| 7607 | + bool do_cleanup = false; |
|---|
| 7608 | + unsigned long flags; |
|---|
| 7609 | + |
|---|
| 7610 | + if (ha->flags.eeh_busy) |
|---|
| 7611 | + return; |
|---|
| 7612 | + |
|---|
| 7613 | + spin_lock_irqsave(&base_vha->work_lock, flags); |
|---|
| 7614 | + if (!ha->flags.eeh_busy) { |
|---|
| 7615 | + ha->flags.eeh_busy = 1; |
|---|
| 7616 | + do_cleanup = true; |
|---|
| 7617 | + } |
|---|
| 7618 | + spin_unlock_irqrestore(&base_vha->work_lock, flags); |
|---|
| 7619 | + |
|---|
| 7620 | + if (do_cleanup) |
|---|
| 7621 | + qla_pci_error_cleanup(base_vha); |
|---|
| 7622 | +} |
|---|
| 7623 | + |
|---|
| 7624 | +/* |
|---|
| 7625 | + * this routine will schedule a task to pause IO from interrupt context |
|---|
| 7626 | + * if caller sees a PCIE error event (register read = 0xf's) |
|---|
| 7627 | + */ |
|---|
| 7628 | +void qla_schedule_eeh_work(struct scsi_qla_host *vha) |
|---|
| 7629 | +{ |
|---|
| 7630 | + struct qla_hw_data *ha = vha->hw; |
|---|
| 7631 | + struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); |
|---|
| 7632 | + |
|---|
| 7633 | + if (ha->flags.eeh_busy) |
|---|
| 7634 | + return; |
|---|
| 7635 | + |
|---|
| 7636 | + set_bit(DO_EEH_RECOVERY, &base_vha->dpc_flags); |
|---|
| 7637 | + qla2xxx_wake_dpc(base_vha); |
|---|
| 7590 | 7638 | } |
|---|
| 7591 | 7639 | |
|---|
| 7592 | 7640 | static void |
|---|