mpt2sas: [Resend] Prevent sending command to FW while Host Reset
PATCH 2/7 mpt2sas: [Resend] Prevent sending command to FW while Host Reset
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 <[email protected]>
Reviewed-by Eric Moore <[email protected]>
---
drivers/scsi/mpt2sas/mpt2sas_base.c +3 -10
@@ -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)
drivers/scsi/mpt2sas/mpt2sas_base.h +1 -2
@@ -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;
drivers/scsi/mpt2sas/mpt2sas_ctl.c +2 -14
@@ -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;
drivers/scsi/mpt2sas/mpt2sas_scsih.c +24 -16
@@ -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; } }
drivers/scsi/mpt2sas/mpt2sas_transport.c +17 -12
@@ -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)