diff options
Diffstat (limited to 'drivers/message/fusion')
| -rw-r--r-- | drivers/message/fusion/Makefile | 2 | ||||
| -rw-r--r-- | drivers/message/fusion/lsi/mpi_cnfg.h | 2 | ||||
| -rw-r--r-- | drivers/message/fusion/lsi/mpi_ioc.h | 3 | ||||
| -rw-r--r-- | drivers/message/fusion/lsi/mpi_log_fc.h | 4 | ||||
| -rw-r--r-- | drivers/message/fusion/lsi/mpi_log_sas.h | 16 | ||||
| -rw-r--r-- | drivers/message/fusion/mptbase.c | 173 | ||||
| -rw-r--r-- | drivers/message/fusion/mptbase.h | 73 | ||||
| -rw-r--r-- | drivers/message/fusion/mptctl.c | 18 | ||||
| -rw-r--r-- | drivers/message/fusion/mptfc.c | 22 | ||||
| -rw-r--r-- | drivers/message/fusion/mptlan.h | 1 | ||||
| -rw-r--r-- | drivers/message/fusion/mptsas.c | 92 | ||||
| -rw-r--r-- | drivers/message/fusion/mptscsih.c | 143 | ||||
| -rw-r--r-- | drivers/message/fusion/mptscsih.h | 5 | ||||
| -rw-r--r-- | drivers/message/fusion/mptspi.c | 36 | 
14 files changed, 337 insertions, 253 deletions
diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile index 95c9532cb07..d182a24b319 100644 --- a/drivers/message/fusion/Makefile +++ b/drivers/message/fusion/Makefile @@ -2,7 +2,7 @@  # enable verbose logging  # CONFIG_FUSION_LOGGING needs to be enabled in Kconfig -#EXTRA_CFLAGS += -DMPT_DEBUG_VERBOSE +#ccflags-y := -DMPT_DEBUG_VERBOSE  #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h index 013c7d88194..d9bcfba6b04 100644 --- a/drivers/message/fusion/lsi/mpi_cnfg.h +++ b/drivers/message/fusion/lsi/mpi_cnfg.h @@ -583,6 +583,7 @@ typedef struct _MSG_CONFIG_REPLY  #define MPI_MANUFACTPAGE_DEVID_SAS1066E             (0x005A)  #define MPI_MANUFACTPAGE_DEVID_SAS1068              (0x0054)  #define MPI_MANUFACTPAGE_DEVID_SAS1068E             (0x0058) +#define MPI_MANUFACTPAGE_DEVID_SAS1068_820XELP      (0x0059)  #define MPI_MANUFACTPAGE_DEVID_SAS1078              (0x0062) @@ -2593,6 +2594,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0  #define MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE              (0x03)  #define MPI_SAS_IOUNIT0_RATE_1_5                            (0x08)  #define MPI_SAS_IOUNIT0_RATE_3_0                            (0x09) +#define MPI_SAS_IOUNIT0_RATE_6_0                            (0x0A)  /* see mpi_sas.h for values for SAS IO Unit Page 0 ControllerPhyDeviceInfo values */ diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h index 8faa4fab7b8..19fb21b8f0c 100644 --- a/drivers/message/fusion/lsi/mpi_ioc.h +++ b/drivers/message/fusion/lsi/mpi_ioc.h @@ -841,6 +841,7 @@ typedef struct _EVENT_DATA_SAS_PHY_LINK_STATUS  #define MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE         (0x03)  #define MPI_EVENT_SAS_PLS_LR_RATE_1_5                       (0x08)  #define MPI_EVENT_SAS_PLS_LR_RATE_3_0                       (0x09) +#define MPI_EVENT_SAS_PLS_LR_RATE_6_0                       (0x0A)  /* SAS Discovery Event data */ @@ -856,7 +857,7 @@ typedef struct _EVENT_DATA_SAS_DISCOVERY  #define MPI_EVENT_SAS_DSCVRY_PHY_BITS_MASK                  (0xFFFF0000)  #define MPI_EVENT_SAS_DSCVRY_PHY_BITS_SHIFT                 (16) -/* SAS Discovery Errror Event data */ +/* SAS Discovery Error Event data */  typedef struct _EVENT_DATA_DISCOVERY_ERROR  { diff --git a/drivers/message/fusion/lsi/mpi_log_fc.h b/drivers/message/fusion/lsi/mpi_log_fc.h index face6e7acc7..03be8b21770 100644 --- a/drivers/message/fusion/lsi/mpi_log_fc.h +++ b/drivers/message/fusion/lsi/mpi_log_fc.h @@ -38,8 +38,8 @@ typedef enum _MpiIocLogInfoFc  {      MPI_IOCLOGINFO_FC_INIT_BASE                     = 0x20000000,      MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME = 0x20000001, /* received an out of order frame - unsupported */ -    MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primative */ -    MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME   = 0x20000003, /* Bad Rx Frame, bad end of frame primative */ +    MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primitive */ +    MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME   = 0x20000003, /* Bad Rx Frame, bad end of frame primitive */      MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN           = 0x20000004, /* Bad Rx Frame, overrun */      MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER           = 0x20000005, /* Other errors caught by IOC which require retries */      MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD       = 0x20000006, /* Main processor could not initialize sub-processor */ diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h index 691620dbedd..f62960b5d52 100644 --- a/drivers/message/fusion/lsi/mpi_log_sas.h +++ b/drivers/message/fusion/lsi/mpi_log_sas.h @@ -56,9 +56,9 @@  #define IOP_LOGINFO_CODE_FWUPLOAD_NO_FLASH_AVAILABLE         (0x0003E000) /* Tried to upload from flash, but there is none */  #define IOP_LOGINFO_CODE_FWUPLOAD_UNKNOWN_IMAGE_TYPE         (0x0003E001) /* ImageType field contents were invalid */  #define IOP_LOGINFO_CODE_FWUPLOAD_WRONG_IMAGE_SIZE           (0x0003E002) /* ImageSize field in TCSGE was bad/offset in MfgPg 4 was wrong */ -#define IOP_LOGINFO_CODE_FWUPLOAD_ENTIRE_FLASH_UPLOAD_FAILED (0x0003E003) /* Error occured while attempting to upload the entire flash */ -#define IOP_LOGINFO_CODE_FWUPLOAD_REGION_UPLOAD_FAILED       (0x0003E004) /* Error occured while attempting to upload single flash region */ -#define IOP_LOGINFO_CODE_FWUPLOAD_DMA_FAILURE                (0x0003E005) /* Problem occured while DMAing FW to host memory */ +#define IOP_LOGINFO_CODE_FWUPLOAD_ENTIRE_FLASH_UPLOAD_FAILED (0x0003E003) /* Error occurred while attempting to upload the entire flash */ +#define IOP_LOGINFO_CODE_FWUPLOAD_REGION_UPLOAD_FAILED       (0x0003E004) /* Error occurred while attempting to upload single flash region */ +#define IOP_LOGINFO_CODE_FWUPLOAD_DMA_FAILURE                (0x0003E005) /* Problem occurred while DMAing FW to host memory */  #define IOP_LOGINFO_CODE_DIAG_MSG_ERROR                      (0x00040000) /* Error handling diag msg - or'd with diag status */ @@ -187,8 +187,8 @@  #define PL_LOGINFO_SUB_CODE_BREAK_ON_INCOMPLETE_BREAK_RCVD   (0x00005000)  #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE          (0x00200000) /* Can't get SMP Frame */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR             (0x00200010) /* Error occured on SMP Read */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR            (0x00200020) /* Error occured on SMP Write */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR             (0x00200010) /* Error occurred on SMP Read */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR            (0x00200020) /* Error occurred on SMP Write */  #define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL      (0x00200040) /* Encl Mgmt services not available for this WWID */  #define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED    (0x00200050) /* Address Mode not suppored */  #define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM               (0x00200060) /* Invalid Slot Number in SEP Msg */ @@ -207,8 +207,8 @@  #define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE           (0x00200103) /* SEP NACK'd, it is busy */  #define PL_LOGINFO_DA_SEP_DID_NOT_RECEIVE_ACK                (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */  #define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM              (0x00200105) /* SEP stopped or sent bad chksum in Hdr */ -#define PL_LOGINFO_DA_SEP_STOP_ON_DATA                       (0x00200106) /* SEP stopped while transfering data */ -#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA                 (0x00200107) /* SEP stopped while transfering sense data */ +#define PL_LOGINFO_DA_SEP_STOP_ON_DATA                       (0x00200106) /* SEP stopped while transferring data */ +#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA                 (0x00200107) /* SEP stopped while transferring sense data */  #define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1          (0x00200108) /* SEP returned unknown scsi status */  #define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2          (0x00200109) /* SEP returned unknown scsi status */  #define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP            (0x0020010A) /* SEP returned bad chksum after STOP */ @@ -268,7 +268,7 @@  /* Compatibility Error : IR Disabled */  #define IR_LOGINFO_COMPAT_ERROR_RAID_DISABLED                  (0x00010030) -/* Compatibility Error : Inquiry Comand failed */ +/* Compatibility Error : Inquiry Command failed */  #define IR_LOGINFO_COMPAT_ERROR_INQUIRY_FAILED                 (0x00010031)  /* Compatibility Error : Device not direct access device */  #define IR_LOGINFO_COMPAT_ERROR_NOT_DIRECT_ACCESS              (0x00010032) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 3e57b61ca44..ebc0af7d769 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" @@ -83,19 +85,18 @@ MODULE_VERSION(my_VERSION);  static int mpt_msi_enable_spi;  module_param(mpt_msi_enable_spi, int, 0); -MODULE_PARM_DESC(mpt_msi_enable_spi, " Enable MSI Support for SPI \ -		controllers (default=0)"); +MODULE_PARM_DESC(mpt_msi_enable_spi, +		 " Enable MSI Support for SPI controllers (default=0)");  static int mpt_msi_enable_fc;  module_param(mpt_msi_enable_fc, int, 0); -MODULE_PARM_DESC(mpt_msi_enable_fc, " Enable MSI Support for FC \ -		controllers (default=0)"); +MODULE_PARM_DESC(mpt_msi_enable_fc, +		 " Enable MSI Support for FC controllers (default=0)");  static int mpt_msi_enable_sas;  module_param(mpt_msi_enable_sas, int, 0); -MODULE_PARM_DESC(mpt_msi_enable_sas, " Enable MSI Support for SAS \ -		controllers (default=0)"); - +MODULE_PARM_DESC(mpt_msi_enable_sas, +		 " Enable MSI Support for SAS controllers (default=0)");  static int mpt_channel_mapping;  module_param(mpt_channel_mapping, int, 0); @@ -105,17 +106,17 @@ static int mpt_debug_level;  static int mpt_set_debug_level(const char *val, struct kernel_param *kp);  module_param_call(mpt_debug_level, mpt_set_debug_level, param_get_int,  		  &mpt_debug_level, 0600); -MODULE_PARM_DESC(mpt_debug_level, " debug level - refer to mptdebug.h \ -	- (default=0)"); +MODULE_PARM_DESC(mpt_debug_level, +		 " debug level - refer to mptdebug.h - (default=0)");  int mpt_fwfault_debug;  EXPORT_SYMBOL(mpt_fwfault_debug);  module_param(mpt_fwfault_debug, int, 0600); -MODULE_PARM_DESC(mpt_fwfault_debug, "Enable detection of Firmware fault" -	" and halt Firmware on fault - (default=0)"); - +MODULE_PARM_DESC(mpt_fwfault_debug, +		 "Enable detection of Firmware fault and halt Firmware on fault - (default=0)"); -static char	MptCallbacksName[MPT_MAX_PROTOCOL_DRIVERS][50]; +static char	MptCallbacksName[MPT_MAX_PROTOCOL_DRIVERS] +				[MPT_MAX_CALLBACKNAME_LEN+1];  #ifdef MFCNT  static int mfcounter = 0; @@ -325,6 +326,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_stop_and_remove_bus_device_locked(pdev); +	return 0; +} + + +  /**   *	mpt_fault_reset_work - work performed on workq after ioc fault   *	@work: input argument, used to derive ioc @@ -338,12 +365,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", @@ -658,8 +718,8 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass, char *func_name)  			MptDriverClass[cb_idx] = dclass;  			MptEvHandlers[cb_idx] = NULL;  			last_drv_idx = cb_idx; -			memcpy(MptCallbacksName[cb_idx], func_name, -			    strlen(func_name) > 50 ? 50 : strlen(func_name)); +			strlcpy(MptCallbacksName[cb_idx], func_name, +				MPT_MAX_CALLBACKNAME_LEN+1);  			break;  		}  	} @@ -977,7 +1037,7 @@ mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)  		goto out;  	/* signature to know if this mf is freed */  	mf->u.frame.linkage.arg1 = cpu_to_le32(0xdeadbeaf); -	list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ); +	list_add(&mf->u.frame.linkage.list, &ioc->FreeQ);  #ifdef MFCNT  	ioc->mfcnt--;  #endif @@ -1593,7 +1653,6 @@ mpt_mapresources(MPT_ADAPTER *ioc)  	unsigned long	 port;  	u32		 msize;  	u32		 psize; -	u8		 revision;  	int		 r = -ENODEV;  	struct pci_dev *pdev; @@ -1607,11 +1666,9 @@ mpt_mapresources(MPT_ADAPTER *ioc)  	if (pci_request_selected_regions(pdev, ioc->bars, "mpt")) {  		printk(MYIOC_s_ERR_FMT "pci_request_selected_regions() with "  		    "MEM failed\n", ioc->name); -		return r; +		goto out_pci_disable_device;  	} -	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); -  	if (sizeof(dma_addr_t) > 4) {  		const uint64_t required_mask = dma_get_required_mask  		    (&pdev->dev); @@ -1633,8 +1690,7 @@ mpt_mapresources(MPT_ADAPTER *ioc)  		} else {  			printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",  			    ioc->name, pci_name(pdev)); -			pci_release_selected_regions(pdev, ioc->bars); -			return r; +			goto out_pci_release_region;  		}  	} else {  		if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) @@ -1647,8 +1703,7 @@ mpt_mapresources(MPT_ADAPTER *ioc)  		} else {  			printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",  			    ioc->name, pci_name(pdev)); -			pci_release_selected_regions(pdev, ioc->bars); -			return r; +			goto out_pci_release_region;  		}  	} @@ -1678,8 +1733,8 @@ mpt_mapresources(MPT_ADAPTER *ioc)  	if (mem == NULL) {  		printk(MYIOC_s_ERR_FMT ": ERROR - Unable to map adapter"  			" memory!\n", ioc->name); -		pci_release_selected_regions(pdev, ioc->bars); -		return -EINVAL; +		r = -EINVAL; +		goto out_pci_release_region;  	}  	ioc->memmap = mem;  	dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %llx\n", @@ -1693,6 +1748,12 @@ mpt_mapresources(MPT_ADAPTER *ioc)  	ioc->pio_chip = (SYSIF_REGS __iomem *)port;  	return 0; + +out_pci_release_region: +	pci_release_selected_regions(pdev, ioc->bars); +out_pci_disable_device: +	pci_disable_device(pdev); +	return r;  }  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1719,7 +1780,6 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)  	MPT_ADAPTER	*ioc;  	u8		 cb_idx;  	int		 r = -ENODEV; -	u8		 revision;  	u8		 pcixcmd;  	static int	 mpt_ids = 0;  #ifdef CONFIG_PROC_FS @@ -1827,8 +1887,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)  	dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",  	    ioc->name, &ioc->facts, &ioc->pfacts[0])); -	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); -	mpt_get_product_name(pdev->vendor, pdev->device, revision, ioc->prod_name); +	mpt_get_product_name(pdev->vendor, pdev->device, pdev->revision, +			     ioc->prod_name);  	switch (pdev->device)  	{ @@ -1843,7 +1903,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)  		break;  	case MPI_MANUFACTPAGE_DEVICEID_FC929X: -		if (revision < XL_929) { +		if (pdev->revision < XL_929) {  			/* 929X Chip Fix. Set Split transactions level  		 	* for PCIX. Set MOST bits to zero.  		 	*/ @@ -1874,7 +1934,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)  		/* 1030 Chip Fix. Disable Split transactions  		 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).  		 */ -		if (revision < C0_1030) { +		if (pdev->revision < C0_1030) {  			pci_read_config_byte(pdev, 0x6a, &pcixcmd);  			pcixcmd &= 0x8F;  			pci_write_config_byte(pdev, 0x6a, pcixcmd); @@ -3435,7 +3495,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)   *	If memory has already been allocated, the same (cached) value   *	is returned.   * - *	Return 0 if successfull, or non-zero for failure + *	Return 0 if successful, or non-zero for failure   **/  int  mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size) @@ -6415,8 +6475,20 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)  			pReq->Action, ioc->mptbase_cmds.status, timeleft));  		if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)  			goto out; -		if (!timeleft) +		if (!timeleft) { +			spin_lock_irqsave(&ioc->taskmgmt_lock, flags); +			if (ioc->ioc_reset_in_progress) { +				spin_unlock_irqrestore(&ioc->taskmgmt_lock, +					flags); +				printk(MYIOC_s_INFO_FMT "%s: host reset in" +					" progress mpt_config timed out.!!\n", +					__func__, ioc->name); +				mutex_unlock(&ioc->mptbase_cmds.mutex); +				return -EFAULT; +			} +			spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);  			issue_hard_reset = 1; +		}  		goto out;  	} @@ -6584,7 +6656,7 @@ static int mpt_summary_proc_show(struct seq_file *m, void *v)  static int mpt_summary_proc_open(struct inode *inode, struct file *file)  { -	return single_open(file, mpt_summary_proc_show, PDE(inode)->data); +	return single_open(file, mpt_summary_proc_show, PDE_DATA(inode));  }  static const struct file_operations mpt_summary_proc_fops = { @@ -6733,7 +6805,7 @@ static int mpt_iocinfo_proc_show(struct seq_file *m, void *v)  static int mpt_iocinfo_proc_open(struct inode *inode, struct file *file)  { -	return single_open(file, mpt_iocinfo_proc_show, PDE(inode)->data); +	return single_open(file, mpt_iocinfo_proc_show, PDE_DATA(inode));  }  static const struct file_operations mpt_iocinfo_proc_fops = { @@ -6932,7 +7004,7 @@ EXPORT_SYMBOL(mpt_halt_firmware);   *	Message Unit Reset - instructs the IOC to reset the Reply Post and   *	Free FIFO's. All the Message Frames on Reply Free FIFO are discarded.   *	All posted buffers are freed, and event notification is turned off. - *	IOC doesnt reply to any outstanding request. This will transfer IOC + *	IOC doesn't reply to any outstanding request. This will transfer IOC   *	to READY state.   **/  int @@ -7130,7 +7202,18 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)  	spin_lock_irqsave(&ioc->taskmgmt_lock, flags);  	if (ioc->ioc_reset_in_progress) {  		spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); -		return 0; +		ioc->wait_on_reset_completion = 1; +		do { +			ssleep(1); +		} while (ioc->ioc_reset_in_progress == 1); +		ioc->wait_on_reset_completion = 0; +		return ioc->reset_status; +	} +	if (ioc->wait_on_reset_completion) { +		spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); +		rc = 0; +		time_count = jiffies; +		goto exit;  	}  	ioc->ioc_reset_in_progress = 1;  	if (ioc->alt_ioc) @@ -7167,6 +7250,7 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)  	ioc->ioc_reset_in_progress = 0;  	ioc->taskmgmt_quiesce_io = 0;  	ioc->taskmgmt_in_progress = 0; +	ioc->reset_status = rc;  	if (ioc->alt_ioc) {  		ioc->alt_ioc->ioc_reset_in_progress = 0;  		ioc->alt_ioc->taskmgmt_quiesce_io = 0; @@ -7182,7 +7266,7 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)  					ioc->alt_ioc, MPT_IOC_POST_RESET);  		}  	} - +exit:  	dtmprintk(ioc,  	    printk(MYIOC_s_DEBUG_FMT  		"HardResetHandler: completed (%d seconds): %s\n", ioc->name, @@ -7418,7 +7502,12 @@ mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply)  		case MPI_EVENT_SAS_PLS_LR_RATE_3_0:  			snprintf(evStr, EVENT_DESCR_STR_SZ,  			   "SAS PHY Link Status: Phy=%d:" -			   " Rate 3.0 Gpbs",PhyNumber); +			   " Rate 3.0 Gbps", PhyNumber); +			break; +		case MPI_EVENT_SAS_PLS_LR_RATE_6_0: +			snprintf(evStr, EVENT_DESCR_STR_SZ, +			   "SAS PHY Link Status: Phy=%d:" +			   " Rate 6.0 Gbps", PhyNumber);  			break;  		default:  			snprintf(evStr, EVENT_DESCR_STR_SZ, @@ -7900,7 +7989,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)  		    "Owner", 					/* 15h */  		"Open Transmit DMA Abort",			/* 16h */  		"IO Device Missing Delay Retry",		/* 17h */ -		"IO Cancelled Due to Recieve Error",		/* 18h */ +		"IO Cancelled Due to Receive Error",		/* 18h */  		NULL,						/* 19h */  		NULL,						/* 1Ah */  		NULL,						/* 1Bh */ @@ -7977,7 +8066,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)  		NULL,						/* 2Eh */  		NULL,						/* 2Fh */  		"Compatibility Error: IR Disabled",		/* 30h */ -		"Compatibility Error: Inquiry Comand Failed",	/* 31h */ +		"Compatibility Error: Inquiry Command Failed",	/* 31h */  		"Compatibility Error: Device not Direct Access "  		    "Device ",					/* 32h */  		"Compatibility Error: Removable Device Found",	/* 33h */ diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index f71f2294847..76c05bc24cb 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -76,8 +76,8 @@  #define COPYRIGHT	"Copyright (c) 1999-2008 " MODULEAUTHOR  #endif -#define MPT_LINUX_VERSION_COMMON	"3.04.17" -#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.17" +#define MPT_LINUX_VERSION_COMMON	"3.04.20" +#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.20"  #define WHAT_MAGIC_STRING		"@" "(" "#" ")"  #define show_mptmod_ver(s,ver)  \ @@ -89,6 +89,7 @@   */  #define MPT_MAX_ADAPTERS		18  #define MPT_MAX_PROTOCOL_DRIVERS	16 +#define MPT_MAX_CALLBACKNAME_LEN	49  #define MPT_MAX_BUS			1	/* Do not change */  #define MPT_MAX_FC_DEVICES		255  #define MPT_MAX_SCSI_DEVICES		16 @@ -554,10 +555,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 @@ -716,7 +754,10 @@ typedef struct _MPT_ADAPTER  	int			 taskmgmt_in_progress;  	u8			 taskmgmt_quiesce_io;  	u8			 ioc_reset_in_progress; +	u8			 reset_status; +	u8			 wait_on_reset_completion;  	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 +871,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 +879,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/mptctl.c b/drivers/message/fusion/mptctl.c index a3856ed90ae..8a050e88568 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -978,7 +978,7 @@ retry_wait:  	ReplyMsg = (pFWDownloadReply_t)iocp->ioctl_cmds.reply;  	iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK;  	if (iocstat == MPI_IOCSTATUS_SUCCESS) { -		printk(MYIOC_s_INFO_FMT "F/W update successfull!\n", iocp->name); +		printk(MYIOC_s_INFO_FMT "F/W update successful!\n", iocp->name);  		return 0;  	} else if (iocstat == MPI_IOCSTATUS_INVALID_FUNCTION) {  		printk(MYIOC_s_WARN_FMT "Hmmm...  F/W download not supported!?!\n", @@ -1243,7 +1243,6 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)  	int			iocnum;  	unsigned int		port;  	int			cim_rev; -	u8			revision;  	struct scsi_device 	*sdev;  	VirtDevice		*vdevice; @@ -1307,16 +1306,17 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)  	else  		karg->adapterType = MPT_IOCTL_INTERFACE_SCSI; -	if (karg->hdr.port > 1) +	if (karg->hdr.port > 1) { +		kfree(karg);  		return -EINVAL; +	}  	port = karg->hdr.port;  	karg->port = port;  	pdev = (struct pci_dev *) ioc->pcidev;  	karg->pciId = pdev->device; -	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); -	karg->hwRev = revision; +	karg->hwRev = pdev->revision;  	karg->subSystemDevice = pdev->subsystem_device;  	karg->subSystemVendor = pdev->subsystem_vendor; @@ -2398,7 +2398,7 @@ done_free_mem:  	}  	/* mf is null if command issued successfully -	 * otherwise, failure occured after mf acquired. +	 * otherwise, failure occurred after mf acquired.  	 */  	if (mf)  		mpt_free_msg_frame(ioc, mf); @@ -2432,9 +2432,9 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)  	int			rc, cim_rev;  	ToolboxIstwiReadWriteRequest_t	*IstwiRWRequest;  	MPT_FRAME_HDR		*mf = NULL; -	MPIHeader_t		*mpi_hdr;  	unsigned long		timeleft;  	int			retval; +	u32			msgcontext;  	/* Reset long to int. Should affect IA64 and SPARC only  	 */ @@ -2581,11 +2581,11 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)  	}  	IstwiRWRequest = (ToolboxIstwiReadWriteRequest_t *)mf; -	mpi_hdr = (MPIHeader_t *) mf; +	msgcontext = IstwiRWRequest->MsgContext;  	memset(IstwiRWRequest,0,sizeof(ToolboxIstwiReadWriteRequest_t)); +	IstwiRWRequest->MsgContext = msgcontext;  	IstwiRWRequest->Function = MPI_FUNCTION_TOOLBOX;  	IstwiRWRequest->Tool = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL; -	IstwiRWRequest->MsgContext = mpi_hdr->MsgContext;  	IstwiRWRequest->Flags = MPI_TB_ISTWI_FLAGS_READ;  	IstwiRWRequest->NumAddressBytes = 0x01;  	IstwiRWRequest->DataLength = cpu_to_le16(0x04); diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index e15220ff52f..02a3eefd693 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -97,11 +97,10 @@ static u8	mptfcInternalCtx = MPT_MAX_PROTOCOL_DRIVERS;  static int mptfc_target_alloc(struct scsi_target *starget);  static int mptfc_slave_alloc(struct scsi_device *sdev); -static int mptfc_qcmd(struct scsi_cmnd *SCpnt, -		      void (*done)(struct scsi_cmnd *)); +static int mptfc_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *SCpnt);  static void mptfc_target_destroy(struct scsi_target *starget);  static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout); -static void __devexit mptfc_remove(struct pci_dev *pdev); +static void mptfc_remove(struct pci_dev *pdev);  static int mptfc_abort(struct scsi_cmnd *SCpnt);  static int mptfc_dev_reset(struct scsi_cmnd *SCpnt);  static int mptfc_bus_reset(struct scsi_cmnd *SCpnt); @@ -110,7 +109,7 @@ static int mptfc_host_reset(struct scsi_cmnd *SCpnt);  static struct scsi_host_template mptfc_driver_template = {  	.module				= THIS_MODULE,  	.proc_name			= "mptfc", -	.proc_info			= mptscsih_proc_info, +	.show_info			= mptscsih_show_info,  	.name				= "MPT FC Host",  	.info				= mptscsih_info,  	.queuecommand			= mptfc_qcmd, @@ -650,7 +649,7 @@ mptfc_slave_alloc(struct scsi_device *sdev)  }  static int -mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) +mptfc_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *SCpnt)  {  	struct mptfc_rport_info	*ri;  	struct fc_rport	*rport = starget_to_rport(scsi_target(SCpnt->device)); @@ -659,14 +658,14 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))  	if (!vdevice || !vdevice->vtarget) {  		SCpnt->result = DID_NO_CONNECT << 16; -		done(SCpnt); +		SCpnt->scsi_done(SCpnt);  		return 0;  	}  	err = fc_remote_port_chkready(rport);  	if (unlikely(err)) {  		SCpnt->result = err; -		done(SCpnt); +		SCpnt->scsi_done(SCpnt);  		return 0;  	} @@ -674,11 +673,11 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))  	ri = *((struct mptfc_rport_info **)rport->dd_data);  	if (unlikely(!ri)) {  		SCpnt->result = DID_IMM_RETRY << 16; -		done(SCpnt); +		SCpnt->scsi_done(SCpnt);  		return 0;  	} -	return mptscsih_qcmd(SCpnt,done); +	return mptscsih_qcmd(SCpnt);  }  /* @@ -1359,7 +1358,7 @@ static struct pci_driver mptfc_driver = {  	.name		= "mptfc",  	.id_table	= mptfc_pci_table,  	.probe		= mptfc_probe, -	.remove		= __devexit_p(mptfc_remove), +	.remove		= mptfc_remove,  	.shutdown	= mptscsih_shutdown,  #ifdef CONFIG_PM  	.suspend	= mptscsih_suspend, @@ -1495,8 +1494,7 @@ mptfc_init(void)   *	@pdev: Pointer to pci_dev structure   *   */ -static void __devexit -mptfc_remove(struct pci_dev *pdev) +static void mptfc_remove(struct pci_dev *pdev)  {  	MPT_ADAPTER		*ioc = pci_get_drvdata(pdev);  	struct mptfc_rport_info	*p, *n; diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h index c171afa9323..69e9d546356 100644 --- a/drivers/message/fusion/mptlan.h +++ b/drivers/message/fusion/mptlan.h @@ -69,7 +69,6 @@  #include <linux/spinlock.h>  #include <linux/workqueue.h>  #include <linux/delay.h> -// #include <linux/trdevice.h>  #include <asm/uaccess.h>  #include <asm/io.h> diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 83a5115f025..711fcb5cec8 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -92,6 +92,11 @@ static int max_lun = MPTSAS_MAX_LUN;  module_param(max_lun, int, 0);  MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); +static int mpt_loadtime_max_sectors = 8192; +module_param(mpt_loadtime_max_sectors, int, 0); +MODULE_PARM_DESC(mpt_loadtime_max_sectors, +		" Maximum sector define for Host Bus Adaptor.Range 64 to 8192 default=8192"); +  static u8	mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;  static u8	mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;  static u8	mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */ @@ -285,10 +290,11 @@ mptsas_add_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,  	spin_lock_irqsave(&ioc->fw_event_lock, flags);  	list_add_tail(&fw_event->list, &ioc->fw_event_list);  	INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work); -	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)\n", -	    ioc->name, __func__, fw_event)); -	queue_delayed_work(ioc->fw_event_q, &fw_event->work, -	    delay); +	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)" +		"on cpuid %d\n", ioc->name, __func__, +		fw_event, smp_processor_id())); +	queue_delayed_work_on(smp_processor_id(), ioc->fw_event_q, +	    &fw_event->work, delay);  	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);  } @@ -300,14 +306,15 @@ mptsas_requeue_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,  	unsigned long flags;  	spin_lock_irqsave(&ioc->fw_event_lock, flags);  	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: reschedule task " -	    "(fw_event=0x%p)\n", ioc->name, __func__, fw_event)); +	    "(fw_event=0x%p)on cpuid %d\n", ioc->name, __func__, +		fw_event, smp_processor_id()));  	fw_event->retries++; -	queue_delayed_work(ioc->fw_event_q, &fw_event->work, -	    msecs_to_jiffies(delay)); +	queue_delayed_work_on(smp_processor_id(), ioc->fw_event_q, +	    &fw_event->work, msecs_to_jiffies(delay));  	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);  } -/* free memory assoicated to a sas firmware event */ +/* free memory associated to a sas firmware event */  static void  mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event)  { @@ -1094,7 +1101,7 @@ mptsas_block_io_starget(struct scsi_target *starget)  /**   * mptsas_target_reset_queue   * - * Receive request for TARGET_RESET after recieving an firmware + * Receive request for TARGET_RESET after receiving an firmware   * event NOT_RESPONDING_EVENT, then put command in link list   * and queue if task_queue already in use.   * @@ -1146,7 +1153,7 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc,   *   * This function will delete scheduled target reset from the list and   * try to send next target reset. This will be called from completion - * context of any Task managment command. + * context of any Task management command.   */  void @@ -1403,7 +1410,7 @@ mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,  /**   *	mptsas_add_end_device - report a new end device to sas transport layer   *	@ioc: Pointer to MPT_ADAPTER structure - *	@phy_info: decribes attached device + *	@phy_info: describes attached device   *   *	return (0) success (1) failure   * @@ -1481,7 +1488,7 @@ mptsas_add_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)  /**   *	mptsas_del_end_device - report a deleted end device to sas transport layer   *	@ioc: Pointer to MPT_ADAPTER structure - *	@phy_info: decribes attached device + *	@phy_info: describes attached device   *   **/  static void @@ -1889,7 +1896,7 @@ mptsas_slave_alloc(struct scsi_device *sdev)  }  static int -mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) +mptsas_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *SCpnt)  {  	MPT_SCSI_HOST	*hd;  	MPT_ADAPTER	*ioc; @@ -1897,11 +1904,11 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))  	if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {  		SCpnt->result = DID_NO_CONNECT << 16; -		done(SCpnt); +		SCpnt->scsi_done(SCpnt);  		return 0;  	} -	hd = shost_priv(SCpnt->device->host); +	hd = shost_priv(shost);  	ioc = hd->ioc;  	if (ioc->sas_discovery_quiesce_io) @@ -1910,7 +1917,7 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))  	if (ioc->debug_level & MPT_DEBUG_SCSI)  		scsi_print_command(SCpnt); -	return mptscsih_qcmd(SCpnt,done); +	return mptscsih_qcmd(SCpnt);  }  /** @@ -1941,6 +1948,15 @@ static enum blk_eh_timer_return mptsas_eh_timed_out(struct scsi_cmnd *sc)  		goto done;  	} +	/* In case if IOC is in reset from internal context. +	*  Do not execute EEH for the same IOC. SML should to reset timer. +	*/ +	if (ioc->ioc_reset_in_progress) { +		dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: ioc is in reset," +		    "SML need to reset the timer (sc=%p)\n", +		    ioc->name, __func__, sc)); +		rc = BLK_EH_RESET_TIMER; +	}  	vdevice = sc->device->hostdata;  	if (vdevice && vdevice->vtarget && (vdevice->vtarget->inDMD  		|| vdevice->vtarget->deleted)) { @@ -1959,7 +1975,7 @@ done:  static struct scsi_host_template mptsas_driver_template = {  	.module				= THIS_MODULE,  	.proc_name			= "mptsas", -	.proc_info			= mptscsih_proc_info, +	.show_info			= mptscsih_show_info,  	.name				= "MPT SAS Host",  	.info				= mptscsih_info,  	.queuecommand			= mptsas_qcmd, @@ -1971,7 +1987,6 @@ static struct scsi_host_template mptsas_driver_template = {  	.change_queue_depth 		= mptscsih_change_queue_depth,  	.eh_abort_handler		= mptscsih_abort,  	.eh_device_reset_handler	= mptscsih_dev_reset, -	.eh_bus_reset_handler		= mptscsih_bus_reset,  	.eh_host_reset_handler		= mptscsih_host_reset,  	.bios_param			= mptscsih_bios_param,  	.can_queue			= MPT_SAS_CAN_QUEUE, @@ -2218,10 +2233,10 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,  	}  	/* do we need to support multiple segments? */ -	if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) { -		printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n", -		    ioc->name, __func__, req->bio->bi_vcnt, blk_rq_bytes(req), -		    rsp->bio->bi_vcnt, blk_rq_bytes(rsp)); +	if (bio_multiple_segments(req->bio) || +	    bio_multiple_segments(rsp->bio)) { +		printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u, rsp %u\n", +		    ioc->name, __func__, blk_rq_bytes(req), blk_rq_bytes(rsp));  		return -EINVAL;  	} @@ -3061,6 +3076,9 @@ static int mptsas_probe_one_phy(struct device *dev,  	case MPI_SAS_IOUNIT0_RATE_3_0:  		phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;  		break; +	case MPI_SAS_IOUNIT0_RATE_6_0: +		phy->negotiated_linkrate = SAS_LINK_RATE_6_0_GBPS; +		break;  	case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:  	case MPI_SAS_IOUNIT0_RATE_UNKNOWN:  	default: @@ -3689,7 +3707,8 @@ mptsas_send_link_status_event(struct fw_event_work *fw_event)  	}  	if (link_rate == MPI_SAS_IOUNIT0_RATE_1_5 || -	    link_rate == MPI_SAS_IOUNIT0_RATE_3_0) { +	    link_rate == MPI_SAS_IOUNIT0_RATE_3_0 || +	    link_rate == MPI_SAS_IOUNIT0_RATE_6_0) {  		if (!port_info) {  			if (ioc->old_sas_discovery_protocal) { @@ -5007,7 +5026,6 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)  			(ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)) {  			VirtTarget *vtarget = NULL;  			u8		id, channel; -			u32	 log_info = le32_to_cpu(reply->IOCLogInfo);  			id = sas_event_data->TargetID;  			channel = sas_event_data->Bus; @@ -5018,7 +5036,8 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)  				    "LogInfo (0x%x) available for "  				   "INTERNAL_DEVICE_RESET"  				   "fw_id %d fw_channel %d\n", ioc->name, -				   log_info, id, channel)); +				   le32_to_cpu(reply->IOCLogInfo), +				   id, channel));  				if (vtarget->raidVolume) {  					devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT  					"Skipping Raid Volume for inDMD\n", @@ -5137,6 +5156,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) { @@ -5234,6 +5255,21 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)  		sh->sg_tablesize = numSGE;  	} +	if (mpt_loadtime_max_sectors) { +		if (mpt_loadtime_max_sectors < 64 || +			mpt_loadtime_max_sectors > 8192) { +			printk(MYIOC_s_INFO_FMT "Invalid value passed for" +				"mpt_loadtime_max_sectors %d." +				"Range from 64 to 8192\n", ioc->name, +				mpt_loadtime_max_sectors); +		} +		mpt_loadtime_max_sectors &=  0xFFFFFFFE; +		dprintk(ioc, printk(MYIOC_s_DEBUG_FMT +			"Resetting max sector to %d from %d\n", +		  ioc->name, mpt_loadtime_max_sectors, sh->max_sectors)); +		sh->max_sectors = mpt_loadtime_max_sectors; +	} +  	hd = shost_priv(sh);  	hd->ioc = ioc; @@ -5294,7 +5330,7 @@ mptsas_shutdown(struct pci_dev *pdev)  	mptsas_cleanup_fw_event_q(ioc);  } -static void __devexit mptsas_remove(struct pci_dev *pdev) +static void mptsas_remove(struct pci_dev *pdev)  {  	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);  	struct mptsas_portinfo *p, *n; @@ -5338,6 +5374,8 @@ static struct pci_device_id mptsas_pci_table[] = {  		PCI_ANY_ID, PCI_ANY_ID },  	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,  		PCI_ANY_ID, PCI_ANY_ID }, +	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068_820XELP, +		PCI_ANY_ID, PCI_ANY_ID },  	{0}	/* Terminating entry */  };  MODULE_DEVICE_TABLE(pci, mptsas_pci_table); @@ -5347,7 +5385,7 @@ static struct pci_driver mptsas_driver = {  	.name		= "mptsas",  	.id_table	= mptsas_pci_table,  	.probe		= mptsas_probe, -	.remove		= __devexit_p(mptsas_remove), +	.remove		= mptsas_remove,  	.shutdown	= mptsas_shutdown,  #ifdef CONFIG_PM  	.suspend	= mptscsih_suspend, diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 59b8f53d1ec..2a1c6f21af2 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -792,6 +792,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)  			 * than an unsolicited DID_ABORT.  			 */  			sc->result = DID_RESET << 16; +			break;  		case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:		/* 0x004C */  			if (ioc->bus_type == FC) @@ -827,10 +828,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)  				 * DID_SOFT_ERROR is set.  				 */  				if (ioc->bus_type == SPI) { -					if (pScsiReq->CDB[0] == READ_6  || +					if ((pScsiReq->CDB[0] == READ_6  && ((pScsiReq->CDB[1] & 0x02) == 0)) ||  					    pScsiReq->CDB[0] == READ_10 ||  					    pScsiReq->CDB[0] == READ_12 || -					    pScsiReq->CDB[0] == READ_16 || +						(pScsiReq->CDB[0] == READ_16 && +						((pScsiReq->CDB[1] & 0x02) == 0)) ||  					    pScsiReq->CDB[0] == VERIFY  ||  					    pScsiReq->CDB[0] == VERIFY_16) {  						if (scsi_bufflen(sc) != @@ -1024,7 +1026,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 +1057,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 @@ -1281,101 +1284,17 @@ mptscsih_info(struct Scsi_Host *SChost)  	return h->info_kbuf;  } -struct info_str { -	char *buffer; -	int   length; -	int   offset; -	int   pos; -}; - -static void -mptscsih_copy_mem_info(struct info_str *info, char *data, int len) -{ -	if (info->pos + len > info->length) -		len = info->length - info->pos; - -	if (info->pos + len < info->offset) { -		info->pos += len; -		return; -	} - -	if (info->pos < info->offset) { -	        data += (info->offset - info->pos); -	        len  -= (info->offset - info->pos); -	} - -	if (len > 0) { -                memcpy(info->buffer + info->pos, data, len); -                info->pos += len; -	} -} - -static int -mptscsih_copy_info(struct info_str *info, char *fmt, ...) -{ -	va_list args; -	char buf[81]; -	int len; - -	va_start(args, fmt); -	len = vsprintf(buf, fmt, args); -	va_end(args); - -	mptscsih_copy_mem_info(info, buf, len); -	return len; -} - -static int -mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len) -{ -	struct info_str info; - -	info.buffer	= pbuf; -	info.length	= len; -	info.offset	= offset; -	info.pos	= 0; - -	mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name); -	mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word); -	mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts); -	mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth); - -	return ((info.pos > info.offset) ? info.pos - info.offset : 0); -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - *	mptscsih_proc_info - Return information about MPT adapter - * 	@host:   scsi host struct - * 	@buffer: if write, user data; if read, buffer for user - *	@start: returns the buffer address - * 	@offset: if write, 0; if read, the current offset into the buffer from - * 		 the previous read. - * 	@length: if write, return length; - *	@func:   write = 1; read = 0 - * - *	(linux scsi_host_template.info routine) - */ -int -mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, -			int length, int func) +int mptscsih_show_info(struct seq_file *m, struct Scsi_Host *host)  {  	MPT_SCSI_HOST	*hd = shost_priv(host);  	MPT_ADAPTER	*ioc = hd->ioc; -	int size = 0; -	if (func) { -		/* -		 * write is not supported -		 */ -	} else { -		if (start) -			*start = buffer; +	seq_printf(m, "%s: %s, ", ioc->name, ioc->prod_name); +	seq_printf(m, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word); +	seq_printf(m, "Ports=%d, ", ioc->facts.NumberOfPorts); +	seq_printf(m, "MaxQ=%d\n", ioc->req_depth); -		size = mptscsih_host_info(ioc, buffer, offset, length); -	} - -	return size; +	return 0;  }  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1385,7 +1304,6 @@ mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t off  /**   *	mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.   *	@SCpnt: Pointer to scsi_cmnd structure - *	@done: Pointer SCSI mid-layer IO completion function   *   *	(linux scsi_host_template.queuecommand routine)   *	This is the primary SCSI IO start routine.  Create a MPI SCSIIORequest @@ -1394,7 +1312,7 @@ mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t off   *	Returns 0. (rtn value discarded by linux scsi mid-layer)   */  int -mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) +mptscsih_qcmd(struct scsi_cmnd *SCpnt)  {  	MPT_SCSI_HOST		*hd;  	MPT_FRAME_HDR		*mf; @@ -1410,16 +1328,12 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))  	hd = shost_priv(SCpnt->device->host);  	ioc = hd->ioc; -	SCpnt->scsi_done = done; -	dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p, done()=%p\n", -		ioc->name, SCpnt, done)); +	dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p\n", +		ioc->name, SCpnt)); -	if (ioc->taskmgmt_quiesce_io) { -		dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n", -			ioc->name, SCpnt)); +	if (ioc->taskmgmt_quiesce_io)  		return SCSI_MLQUEUE_HOST_BUSY; -	}  	/*  	 *  Put together a MPT SCSI request... @@ -1632,7 +1546,13 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun,  		return 0;  	} -	if (ioc_raw_state & MPI_DOORBELL_ACTIVE) { +	/* DOORBELL ACTIVE check is not required if +	*  MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q is supported. +	*/ + +	if (!((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) +		 && (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) && +		(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {  		printk(MYIOC_s_WARN_FMT  			"TaskMgmt type=%x: ioc_state: "  			"DOORBELL_ACTIVE (0x%x)!\n", @@ -1731,7 +1651,9 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun,  		printk(MYIOC_s_WARN_FMT  		       "Issuing Reset from %s!! doorbell=0x%08x\n",  		       ioc->name, __func__, mpt_GetIocState(ioc, 0)); -		retval = mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); +		retval = (ioc->bus_type == SAS) ? +			mpt_HardResetHandler(ioc, CAN_SLEEP) : +			mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);  		mpt_free_msg_frame(ioc, mf);  	} @@ -1773,7 +1695,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)  	int		 scpnt_idx;  	int		 retval;  	VirtDevice	 *vdevice; -	ulong	 	 sn = SCpnt->serial_number;  	MPT_ADAPTER	*ioc;  	/* If we can't locate our host adapter structure, return FAILED status. @@ -1859,8 +1780,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)  			 vdevice->vtarget->id, vdevice->lun,  			 ctx2abort, mptscsih_get_tm_timeout(ioc)); -	if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx && -	    SCpnt->serial_number == sn) { +	if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx) {  		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT  		    "task abort: command still in active list! (sc=%p)\n",  		    ioc->name, SCpnt)); @@ -1873,8 +1793,9 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)  	}   out: -	printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n", -	    ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), SCpnt); +	printk(MYIOC_s_INFO_FMT "task abort: %s (rv=%04x) (sc=%p)\n", +	    ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), retval, +	    SCpnt);  	return retval;  } @@ -1911,7 +1832,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)  	vdevice = SCpnt->device->hostdata;  	if (!vdevice || !vdevice->vtarget) { -		retval = SUCCESS; +		retval = 0;  		goto out;  	} @@ -3341,7 +3262,7 @@ EXPORT_SYMBOL(mptscsih_shutdown);  EXPORT_SYMBOL(mptscsih_suspend);  EXPORT_SYMBOL(mptscsih_resume);  #endif -EXPORT_SYMBOL(mptscsih_proc_info); +EXPORT_SYMBOL(mptscsih_show_info);  EXPORT_SYMBOL(mptscsih_info);  EXPORT_SYMBOL(mptscsih_qcmd);  EXPORT_SYMBOL(mptscsih_slave_destroy); diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 45a5ff3eff6..99e3390807f 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -111,9 +111,9 @@ extern void mptscsih_shutdown(struct pci_dev *);  extern int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);  extern int mptscsih_resume(struct pci_dev *pdev);  #endif -extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func); +extern int mptscsih_show_info(struct seq_file *, struct Scsi_Host *);  extern const char * mptscsih_info(struct Scsi_Host *SChost); -extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)); +extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt);  extern int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel,  	u8 id, int lun, int ctx2abort, ulong timeout);  extern void mptscsih_slave_destroy(struct scsi_device *device); @@ -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); diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 0e2803155ae..49d11338294 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -780,29 +780,29 @@ static int mptspi_slave_configure(struct scsi_device *sdev)  }  static int -mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) +mptspi_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *SCpnt)  { -	struct _MPT_SCSI_HOST *hd = shost_priv(SCpnt->device->host); +	struct _MPT_SCSI_HOST *hd = shost_priv(shost);  	VirtDevice	*vdevice = SCpnt->device->hostdata;  	MPT_ADAPTER *ioc = hd->ioc;  	if (!vdevice || !vdevice->vtarget) {  		SCpnt->result = DID_NO_CONNECT << 16; -		done(SCpnt); +		SCpnt->scsi_done(SCpnt);  		return 0;  	}  	if (SCpnt->device->channel == 1 &&  		mptscsih_is_phys_disk(ioc, 0, SCpnt->device->id) == 0) {  		SCpnt->result = DID_NO_CONNECT << 16; -		done(SCpnt); +		SCpnt->scsi_done(SCpnt);  		return 0;  	}  	if (spi_dv_pending(scsi_target(SCpnt->device)))  		ddvprintk(ioc, scsi_print_command(SCpnt)); -	return mptscsih_qcmd(SCpnt,done); +	return mptscsih_qcmd(SCpnt);  }  static void mptspi_slave_destroy(struct scsi_device *sdev) @@ -829,7 +829,7 @@ static void mptspi_slave_destroy(struct scsi_device *sdev)  static struct scsi_host_template mptspi_driver_template = {  	.module				= THIS_MODULE,  	.proc_name			= "mptspi", -	.proc_info			= mptscsih_proc_info, +	.show_info			= mptscsih_show_info,  	.name				= "MPT SPI Host",  	.info				= mptscsih_info,  	.queuecommand			= mptspi_qcmd, @@ -865,6 +865,10 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget,  	struct _x_config_parms cfg;  	struct _CONFIG_PAGE_HEADER hdr;  	int err = -EBUSY; +	u32 nego_parms; +	u32 period; +	struct scsi_device *sdev; +	int i;  	/* don't allow updating nego parameters on RAID devices */  	if (starget->channel == 0 && @@ -902,6 +906,24 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget,  	pg1->Header.PageNumber = hdr.PageNumber;  	pg1->Header.PageType = hdr.PageType; +	nego_parms = le32_to_cpu(pg1->RequestedParameters); +	period = (nego_parms & MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK) >> +		MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD; +	if (period == 8) { +		/* Turn on inline data padding for TAPE when running U320 */ +		for (i = 0 ; i < 16; i++) { +			sdev = scsi_device_lookup_by_target(starget, i); +			if (sdev && sdev->type == TYPE_TAPE) { +				sdev_printk(KERN_DEBUG, sdev, MYIOC_s_FMT +					    "IDP:ON\n", ioc->name); +				nego_parms |= MPI_SCSIDEVPAGE1_RP_IDP; +				pg1->RequestedParameters = +				    cpu_to_le32(nego_parms); +				break; +			} +		} +	} +  	mptspi_print_write_nego(hd, starget, le32_to_cpu(pg1->RequestedParameters));  	if (mpt_config(ioc, &cfg)) { @@ -1526,7 +1548,7 @@ static struct pci_driver mptspi_driver = {  	.name		= "mptspi",  	.id_table	= mptspi_pci_table,  	.probe		= mptspi_probe, -	.remove		= __devexit_p(mptscsih_remove), +	.remove		= mptscsih_remove,  	.shutdown	= mptscsih_shutdown,  #ifdef CONFIG_PM  	.suspend	= mptscsih_suspend,  | 
