mpt2sas: Power cycling cascaded expanders causes kernel panic
PATCH 1/6 mpt2sas: Power cycling cascaded expanders causes kernel panic
Code cleanup of the host reset handling of the driver, and fix host plug work thread deadlocks, and kernel panics.
Summary of the changes:
(1) removed ioc->ioc_reset_in_progress flag, replaced with ioc->shost_recovery.
(2) removed the spin lock around reading ioc->shost_recovery.
(3) removed changing shost state during host reset handling; such as SHOST_RECOVERY
(4) moved rescanning the devices, updating handles, and deleting not responding devices to the same contents at the host reset handling.
(5) return SCSI_MLQUEUE_DEVICE_BUSY from _qcmd when sas_target_priv_data->tm_busy is set
(6) set SDEV_RUNNING from contents of the interrupt, instead of work threads
(7) when there is a failure during _scsih_expander_add, need to call mpt2sas_transport_port_remove to properly tear down the port.
---
---
drivers/scsi/mpt2sas/mpt2sas_base.c +7 -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);
@@ -3465,20 +3465,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 );
@@ -3493,12 +3486,16 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, sleep_flag);if (!r)_base_reset_handler (ioc,MPT2_IOC_DONE_RESET ); + out:dtmprintk (ioc,printk (MPT2SAS_DEBUG_FMT "%s: %s\n" , 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) +_base_reset_handler (ioc,MPT2_IOC_RUNNING );return r; }
drivers/scsi/mpt2sas/mpt2sas_base.h +3 -3
@@ -119,6 +119,7 @@#define MPT2_IOC_PRE_RESET 1/* prior to host reset */ #define MPT2_IOC_AFTER_RESET 2/* just after host reset */ #define MPT2_IOC_DONE_RESET 3/* links re-initialized */ +#define MPT2_IOC_RUNNING 4/* shost running */ /* * logging format
@@ -431,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
@@ -544,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;
@@ -796,7 +796,7 @@ int mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev);int mpt2sas_transport_add_expander_phy (struct MPT2SAS_ADAPTER *ioc,struct _sas_phy *mpt2sas_phy,Mpi2ExpanderPage1_t expander_pg1,struct device *parent_dev); -void mpt2sas_transport_update_phy_link_change (struct MPT2SAS_ADAPTER *ioc,u16 handle, +void mpt2sas_transport_update_links (struct MPT2SAS_ADAPTER *ioc,u16 handle,u16 attached_handle,u8 phy_number,u8 link_rate);extern struct sas_function_template mpt2sas_transport_functions;extern struct scsi_transport_template *mpt2sas_transport_template;
drivers/scsi/mpt2sas/mpt2sas_config.c +16 -19
@@ -236,7 +236,6 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_tMpi2ConfigRequest_t *config_request;int r;u8 retry_count; -u8 issue_reset;u16 wait_state_count;if (ioc->config_cmds.status !=MPT2_CMD_NOT_USED ) {
@@ -247,6 +246,12 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t retry_count =0 ; retry_config: +if (retry_count) { +if (retry_count >2 )/* attempt only 2 retries */ +return -EFAULT ; +printk (MPT2SAS_INFO_FMT "%s: attempting retry (%d)\n" , + ioc->name, __func__, retry_count); + } wait_state_count =0 ; ioc_state =mpt2sas_base_get_iocstate (ioc,1 );while (ioc_state !=MPI2_IOC_STATE_OPERATIONAL ) {
@@ -292,31 +297,23 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t ioc->name, __func__);_debug_dump_mf (mpi_request,sizeof (Mpi2ConfigRequest_t)/4 ); -if (!(ioc->config_cmds.status &MPT2_CMD_RESET )) - issue_reset =1 ; - goto issue_host_reset; + retry_count++; +if ((ioc->shost_recovery) || + (ioc->config_cmds.status &MPT2_CMD_RESET )) + goto retry_config; +mpt2sas_base_hard_reset_handler (ioc,CAN_SLEEP , +FORCE_BIG_HAMMER ); + goto retry_config; } +if (ioc->config_cmds.status &MPT2_CMD_REPLY_VALID )memcpy (mpi_reply, ioc->config_cmds.reply,sizeof (Mpi2ConfigReply_t));if (retry_count) -printk (MPT2SAS_INFO_FMT "%s: retry completed!!\n" , - ioc->name, __func__); +printk (MPT2SAS_INFO_FMT "%s: retry (%d) completed!!\n" , + ioc->name, __func__, retry_count); ioc->config_cmds.status =MPT2_CMD_NOT_USED ;return r; - - issue_host_reset: -if (issue_reset) -mpt2sas_base_hard_reset_handler (ioc,CAN_SLEEP , -FORCE_BIG_HAMMER ); - ioc->config_cmds.status =MPT2_CMD_NOT_USED ; -if (!retry_count) { -printk (MPT2SAS_INFO_FMT "%s: attempting retry\n" , - ioc->name, __func__); - retry_count++; - goto retry_config; - } -return -EFAULT ; }/**
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_ctl.h +0 -0
drivers/scsi/mpt2sas/mpt2sas_debug.h +0 -0
drivers/scsi/mpt2sas/mpt2sas_scsih.c +113 -147
439 lines not on this page · raw message
drivers/scsi/mpt2sas/mpt2sas_transport.c +19 -14
@@ -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);
@@ -789,7 +792,7 @@ mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy }/** -* mpt2sas_transport_update_phy_link_change - refreshing phy link changes and attached devices +* mpt2sas_transport_update_links - refreshing phy link changes * @ioc: per adapter object * @handle: handle to sas_host or expander * @attached_handle: attached device handle
@@ -799,13 +802,19 @@ mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy* Returns nothing. */ void -mpt2sas_transport_update_phy_link_change (struct MPT2SAS_ADAPTER *ioc, +mpt2sas_transport_update_links (struct MPT2SAS_ADAPTER *ioc,u16 handle,u16 attached_handle,u8 phy_number,u8 link_rate) {unsigned long flags;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)
James Bottomley
maintainerQuoted 11 lines · Desai
Code cleanup of the host reset handling of the driver, and fix host plug work thread deadlocks, and kernel panics.
Summary of the changes:
(1) removed
ioc->ioc_reset_in_progressflag, replaced withioc->shost_recovery.
(2) removed the spin lock around readingioc->shost_recovery.
(3) removed changing shost state during host reset handling; such asSHOST_RECOVERY
(4) moved rescanning the devices, updating handles, and deleting not responding devices to the same contents at the host reset handling.
(5) returnSCSI_MLQUEUE_DEVICE_BUSYfrom_qcmdwhensas_target_priv_data->tm_busyis set
(6) setSDEV_RUNNINGfrom contents of the interrupt, instead of work threads
(7) when there is a failure during_scsih_expander_add, need to callmpt2sas_transport_port_removeto properly tear down the port.
Will you please *not* do this. A kernel panic fix should be completely separate from code cleanups (primarily because it will likely need backporting to stable kernels). The rule is one patch per functional change (code cleanups, since they technically should have no functional changes, can be in a single patch).
Could we have a pointer to the panic and an indication whether backporting to stable is necessary?
James