diff options
Diffstat (limited to 'drivers/message')
| -rw-r--r-- | drivers/message/fusion/mptbase.c | 63 | ||||
| -rw-r--r-- | drivers/message/fusion/mptbase.h | 66 | ||||
| -rw-r--r-- | drivers/message/fusion/mptsas.c | 2 | ||||
| -rw-r--r-- | drivers/message/fusion/mptscsih.c | 3 | ||||
| -rw-r--r-- | drivers/message/fusion/mptscsih.h | 1 | 
5 files changed, 105 insertions, 30 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 7956a10f948..517621fa8bc 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -63,6 +63,8 @@  #ifdef CONFIG_MTRR  #include <asm/mtrr.h>  #endif +#include <linux/kthread.h> +#include <scsi/scsi_host.h>  #include "mptbase.h"  #include "lsi/mpi_log_fc.h" @@ -323,6 +325,32 @@ mpt_is_discovery_complete(MPT_ADAPTER *ioc)  	return rc;  } + +/** + *  mpt_remove_dead_ioc_func - kthread context to remove dead ioc + * @arg: input argument, used to derive ioc + * + * Return 0 if controller is removed from pci subsystem. + * Return -1 for other case. + */ +static int mpt_remove_dead_ioc_func(void *arg) +{ +	MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; +	struct pci_dev *pdev; + +	if ((ioc == NULL)) +		return -1; + +	pdev = ioc->pcidev; +	if ((pdev == NULL)) +		return -1; + +	pci_remove_bus_device(pdev); +	return 0; +} + + +  /**   *	mpt_fault_reset_work - work performed on workq after ioc fault   *	@work: input argument, used to derive ioc @@ -336,12 +364,45 @@ mpt_fault_reset_work(struct work_struct *work)  	u32		 ioc_raw_state;  	int		 rc;  	unsigned long	 flags; +	MPT_SCSI_HOST	*hd; +	struct task_struct *p;  	if (ioc->ioc_reset_in_progress || !ioc->active)  		goto out; +  	ioc_raw_state = mpt_GetIocState(ioc, 0); -	if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) { +	if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_MASK) { +		printk(MYIOC_s_INFO_FMT "%s: IOC is non-operational !!!!\n", +		    ioc->name, __func__); + +		/* +		 * Call mptscsih_flush_pending_cmds callback so that we +		 * flush all pending commands back to OS. +		 * This call is required to aovid deadlock at block layer. +		 * Dead IOC will fail to do diag reset,and this call is safe +		 * since dead ioc will never return any command back from HW. +		 */ +		hd = shost_priv(ioc->sh); +		ioc->schedule_dead_ioc_flush_running_cmds(hd); + +		/*Remove the Dead Host */ +		p = kthread_run(mpt_remove_dead_ioc_func, ioc, +				"mpt_dead_ioc_%d", ioc->id); +		if (IS_ERR(p))	{ +			printk(MYIOC_s_ERR_FMT +				"%s: Running mpt_dead_ioc thread failed !\n", +				ioc->name, __func__); +		} else { +			printk(MYIOC_s_WARN_FMT +				"%s: Running mpt_dead_ioc thread success !\n", +				ioc->name, __func__); +		} +		return; /* don't rearm timer */ +	} + +	if ((ioc_raw_state & MPI_IOC_STATE_MASK) +			== MPI_IOC_STATE_FAULT) {  		printk(MYIOC_s_WARN_FMT "IOC is in FAULT state (%04xh)!!!\n",  		       ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);  		printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n", diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index fe902338539..69ddabd5195 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -554,10 +554,47 @@ struct mptfc_rport_info  	u8		flags;  }; +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + +/* + * MPT_SCSI_HOST defines - Used by the IOCTL and the SCSI drivers + * Private to the driver. + */ + +#define MPT_HOST_BUS_UNKNOWN		(0xFF) +#define MPT_HOST_TOO_MANY_TM		(0x05) +#define MPT_HOST_NVRAM_INVALID		(0xFFFFFFFF) +#define MPT_HOST_NO_CHAIN		(0xFFFFFFFF) +#define MPT_NVRAM_MASK_TIMEOUT		(0x000000FF) +#define MPT_NVRAM_SYNC_MASK		(0x0000FF00) +#define MPT_NVRAM_SYNC_SHIFT		(8) +#define MPT_NVRAM_DISCONNECT_ENABLE	(0x00010000) +#define MPT_NVRAM_ID_SCAN_ENABLE	(0x00020000) +#define MPT_NVRAM_LUN_SCAN_ENABLE	(0x00040000) +#define MPT_NVRAM_TAG_QUEUE_ENABLE	(0x00080000) +#define MPT_NVRAM_WIDE_DISABLE		(0x00100000) +#define MPT_NVRAM_BOOT_CHOICE		(0x00200000) + +typedef enum { +	FC, +	SPI, +	SAS +} BUS_TYPE; + +typedef struct _MPT_SCSI_HOST { +	struct _MPT_ADAPTER		 *ioc; +	ushort			  sel_timeout[MPT_MAX_FC_DEVICES]; +	char			  *info_kbuf; +	long			  last_queue_full; +	u16			  spi_pending; +	struct list_head	  target_reset_list; +} MPT_SCSI_HOST; +  typedef void (*MPT_ADD_SGE)(void *pAddr, u32 flagslength, dma_addr_t dma_addr);  typedef void (*MPT_ADD_CHAIN)(void *pAddr, u8 next, u16 length,  		dma_addr_t dma_addr);  typedef void (*MPT_SCHEDULE_TARGET_RESET)(void *ioc); +typedef void (*MPT_FLUSH_RUNNING_CMDS)(MPT_SCSI_HOST *hd);  /*   *  Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS @@ -717,6 +754,7 @@ typedef struct _MPT_ADAPTER  	u8			 taskmgmt_quiesce_io;  	u8			 ioc_reset_in_progress;  	MPT_SCHEDULE_TARGET_RESET schedule_target_reset; +	MPT_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds;  	struct work_struct	 sas_persist_task;  	struct work_struct	 fc_setup_reset_work; @@ -830,19 +868,6 @@ typedef struct _MPT_LOCAL_REPLY {  	u32	pad;  } MPT_LOCAL_REPLY; -#define MPT_HOST_BUS_UNKNOWN		(0xFF) -#define MPT_HOST_TOO_MANY_TM		(0x05) -#define MPT_HOST_NVRAM_INVALID		(0xFFFFFFFF) -#define MPT_HOST_NO_CHAIN		(0xFFFFFFFF) -#define MPT_NVRAM_MASK_TIMEOUT		(0x000000FF) -#define MPT_NVRAM_SYNC_MASK		(0x0000FF00) -#define MPT_NVRAM_SYNC_SHIFT		(8) -#define MPT_NVRAM_DISCONNECT_ENABLE	(0x00010000) -#define MPT_NVRAM_ID_SCAN_ENABLE	(0x00020000) -#define MPT_NVRAM_LUN_SCAN_ENABLE	(0x00040000) -#define MPT_NVRAM_TAG_QUEUE_ENABLE	(0x00080000) -#define MPT_NVRAM_WIDE_DISABLE		(0x00100000) -#define MPT_NVRAM_BOOT_CHOICE		(0x00200000)  /* The TM_STATE variable is used to provide strict single threading of TM   * requests as well as communicate TM error conditions. @@ -851,21 +876,6 @@ typedef struct _MPT_LOCAL_REPLY {  #define	TM_STATE_IN_PROGRESS   (1)  #define	TM_STATE_ERROR	       (2) -typedef enum { -	FC, -	SPI, -	SAS -} BUS_TYPE; - -typedef struct _MPT_SCSI_HOST { -	MPT_ADAPTER		 *ioc; -	ushort			  sel_timeout[MPT_MAX_FC_DEVICES]; -	char 			  *info_kbuf; -	long			  last_queue_full; -	u16			  spi_pending; -	struct list_head	  target_reset_list; -} MPT_SCSI_HOST; -  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/  /*   *	More Dynamic Multi-Pathing stuff... diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 73229ff9caf..d21924ba4b1 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -5147,6 +5147,8 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)  	ioc->TaskCtx = mptsasTaskCtx;  	ioc->InternalCtx = mptsasInternalCtx;  	ioc->schedule_target_reset = &mptsas_schedule_target_reset; +	ioc->schedule_dead_ioc_flush_running_cmds = +				&mptscsih_flush_running_cmds;  	/*  Added sanity check on readiness of the MPT adapter.  	 */  	if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) { diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index ce61a576976..de8cf92d861 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1024,7 +1024,7 @@ out:   *   *	Must be called while new I/Os are being queued.   */ -static void +void  mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)  {  	MPT_ADAPTER *ioc = hd->ioc; @@ -1055,6 +1055,7 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)  		sc->scsi_done(sc);  	}  } +EXPORT_SYMBOL(mptscsih_flush_running_cmds);  /*   *	mptscsih_search_running_cmds - Delete any commands associated diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 45a5ff3eff6..43e75ff3992 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -135,3 +135,4 @@ extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);  extern struct device_attribute *mptscsih_host_attrs[];  extern struct scsi_cmnd	*mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);  extern void mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code); +extern void mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd);  |