qla2x00_disable_board_on_pci_error and pcie error handlers may run in parallel. Specifically, I observed qla2xxx_pci_slot_reset running at around the same moment as qla2x00_disable_board_on_pci_error. If scsi_qla_host_t or qla_hw_data structs are removed before an error handler completes, the handler crashes. This patch disables pcie error handling early in qla2x00_disable_board_on_pci_error and in other paths that remove those structs. Signed-off-by: Anatoliy Glagolev <glagolig@xxxxxxxxx> --- drivers/scsi/qla2xxx/qla_os.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index e881fce..b8f277a 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2775,9 +2775,6 @@ static void qla2x00_iocb_work_fn(struct work_struct *work) return ret; } - /* This may fail but that's ok */ - pci_enable_pcie_error_reporting(pdev); - ha = kzalloc(sizeof(struct qla_hw_data), GFP_KERNEL); if (!ha) { ql_log_pci(ql_log_fatal, pdev, 0x0009, @@ -3039,6 +3036,9 @@ static void qla2x00_iocb_work_fn(struct work_struct *work) goto probe_hw_failed; } + /* This may fail but that's ok */ + pci_enable_pcie_error_reporting(pdev); + pci_set_drvdata(pdev, base_vha); set_bit(PFLG_DRIVER_PROBING, &base_vha->pci_flags); @@ -3400,6 +3400,8 @@ static void qla2x00_iocb_work_fn(struct work_struct *work) kthread_stop(t); } + pci_disable_pcie_error_reporting(); + qla2x00_free_device(base_vha); scsi_host_put(base_vha->host); /* @@ -3625,6 +3627,8 @@ static void qla2x00_iocb_work_fn(struct work_struct *work) } qla2x00_wait_for_hba_ready(base_vha); + pci_disable_pcie_error_reporting(pdev); + qla2x00_wait_for_sess_deletion(base_vha); /* @@ -3698,8 +3702,6 @@ static void qla2x00_iocb_work_fn(struct work_struct *work) pci_release_selected_regions(ha->pdev, ha->bars); kfree(ha); - pci_disable_pcie_error_reporting(pdev); - pci_disable_device(pdev); } @@ -5826,6 +5828,8 @@ void qla2x00_relogin(struct scsi_qla_host *vha) return; } + pci_disable_pcie_error_reporting(pdev); + qla2x00_wait_for_sess_deletion(base_vha); set_bit(UNLOADING, &base_vha->dpc_flags); @@ -5866,7 +5870,6 @@ void qla2x00_relogin(struct scsi_qla_host *vha) qla2x00_unmap_iobases(ha); pci_release_selected_regions(ha->pdev, ha->bars); - pci_disable_pcie_error_reporting(pdev); pci_disable_device(pdev); /* -- 1.9.1