summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_isr.c
diff options
context:
space:
mode:
authorJoe Lawrence <joe.lawrence@stratus.com>2014-08-26 17:12:14 -0400
committerChristoph Hellwig <hch@lst.de>2014-09-16 09:10:01 -0700
commitbeb9e315e6e0d8d1d7d3a79d2e5d4664aa8f8796 (patch)
treea6955355cb53775302f139fa134462af1f5740c1 /drivers/scsi/qla2xxx/qla_isr.c
parent232792b6b43b1420324e432a0498602b9c8d5a8c (diff)
downloadlinux-beb9e315e6e0d8d1d7d3a79d2e5d4664aa8f8796.tar.gz
linux-beb9e315e6e0d8d1d7d3a79d2e5d4664aa8f8796.tar.bz2
linux-beb9e315e6e0d8d1d7d3a79d2e5d4664aa8f8796.zip
qla2xxx: Prevent removal and board_disable race
Introduce mutual exclusion between the qla2xxx_remove_one PCI driver callback and qla2x00_disable_board_on_pci_error, which is scheduled as board_disable work by qla2x00_check_reg{32,16}_for_disconnect: * Leave the driver-specific data attached to the underlying PCI device intact in qla2x00_disable_board_on_pci_error, so that qla2x00_remove_one has enough breadcrumbs to determine that any board_disable work has been completed. * In qla2xxx_remove_one, set a bit to prevent any subsequent board_disable work from scheduling, then cancel and wait until pending work has completed. * Reuse the PCI device enable count check in qla2x00_remove_one to determine if board_disable has occured. The original purpose of this check was unnecessary since the driver remove function wasn't called when the probe fails. Signed-off-by: Joe Lawrence <joe.lawrence@stratus.com> Acked-by: Chad Dupuis <chad.dupuis@qlogic.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_isr.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index fd75b9139693..341c64daa959 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -117,7 +117,8 @@ qla2x00_check_reg32_for_disconnect(scsi_qla_host_t *vha, uint32_t reg)
{
/* Check for PCI disconnection */
if (reg == 0xffffffff) {
- if (!test_and_set_bit(PFLG_DISCONNECTED, &vha->pci_flags)) {
+ if (!test_and_set_bit(PFLG_DISCONNECTED, &vha->pci_flags) &&
+ !test_bit(PFLG_DRIVER_REMOVING, &vha->pci_flags)) {
/*
* Schedule this (only once) on the default system
* workqueue so that all the adapter workqueues and the