[SCSI] mpt2sas: Prevent sending command to FW while Host Reset
authorKashyap, Desai <kashyap.desai@lsi.com>
Thu, 20 Aug 2009 07:52:00 +0000 (13:22 +0530)
committerJames Bottomley <James.Bottomley@suse.de>
Sat, 5 Sep 2009 14:34:49 +0000 (09:34 -0500)
This patch renames the flag for indicating host reset from
ioc_reset_in_progress to shost_recovery. It also removes the spin locks
surrounding the setting of this flag, which are unnecessary.   Sanity checks on
the shost_recovery flag were added thru out the code so as to prevent sending
firmware commands during host reset.  Also, the setting of the shost state to
SHOST_RECOVERY was removed to prevent deadlocks, this is actually better
handled by the shost_recovery flag.

Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com>
Reviewed-by: Eric Moore <Eric.moore@lsi.com>
Cc: Stable Tree <stable@kernel.org>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/scsi/mpt2sas/mpt2sas_base.c
drivers/scsi/mpt2sas/mpt2sas_base.h
drivers/scsi/mpt2sas/mpt2sas_ctl.c
drivers/scsi/mpt2sas/mpt2sas_scsih.c
drivers/scsi/mpt2sas/mpt2sas_transport.c

index cc5a8da..1cfb503 100644 (file)
@@ -94,7 +94,7 @@ _base_fault_reset_work(struct work_struct *work)
        int rc;
 
        spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-       if (ioc->ioc_reset_in_progress)
+       if (ioc->shost_recovery)
                goto rearm_timer;
        spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 
@@ -3501,20 +3501,13 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
            __func__));
 
        spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-       if (ioc->ioc_reset_in_progress) {
+       if (ioc->shost_recovery) {
                spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
                printk(MPT2SAS_ERR_FMT "%s: busy\n",
                    ioc->name, __func__);
                return -EBUSY;
        }
-       ioc->ioc_reset_in_progress = 1;
        ioc->shost_recovery = 1;
-       if (ioc->shost->shost_state == SHOST_RUNNING) {
-               /* set back to SHOST_RUNNING in mpt2sas_scsih.c */
-               scsi_host_set_state(ioc->shost, SHOST_RECOVERY);
-               printk(MPT2SAS_INFO_FMT "putting controller into "
-                   "SHOST_RECOVERY\n", ioc->name);
-       }
        spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 
        _base_reset_handler(ioc, MPT2_IOC_PRE_RESET);
@@ -3534,7 +3527,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
            ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED")));
 
        spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-       ioc->ioc_reset_in_progress = 0;
+       ioc->shost_recovery = 0;
        spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 
        if (!r)
index 998a7b8..1582758 100644 (file)
@@ -432,7 +432,7 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
  * @fw_event_list: list of fw events
  * @aen_event_read_flag: event log was read
  * @broadcast_aen_busy: broadcast aen waiting to be serviced
- * @ioc_reset_in_progress: host reset in progress
+ * @shost_recovery: host reset in progress
  * @ioc_reset_in_progress_lock:
  * @ioc_link_reset_in_progress: phy/hard reset in progress
  * @ignore_loginfos: ignore loginfos during task managment
@@ -545,7 +545,6 @@ struct MPT2SAS_ADAPTER {
         /* misc flags */
        int             aen_event_read_flag;
        u8              broadcast_aen_busy;
-       u8              ioc_reset_in_progress;
        u8              shost_recovery;
        spinlock_t      ioc_reset_in_progress_lock;
        u8              ioc_link_reset_in_progress;
index 14e473d..c2a5101 100644 (file)
@@ -1963,7 +1963,6 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg)
 {
        enum block_state state;
        long ret = -EINVAL;
-       unsigned long flags;
 
        state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING :
            BLOCKING;
@@ -1989,13 +1988,8 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg)
                    !ioc)
                        return -ENODEV;
 
-               spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-               if (ioc->shost_recovery) {
-                       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock,
-                           flags);
+               if (ioc->shost_recovery)
                        return -EAGAIN;
-               }
-               spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 
                if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) {
                        uarg = arg;
@@ -2098,7 +2092,6 @@ _ctl_compat_mpt_command(struct file *file, unsigned cmd, unsigned long arg)
        struct mpt2_ioctl_command karg;
        struct MPT2SAS_ADAPTER *ioc;
        enum block_state state;
-       unsigned long flags;
 
        if (_IOC_SIZE(cmd) != sizeof(struct mpt2_ioctl_command32))
                return -EINVAL;
@@ -2113,13 +2106,8 @@ _ctl_compat_mpt_command(struct file *file, unsigned cmd, unsigned long arg)
        if (_ctl_verify_adapter(karg32.hdr.ioc_number, &ioc) == -1 || !ioc)
                return -ENODEV;
 
-       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-       if (ioc->shost_recovery) {
-               spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock,
-                   flags);
+       if (ioc->shost_recovery)
                return -EAGAIN;
-       }
-       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 
        memset(&karg, 0, sizeof(struct mpt2_ioctl_command));
        karg.hdr.ioc_number = karg32.hdr.ioc_number;
index 471c3b6..195f5e5 100644 (file)
@@ -1785,17 +1785,18 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun,
        u32 ioc_state;
        unsigned long timeleft;
        u8 VF_ID = 0;
-       unsigned long flags;
 
-       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-       if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED ||
-           ioc->shost_recovery) {
-               spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+       if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) {
+               printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n",
+                   __func__, ioc->name);
+               return;
+       }
+
+       if (ioc->shost_recovery) {
                printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
                    __func__, ioc->name);
                return;
        }
-       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 
        ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
        if (ioc_state & MPI2_DOORBELL_USED) {
@@ -2553,7 +2554,6 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
        Mpi2SCSIIORequest_t *mpi_request;
        u32 mpi_control;
        u16 smid;
-       unsigned long flags;
 
        scmd->scsi_done = done;
        sas_device_priv_data = scmd->device->hostdata;
@@ -2572,13 +2572,10 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
        }
 
        /* see if we are busy with task managment stuff */
-       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-       if (sas_target_priv_data->tm_busy ||
-           ioc->shost_recovery || ioc->ioc_link_reset_in_progress) {
-               spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+       if (sas_target_priv_data->tm_busy)
+               return SCSI_MLQUEUE_DEVICE_BUSY;
+       else if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress)
                return SCSI_MLQUEUE_HOST_BUSY;
-       }
-       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 
        if (scmd->sc_data_direction == DMA_FROM_DEVICE)
                mpi_control = MPI2_SCSIIO_CONTROL_READ;
@@ -3374,6 +3371,9 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
        if (!handle)
                return -1;
 
+       if (ioc->shost_recovery)
+               return -1;
+
        if ((mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
            MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) {
                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
@@ -3510,6 +3510,9 @@ _scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u16 handle)
        struct _sas_node *sas_expander;
        unsigned long flags;
 
+       if (ioc->shost_recovery)
+               return;
+
        spin_lock_irqsave(&ioc->sas_node_lock, flags);
        sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, handle);
        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
@@ -3681,6 +3684,8 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
                mutex_unlock(&ioc->tm_cmds.mutex);
                dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "issue target reset "
                    "done: handle(0x%04x)\n", ioc->name, device_handle));
+               if (ioc->shost_recovery)
+                       goto out;
        }
 
        /* SAS_IO_UNIT_CNTR - send REMOVE_DEVICE */
@@ -3846,6 +3851,8 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
                            "expander event\n", ioc->name));
                        return;
                }
+               if (ioc->shost_recovery)
+                       return;
                if (event_data->PHY[i].PhyStatus &
                    MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT)
                        continue;
@@ -5217,13 +5224,10 @@ _firmware_event_work(struct work_struct *work)
        }
        spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 
-       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
        if (ioc->shost_recovery) {
-               spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
                _scsih_fw_event_requeue(ioc, fw_event, 1000);
                return;
        }
-       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 
        switch (fw_event->event) {
        case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
@@ -5425,6 +5429,8 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
                        if (!sas_device)
                                continue;
                        _scsih_remove_device(ioc, sas_device->handle);
+                       if (ioc->shost_recovery)
+                               return;
                        goto retry_device_search;
                }
        }
@@ -5446,6 +5452,8 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
                        if (!expander_sibling)
                                continue;
                        _scsih_expander_remove(ioc, expander_sibling->handle);
+                       if (ioc->shost_recovery)
+                               return;
                        goto retry_expander_search;
                }
        }
index 686695b..a53086d 100644 (file)
@@ -140,11 +140,18 @@ _transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
        u32 device_info;
        u32 ioc_status;
 
+       if (ioc->shost_recovery) {
+               printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
+                   __func__, ioc->name);
+               return -EFAULT;
+       }
+
        if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
            MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+
                    ioc->name, __FILE__, __LINE__, __func__);
-               return -1;
+               return -ENXIO;
        }
 
        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
@@ -153,7 +160,7 @@ _transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
                printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)"
                    "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
                     __FILE__, __LINE__, __func__);
-               return -1;
+               return -EIO;
        }
 
        memset(identify, 0, sizeof(identify));
@@ -288,21 +295,17 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
        void *psge;
        u32 sgl_flags;
        u8 issue_reset = 0;
-       unsigned long flags;
        void *data_out = NULL;
        dma_addr_t data_out_dma;
        u32 sz;
        u64 *sas_address_le;
        u16 wait_state_count;
 
-       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-       if (ioc->ioc_reset_in_progress) {
-               spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+       if (ioc->shost_recovery) {
                printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
                    __func__, ioc->name);
                return -EFAULT;
        }
-       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 
        mutex_lock(&ioc->transport_cmds.mutex);
 
@@ -806,6 +809,12 @@ mpt2sas_transport_update_phy_link_change(struct MPT2SAS_ADAPTER *ioc,
        struct _sas_node *sas_node;
        struct _sas_phy *mpt2sas_phy;
 
+       if (ioc->shost_recovery) {
+               printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
+                       __func__, ioc->name);
+               return;
+       }
+
        spin_lock_irqsave(&ioc->sas_node_lock, flags);
        sas_node = _transport_sas_node_find_by_handle(ioc, handle);
        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
@@ -1025,7 +1034,6 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
        void *psge;
        u32 sgl_flags;
        u8 issue_reset = 0;
-       unsigned long flags;
        dma_addr_t dma_addr_in = 0;
        dma_addr_t dma_addr_out = 0;
        u16 wait_state_count;
@@ -1045,14 +1053,11 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
                return -EINVAL;
        }
 
-       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-       if (ioc->ioc_reset_in_progress) {
-               spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+       if (ioc->shost_recovery) {
                printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
                    __func__, ioc->name);
                return -EFAULT;
        }
-       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 
        rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
        if (rc)