aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorSawan Chandak <sawan.chandak@qlogic.com>2016-07-06 11:14:25 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2016-07-15 15:31:31 -0400
commit783e0dc4f66ade6bbd8833b6bae778158d54c1a6 (patch)
tree730b6f3f3b3912a45e70b07ee2504c820f883385 /drivers/scsi
parentc6dc99058e5798958847eab7411083ca5b25643c (diff)
qla2xxx: Check for device state before unloading the driver.
During hot swap of PCI device, there can be PCI error on device, during normal driver unload. The race between normal driver unload and driver unload due to PCI error, can lead to system crash.Fix is to check if there is unload going on and allow that function to unload the driver. Signed-off-by: Sawan Chandak <sawan.chandak@qlogic.com> Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c41
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c21
4 files changed, 52 insertions, 13 deletions
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index c6ccc8a86fa7..2790e5f2f29c 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -14,7 +14,7 @@
14 * | Module Init and Probe | 0x018f | 0x0146 | 14 * | Module Init and Probe | 0x018f | 0x0146 |
15 * | | | 0x015b-0x0160 | 15 * | | | 0x015b-0x0160 |
16 * | | | 0x016e | 16 * | | | 0x016e |
17 * | Mailbox commands | 0x1192 | | 17 * | Mailbox commands | 0x1191 | |
18 * | | | | 18 * | | | |
19 * | Device Discovery | 0x2003 | 0x2016 | 19 * | Device Discovery | 0x2003 | 0x2016 |
20 * | | | 0x2011-0x2012, | 20 * | | | 0x2011-0x2012, |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index a73ecc780e1a..7d4bd7de3e9c 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3658,6 +3658,7 @@ typedef struct scsi_qla_host {
3658#define PFLG_DISCONNECTED 0 /* PCI device removed */ 3658#define PFLG_DISCONNECTED 0 /* PCI device removed */
3659#define PFLG_DRIVER_REMOVING 1 /* PCI driver .remove */ 3659#define PFLG_DRIVER_REMOVING 1 /* PCI driver .remove */
3660#define PFLG_DRIVER_PROBING 2 /* PCI driver .probe */ 3660#define PFLG_DRIVER_PROBING 2 /* PCI driver .probe */
3661#define PCI_ERR 30
3661 3662
3662 uint32_t device_flags; 3663 uint32_t device_flags;
3663#define SWITCH_FOUND BIT_0 3664#define SWITCH_FOUND BIT_0
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 583ad62f8d51..97099ce2df15 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -64,6 +64,13 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
64 return QLA_FUNCTION_TIMEOUT; 64 return QLA_FUNCTION_TIMEOUT;
65 } 65 }
66 66
67 /* if PCI error, then avoid mbx processing.*/
68 if (test_bit(PCI_ERR, &base_vha->dpc_flags)) {
69 ql_log(ql_log_warn, vha, 0x1191,
70 "PCI error, exiting.\n");
71 return QLA_FUNCTION_TIMEOUT;
72 }
73
67 reg = ha->iobase; 74 reg = ha->iobase;
68 io_lock_on = base_vha->flags.init_done; 75 io_lock_on = base_vha->flags.init_done;
69 76
@@ -266,6 +273,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
266 273
267 uint16_t mb0; 274 uint16_t mb0;
268 uint32_t ictrl; 275 uint32_t ictrl;
276 uint16_t w;
269 277
270 if (IS_FWI2_CAPABLE(ha)) { 278 if (IS_FWI2_CAPABLE(ha)) {
271 mb0 = RD_REG_WORD(&reg->isp24.mailbox0); 279 mb0 = RD_REG_WORD(&reg->isp24.mailbox0);
@@ -279,15 +287,32 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
279 "mb[0]=0x%x\n", command, ictrl, jiffies, mb0); 287 "mb[0]=0x%x\n", command, ictrl, jiffies, mb0);
280 ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1019); 288 ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1019);
281 289
282 /* 290 /* Capture FW dump only, if PCI device active */
283 * Attempt to capture a firmware dump for further analysis 291 if (!pci_channel_offline(vha->hw->pdev)) {
284 * of the current firmware state. We do not need to do this 292 pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
285 * if we are intentionally generating a dump. 293 if (w == 0xffff || ictrl == 0xffffffff) {
286 */ 294 /* This is special case if there is unload
287 if (mcp->mb[0] != MBC_GEN_SYSTEM_ERROR) 295 * of driver happening and if PCI device go
288 ha->isp_ops->fw_dump(vha, 0); 296 * into bad state due to PCI error condition
297 * then only PCI ERR flag would be set.
298 * we will do premature exit for above case.
299 */
300 if (test_bit(UNLOADING, &base_vha->dpc_flags))
301 set_bit(PCI_ERR, &base_vha->dpc_flags);
302 ha->flags.mbox_busy = 0;
303 rval = QLA_FUNCTION_TIMEOUT;
304 goto premature_exit;
305 }
289 306
290 rval = QLA_FUNCTION_TIMEOUT; 307 /* Attempt to capture firmware dump for further
308 * anallysis of the current formware state. we do not
309 * need to do this if we are intentionally generating
310 * a dump
311 */
312 if (mcp->mb[0] != MBC_GEN_SYSTEM_ERROR)
313 ha->isp_ops->fw_dump(vha, 0);
314 rval = QLA_FUNCTION_TIMEOUT;
315 }
291 } 316 }
292 317
293 ha->flags.mbox_busy = 0; 318 ha->flags.mbox_busy = 0;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index f1a2394a99e5..fde7ee17ed85 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -897,12 +897,16 @@ static void
897qla2x00_wait_for_hba_ready(scsi_qla_host_t *vha) 897qla2x00_wait_for_hba_ready(scsi_qla_host_t *vha)
898{ 898{
899 struct qla_hw_data *ha = vha->hw; 899 struct qla_hw_data *ha = vha->hw;
900 scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
900 901
901 while (((qla2x00_reset_active(vha)) || ha->dpc_active || 902 while (((qla2x00_reset_active(vha)) || ha->dpc_active ||
902 ha->flags.mbox_busy) || 903 ha->flags.mbox_busy) ||
903 test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags) || 904 test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags) ||
904 test_bit(FX00_TARGET_SCAN, &vha->dpc_flags)) 905 test_bit(FX00_TARGET_SCAN, &vha->dpc_flags)) {
906 if (test_bit(UNLOADING, &base_vha->dpc_flags))
907 break;
905 msleep(1000); 908 msleep(1000);
909 }
906} 910}
907 911
908int 912int
@@ -2954,10 +2958,7 @@ iospace_config_failed:
2954 ha = NULL; 2958 ha = NULL;
2955 2959
2956probe_out: 2960probe_out:
2957 pci_disable_pcie_error_reporting(pdev);
2958 pci_disable_device(pdev); 2961 pci_disable_device(pdev);
2959 if (test_bit(UNLOADING, &base_vha->dpc_flags))
2960 return -ENODEV;
2961 return ret; 2962 return ret;
2962} 2963}
2963 2964
@@ -3138,6 +3139,12 @@ qla2x00_remove_one(struct pci_dev *pdev)
3138 3139
3139 qla2x00_wait_for_hba_ready(base_vha); 3140 qla2x00_wait_for_hba_ready(base_vha);
3140 3141
3142 /* if UNLOAD flag is already set, then continue unload,
3143 * where it was set first.
3144 */
3145 if (test_bit(UNLOADING, &base_vha->dpc_flags))
3146 return;
3147
3141 set_bit(UNLOADING, &base_vha->dpc_flags); 3148 set_bit(UNLOADING, &base_vha->dpc_flags);
3142 3149
3143 if (IS_QLAFX00(ha)) 3150 if (IS_QLAFX00(ha))
@@ -4917,6 +4924,12 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work)
4917 struct pci_dev *pdev = ha->pdev; 4924 struct pci_dev *pdev = ha->pdev;
4918 scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); 4925 scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
4919 4926
4927 /* if UNLOAD flag is already set, then continue unload,
4928 * where it was set first.
4929 */
4930 if (test_bit(UNLOADING, &base_vha->dpc_flags))
4931 return;
4932
4920 ql_log(ql_log_warn, base_vha, 0x015b, 4933 ql_log(ql_log_warn, base_vha, 0x015b,
4921 "Disabling adapter.\n"); 4934 "Disabling adapter.\n");
4922 4935