A system crashes when continuously removing/re-adding
the storage controller.

Signed-off-by: Manish Rangankar <manish.rangan...@cavium.com>
---
 drivers/scsi/qla4xxx/ql4_def.h |  2 ++
 drivers/scsi/qla4xxx/ql4_os.c  | 46 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index fc23371..817f312 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -168,6 +168,8 @@
 #define DEV_DB_NON_PERSISTENT  0
 #define DEV_DB_PERSISTENT      1
 
+#define QL4_ISP_REG_DISCONNECT 0xffffffffU
+
 #define COPY_ISID(dst_isid, src_isid) {                        \
        int i, j;                                       \
        for (i = 0, j = ISID_SIZE - 1; i < ISID_SIZE;)  \
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 2b8a8ce..efaa7f1 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -262,6 +262,24 @@ static int qla4xxx_sysfs_ddb_logout(struct 
iscsi_bus_flash_session *fnode_sess,
 
 static struct scsi_transport_template *qla4xxx_scsi_transport;
 
+static int qla4xxx_isp_check_reg(struct scsi_qla_host *ha)
+{
+       u32 reg_val = 0;
+       int rval = QLA_SUCCESS;
+
+       if (is_qla8022(ha))
+               reg_val = readl(&ha->qla4_82xx_reg->host_status);
+       else if (is_qla8032(ha) || is_qla8042(ha))
+               reg_val = qla4_8xxx_rd_direct(ha, QLA8XXX_PEG_ALIVE_COUNTER);
+       else
+               reg_val = readw(&ha->reg->ctrl_status);
+
+       if (reg_val == QL4_ISP_REG_DISCONNECT)
+               rval = QLA_ERROR;
+
+       return rval;
+}
+
 static int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num,
                             uint32_t iface_type, uint32_t payload_size,
                             uint32_t pid, struct sockaddr *dst_addr)
@@ -9188,10 +9206,17 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd)
        struct srb *srb = NULL;
        int ret = SUCCESS;
        int wait = 0;
+       int rval;
 
        ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%llu: Abort command issued 
cmd=%p, cdb=0x%x\n",
                   ha->host_no, id, lun, cmd, cmd->cmnd[0]);
 
+       rval = qla4xxx_isp_check_reg(ha);
+       if (rval != QLA_SUCCESS) {
+               ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, 
exiting.\n");
+               return FAILED;
+       }
+
        spin_lock_irqsave(&ha->hardware_lock, flags);
        srb = (struct srb *) CMD_SP(cmd);
        if (!srb) {
@@ -9243,6 +9268,7 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
        struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
        struct ddb_entry *ddb_entry = cmd->device->hostdata;
        int ret = FAILED, stat;
+       int rval;
 
        if (!ddb_entry)
                return ret;
@@ -9262,6 +9288,12 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
                      cmd, jiffies, cmd->request->timeout / HZ,
                      ha->dpc_flags, cmd->result, cmd->allowed));
 
+       rval = qla4xxx_isp_check_reg(ha);
+       if (rval != QLA_SUCCESS) {
+               ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, 
exiting.\n");
+               return FAILED;
+       }
+
        /* FIXME: wait for hba to go online */
        stat = qla4xxx_reset_lun(ha, ddb_entry, cmd->device->lun);
        if (stat != QLA_SUCCESS) {
@@ -9305,6 +9337,7 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
        struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
        struct ddb_entry *ddb_entry = cmd->device->hostdata;
        int stat, ret;
+       int rval;
 
        if (!ddb_entry)
                return FAILED;
@@ -9322,6 +9355,12 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
                      ha->host_no, cmd, jiffies, cmd->request->timeout / HZ,
                      ha->dpc_flags, cmd->result, cmd->allowed));
 
+       rval = qla4xxx_isp_check_reg(ha);
+       if (rval != QLA_SUCCESS) {
+               ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, 
exiting.\n");
+               return FAILED;
+       }
+
        stat = qla4xxx_reset_target(ha, ddb_entry);
        if (stat != QLA_SUCCESS) {
                starget_printk(KERN_INFO, scsi_target(cmd->device),
@@ -9376,9 +9415,16 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
 {
        int return_status = FAILED;
        struct scsi_qla_host *ha;
+       int rval;
 
        ha = to_qla_host(cmd->device->host);
 
+       rval = qla4xxx_isp_check_reg(ha);
+       if (rval != QLA_SUCCESS) {
+               ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, 
exiting.\n");
+               return FAILED;
+       }
+
        if ((is_qla8032(ha) || is_qla8042(ha)) && ql4xdontresethba)
                qla4_83xx_set_idc_dontreset(ha);
 
-- 
1.8.3.1

Reply via email to