diff options
Diffstat (limited to 'drivers/message')
26 files changed, 519 insertions, 469 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, diff --git a/drivers/message/i2o/README b/drivers/message/i2o/README index 911fc3021e3..f072a8eb304 100644 --- a/drivers/message/i2o/README +++ b/drivers/message/i2o/README @@ -53,7 +53,7 @@ Symbios Logic (Now LSI)  BoxHill Corporation  	Loan of initial FibreChannel disk array used for development work. -European Comission +European Commission  	Funding the work done by the University of Helsinki  SysKonnect diff --git a/drivers/message/i2o/README.ioctl b/drivers/message/i2o/README.ioctl index 65c0c47aeb7..4a7d2ebdfc9 100644 --- a/drivers/message/i2o/README.ioctl +++ b/drivers/message/i2o/README.ioctl @@ -110,7 +110,7 @@ V. Getting Logical Configuration Table        ENOBUFS     Buffer not large enough.  If this occurs, the required                    buffer length is written into *(lct->reslen) -VI. Settting Parameters +VI. Setting Parameters     SYNOPSIS  @@ -138,7 +138,7 @@ VI. Settting Parameters     The return value is the size in bytes of the data written into     ops->resbuf if no errors occur.  If an error occurs, -1 is returned  -   and errno is set appropriatly: +   and errno is set appropriately:        EFAULT      Invalid user space pointer was passed        ENXIO       Invalid IOP number @@ -222,7 +222,7 @@ VIII. Downloading Software     RETURNS     This function returns 0 no errors occur. If an error occurs, -1  -   is returned and errno is set appropriatly: +   is returned and errno is set appropriately:        EFAULT      Invalid user space pointer was passed        ENXIO       Invalid IOP number @@ -264,7 +264,7 @@ IX. Uploading Software     RETURNS     This function returns 0 if no errors occur.  If an error occurs, -1 -   is returned and errno is set appropriatly: +   is returned and errno is set appropriately:        EFAULT      Invalid user space pointer was passed        ENXIO       Invalid IOP number @@ -301,7 +301,7 @@ X. Removing Software     RETURNS     This function returns 0 if no errors occur.  If an error occurs, -1 -   is returned and errno is set appropriatly: +   is returned and errno is set appropriately:        EFAULT      Invalid user space pointer was passed        ENXIO       Invalid IOP number @@ -325,7 +325,7 @@ X. Validating Configuration     RETURNS     This function returns 0 if no erro occur.  If an error occurs, -1 is -   returned and errno is set appropriatly: +   returned and errno is set appropriately:        ETIMEDOUT   Timeout waiting for reply message        ENXIO       Invalid IOP number @@ -360,7 +360,7 @@ XI. Configuration Dialog     RETURNS     This function returns 0 if no error occur. If an error occurs, -1 -   is returned and errno is set appropriatly: +   is returned and errno is set appropriately:        EFAULT      Invalid user space pointer was passed        ENXIO       Invalid IOP number diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h index cbe384fb848..91614f11f89 100644 --- a/drivers/message/i2o/core.h +++ b/drivers/message/i2o/core.h @@ -33,7 +33,7 @@ extern int __init i2o_pci_init(void);  extern void __exit i2o_pci_exit(void);  /* device */ -extern struct device_attribute i2o_device_attrs[]; +extern const struct attribute_group *i2o_device_groups[];  extern void i2o_device_remove(struct i2o_device *);  extern int i2o_device_parse_lct(struct i2o_controller *); diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c index 0ee4264f5db..98348f420b5 100644 --- a/drivers/message/i2o/device.c +++ b/drivers/message/i2o/device.c @@ -65,7 +65,7 @@ int i2o_device_claim(struct i2o_device *dev)  	rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY);  	if (!rc) -		pr_debug("i2o: claim of device %d succeded\n", +		pr_debug("i2o: claim of device %d succeeded\n",  			 dev->lct_data.tid);  	else  		pr_debug("i2o: claim of device %d failed %d\n", @@ -110,7 +110,7 @@ int i2o_device_claim_release(struct i2o_device *dev)  	}  	if (!rc) -		pr_debug("i2o: claim release of device %d succeded\n", +		pr_debug("i2o: claim release of device %d succeeded\n",  			 dev->lct_data.tid);  	else  		pr_debug("i2o: claim release of device %d failed %d\n", @@ -138,45 +138,55 @@ static void i2o_device_release(struct device *dev)  }  /** - *	i2o_device_show_class_id - Displays class id of I2O device + *	class_id_show - Displays class id of I2O device   *	@dev: device of which the class id should be displayed   *	@attr: pointer to device attribute   *	@buf: buffer into which the class id should be printed   *   *	Returns the number of bytes which are printed into the buffer.   */ -static ssize_t i2o_device_show_class_id(struct device *dev, -					struct device_attribute *attr, -					char *buf) +static ssize_t class_id_show(struct device *dev, struct device_attribute *attr, +			     char *buf)  {  	struct i2o_device *i2o_dev = to_i2o_device(dev);  	sprintf(buf, "0x%03x\n", i2o_dev->lct_data.class_id);  	return strlen(buf) + 1;  } +static DEVICE_ATTR_RO(class_id);  /** - *	i2o_device_show_tid - Displays TID of I2O device + *	tid_show - Displays TID of I2O device   *	@dev: device of which the TID should be displayed   *	@attr: pointer to device attribute   *	@buf: buffer into which the TID should be printed   *   *	Returns the number of bytes which are printed into the buffer.   */ -static ssize_t i2o_device_show_tid(struct device *dev, -				   struct device_attribute *attr, char *buf) +static ssize_t tid_show(struct device *dev, struct device_attribute *attr, +			char *buf)  {  	struct i2o_device *i2o_dev = to_i2o_device(dev);  	sprintf(buf, "0x%03x\n", i2o_dev->lct_data.tid);  	return strlen(buf) + 1;  } +static DEVICE_ATTR_RO(tid);  /* I2O device attributes */ -struct device_attribute i2o_device_attrs[] = { -	__ATTR(class_id, S_IRUGO, i2o_device_show_class_id, NULL), -	__ATTR(tid, S_IRUGO, i2o_device_show_tid, NULL), -	__ATTR_NULL +static struct attribute *i2o_device_attrs[] = { +	&dev_attr_class_id.attr, +	&dev_attr_tid.attr, +	NULL, +}; + +static const struct attribute_group i2o_device_group = { +	.attrs = i2o_device_attrs, +}; + +const struct attribute_group *i2o_device_groups[] = { +	&i2o_device_group, +	NULL,  };  /** @@ -248,7 +258,7 @@ static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry)  			goto unreg_dev;  	} -	/* create user entries refering to this device */ +	/* create user entries referring to this device */  	list_for_each_entry(tmp, &c->devices, list)  	    if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid)  		&& (tmp != i2o_dev)) { @@ -267,7 +277,7 @@ static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry)  			goto rmlink1;  	} -	/* create parent entries refering to this device */ +	/* create parent entries referring to this device */  	list_for_each_entry(tmp, &c->devices, list)  	    if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)  		&& (tmp != i2o_dev)) { diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c index a0421efe04c..1b18a0d1d05 100644 --- a/drivers/message/i2o/driver.c +++ b/drivers/message/i2o/driver.c @@ -62,7 +62,7 @@ static int i2o_bus_match(struct device *dev, struct device_driver *drv)  struct bus_type i2o_bus_type = {  	.name = "i2o",  	.match = i2o_bus_match, -	.dev_attrs = i2o_device_attrs +	.dev_groups = i2o_device_groups,  };  /** @@ -84,7 +84,8 @@ int i2o_driver_register(struct i2o_driver *drv)  	osm_debug("Register driver %s\n", drv->name);  	if (drv->event) { -		drv->event_queue = create_workqueue(drv->name); +		drv->event_queue = alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, +						   drv->name);  		if (!drv->event_queue) {  			osm_err("Could not initialize event queue for driver "  				"%s\n", drv->name); @@ -104,7 +105,8 @@ int i2o_driver_register(struct i2o_driver *drv)  			osm_err("too many drivers registered, increase "  				"max_drivers\n");  			spin_unlock_irqrestore(&i2o_drivers_lock, flags); -			return -EFAULT; +			rc = -EFAULT; +			goto out;  		}  	drv->context = i; @@ -123,11 +125,14 @@ int i2o_driver_register(struct i2o_driver *drv)  	}  	rc = driver_register(&drv->driver); -	if (rc) { -		if (drv->event) { -			destroy_workqueue(drv->event_queue); -			drv->event_queue = NULL; -		} +	if (rc) +		goto out; + +	return 0; +out: +	if (drv->event_queue) { +		destroy_workqueue(drv->event_queue); +		drv->event_queue = NULL;  	}  	return rc; diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index f87a9d405a5..6fc3866965d 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -309,7 +309,7 @@ static inline void i2o_block_request_free(struct i2o_block_request *ireq)   *	@ireq: I2O block request   *	@mptr: message body pointer   * - *	Builds the SG list and map it to be accessable by the controller. + *	Builds the SG list and map it to be accessible by the controller.   *   *	Returns 0 on failure or 1 on success.   */ @@ -600,24 +600,22 @@ static int i2o_block_open(struct block_device *bdev, fmode_t mode)   *   *	Unlock and unmount the media, and power down the device. Gets called if   *	the block device is closed. - * - *	Returns 0 on success or negative error code on failure.   */ -static int i2o_block_release(struct gendisk *disk, fmode_t mode) +static void i2o_block_release(struct gendisk *disk, fmode_t mode)  {  	struct i2o_block_device *dev = disk->private_data;  	u8 operation;  	/* -	 * This is to deail with the case of an application -	 * opening a device and then the device dissapears while +	 * This is to deal with the case of an application +	 * opening a device and then the device disappears while  	 * it's in use, and then the application tries to release  	 * it.  ex: Unmounting a deleted RAID volume at reboot.  	 * If we send messages, it will just cause FAILs since  	 * the TID no longer exists.  	 */  	if (!dev->i2o_dev) -		return 0; +		return;  	mutex_lock(&i2o_block_mutex);  	i2o_block_device_flush(dev->i2o_dev); @@ -631,8 +629,6 @@ static int i2o_block_release(struct gendisk *disk, fmode_t mode)  	i2o_block_device_power(dev, operation);  	mutex_unlock(&i2o_block_mutex); - -	return 0;  }  static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo) @@ -695,27 +691,29 @@ static int i2o_block_ioctl(struct block_device *bdev, fmode_t mode,  };  /** - *	i2o_block_media_changed - Have we seen a media change? + *	i2o_block_check_events - Have we seen a media change?   *	@disk: gendisk which should be verified + *	@clearing: events being cleared   *   *	Verifies if the media has changed.   *   *	Returns 1 if the media was changed or 0 otherwise.   */ -static int i2o_block_media_changed(struct gendisk *disk) +static unsigned int i2o_block_check_events(struct gendisk *disk, +					   unsigned int clearing)  {  	struct i2o_block_device *p = disk->private_data;  	if (p->media_change_flag) {  		p->media_change_flag = 0; -		return 1; +		return DISK_EVENT_MEDIA_CHANGE;  	}  	return 0;  }  /**   *	i2o_block_transfer - Transfer a request to/from the I2O controller - *	@req: the request which should be transfered + *	@req: the request which should be transferred   *   *	This function converts the request into a I2O message. The necessary   *	DMA buffers are allocated and after everything is setup post the message @@ -895,11 +893,7 @@ static void i2o_block_request_fn(struct request_queue *q)  {  	struct request *req; -	while (!blk_queue_plugged(q)) { -		req = blk_peek_request(q); -		if (!req) -			break; - +	while ((req = blk_peek_request(q)) != NULL) {  		if (req->cmd_type == REQ_TYPE_FS) {  			struct i2o_block_delayed_request *dreq;  			struct i2o_block_request *ireq = req->special; @@ -950,7 +944,7 @@ static const struct block_device_operations i2o_block_fops = {  	.ioctl = i2o_block_ioctl,  	.compat_ioctl = i2o_block_ioctl,  	.getgeo = i2o_block_getgeo, -	.media_changed = i2o_block_media_changed +	.check_events = i2o_block_check_events,  };  /** diff --git a/drivers/message/i2o/i2o_block.h b/drivers/message/i2o/i2o_block.h index 67f921b4419..cf8873cbca3 100644 --- a/drivers/message/i2o/i2o_block.h +++ b/drivers/message/i2o/i2o_block.h @@ -73,7 +73,7 @@ struct i2o_block_device {  	struct i2o_device *i2o_dev;	/* pointer to I2O device */  	struct gendisk *gd;  	spinlock_t lock;	/* queue lock */ -	struct list_head open_queue;	/* list of transfered, but unfinished +	struct list_head open_queue;	/* list of transferred, but unfinished  					   requests */  	unsigned int open_queue_depth;	/* number of requests in the queue */ diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index 7d3cc575c36..04bd3b6de40 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c @@ -188,6 +188,13 @@ static int i2o_cfg_parms(unsigned long arg, unsigned int type)  	if (!dev)  		return -ENXIO; +	/* +	 * Stop users being able to try and allocate arbitrary amounts +	 * of DMA space. 64K is way more than sufficient for this. +	 */ +	if (kcmd.oplen > 65536) +		return -EMSGSIZE; +  	ops = memdup_user(kcmd.opbuf, kcmd.oplen);  	if (IS_ERR(ops))  		return PTR_ERR(ops); @@ -680,6 +687,11 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,  		}  		size = size >> 16;  		size *= 4; +		if (size > sizeof(rmsg)) { +			rcode = -EINVAL; +			goto sg_list_cleanup; +		} +  		/* Copy in the user's I2O command */  		if (copy_from_user(rmsg, user_msg, size)) {  			rcode = -EFAULT; @@ -742,19 +754,19 @@ static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd,  				 unsigned long arg)  {  	int ret; -	mutex_lock(&i2o_cfg_mutex);  	switch (cmd) {  	case I2OGETIOPS:  		ret = i2o_cfg_ioctl(file, cmd, arg);  		break;  	case I2OPASSTHRU32: +		mutex_lock(&i2o_cfg_mutex);  		ret = i2o_cfg_passthru32(file, cmd, arg); +		mutex_unlock(&i2o_cfg_mutex);  		break;  	default:  		ret = -ENOIOCTLCMD;  		break;  	} -	mutex_unlock(&i2o_cfg_mutex);  	return ret;  } @@ -915,6 +927,11 @@ static int i2o_cfg_passthru(unsigned long arg)  		}  		size = size >> 16;  		size *= 4; +		if (size > sizeof(rmsg)) { +			rcode = -EFAULT; +			goto sg_list_cleanup; +		} +  		/* Copy in the user's I2O command */  		if (copy_from_user(rmsg, user_msg, size)) {  			rcode = -EFAULT; @@ -1044,8 +1061,7 @@ static long i2o_cfg_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)  static int cfg_open(struct inode *inode, struct file *file)  { -	struct i2o_cfg_info *tmp = -	    (struct i2o_cfg_info *)kmalloc(sizeof(struct i2o_cfg_info), +	struct i2o_cfg_info *tmp = kmalloc(sizeof(struct i2o_cfg_info),  					   GFP_KERNEL);  	unsigned long flags; diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c index 07dbeaf9df9..b7d87cd227a 100644 --- a/drivers/message/i2o/i2o_proc.c +++ b/drivers/message/i2o/i2o_proc.c @@ -56,7 +56,7 @@  /* Structure used to define /proc entries */  typedef struct _i2o_proc_entry_t {  	char *name;		/* entry name */ -	mode_t mode;		/* mode */ +	umode_t mode;		/* mode */  	const struct file_operations *fops;	/* open function */  } i2o_proc_entry; @@ -255,9 +255,8 @@ static char *scsi_devices[] = {  	"Array Controller Device"  }; -static char *chtostr(u8 * chars, int n) +static char *chtostr(char *tmp, u8 *chars, int n)  { -	char tmp[256];  	tmp[0] = 0;  	return strncat(tmp, (char *)chars, n);  } @@ -283,7 +282,6 @@ static char *bus_strings[] = {  	"Local Bus",  	"ISA",  	"EISA", -	"MCA",  	"PCI",  	"PCMCIA",  	"NUBUS", @@ -351,18 +349,6 @@ static int i2o_seq_show_hrt(struct seq_file *seq, void *v)  					   EisaSlotNumber);  				break; -			case I2O_BUS_MCA: -				seq_printf(seq, "     IOBase: %0#6x,", -					   hrt->hrt_entry[i].bus.mca_bus. -					   McaBaseIOPort); -				seq_printf(seq, " MemoryBase: %0#10x,", -					   hrt->hrt_entry[i].bus.mca_bus. -					   McaBaseMemoryAddress); -				seq_printf(seq, " Slot: %0#4x,", -					   hrt->hrt_entry[i].bus.mca_bus. -					   McaSlotNumber); -				break; -  			case I2O_BUS_PCI:  				seq_printf(seq, "     Bus: %0#4x",  					   hrt->hrt_entry[i].bus.pci_bus. @@ -804,6 +790,7 @@ static int i2o_seq_show_ddm_table(struct seq_file *seq, void *v)  	} *result;  	i2o_exec_execute_ddm_table ddm_table; +	char tmp[28 + 1];  	result = kmalloc(sizeof(*result), GFP_KERNEL);  	if (!result) @@ -839,7 +826,7 @@ static int i2o_seq_show_ddm_table(struct seq_file *seq, void *v)  		seq_printf(seq, "%-#7x", ddm_table.i2o_vendor_id);  		seq_printf(seq, "%-#8x", ddm_table.module_id);  		seq_printf(seq, "%-29s", -			   chtostr(ddm_table.module_name_version, 28)); +			   chtostr(tmp, ddm_table.module_name_version, 28));  		seq_printf(seq, "%9d  ", ddm_table.data_size);  		seq_printf(seq, "%8d", ddm_table.code_size); @@ -906,6 +893,7 @@ static int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v)  	i2o_driver_result_table *result;  	i2o_driver_store_table *dst; +	char tmp[28 + 1];  	result = kmalloc(sizeof(i2o_driver_result_table), GFP_KERNEL);  	if (result == NULL) @@ -940,8 +928,9 @@ static int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v)  		seq_printf(seq, "%-#7x", dst->i2o_vendor_id);  		seq_printf(seq, "%-#8x", dst->module_id); -		seq_printf(seq, "%-29s", chtostr(dst->module_name_version, 28)); -		seq_printf(seq, "%-9s", chtostr(dst->date, 8)); +		seq_printf(seq, "%-29s", +			   chtostr(tmp, dst->module_name_version, 28)); +		seq_printf(seq, "%-9s", chtostr(tmp, dst->date, 8));  		seq_printf(seq, "%8d ", dst->module_size);  		seq_printf(seq, "%8d ", dst->mpb_size);  		seq_printf(seq, "0x%04x", dst->module_flags); @@ -1261,6 +1250,7 @@ static int i2o_seq_show_dev_identity(struct seq_file *seq, void *v)  	// == (allow) 512d bytes (max)  	static u16 *work16 = (u16 *) work32;  	int token; +	char tmp[16 + 1];  	token = i2o_parm_field_get(d, 0xF100, -1, &work32, sizeof(work32)); @@ -1273,13 +1263,13 @@ static int i2o_seq_show_dev_identity(struct seq_file *seq, void *v)  	seq_printf(seq, "Owner TID     : %0#5x\n", work16[2]);  	seq_printf(seq, "Parent TID    : %0#5x\n", work16[3]);  	seq_printf(seq, "Vendor info   : %s\n", -		   chtostr((u8 *) (work32 + 2), 16)); +		   chtostr(tmp, (u8 *) (work32 + 2), 16));  	seq_printf(seq, "Product info  : %s\n", -		   chtostr((u8 *) (work32 + 6), 16)); +		   chtostr(tmp, (u8 *) (work32 + 6), 16));  	seq_printf(seq, "Description   : %s\n", -		   chtostr((u8 *) (work32 + 10), 16)); +		   chtostr(tmp, (u8 *) (work32 + 10), 16));  	seq_printf(seq, "Product rev.  : %s\n", -		   chtostr((u8 *) (work32 + 14), 8)); +		   chtostr(tmp, (u8 *) (work32 + 14), 8));  	seq_printf(seq, "Serial number : ");  	print_serial_number(seq, (u8 *) (work32 + 16), @@ -1316,6 +1306,8 @@ static int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v)  		u8 pad[256];	// allow up to 256 byte (max) serial number  	} result; +	char tmp[24 + 1]; +  	token = i2o_parm_field_get(d, 0xF101, -1, &result, sizeof(result));  	if (token < 0) { @@ -1325,9 +1317,9 @@ static int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v)  	seq_printf(seq, "Registering DDM TID : 0x%03x\n", result.ddm_tid);  	seq_printf(seq, "Module name         : %s\n", -		   chtostr(result.module_name, 24)); +		   chtostr(tmp, result.module_name, 24));  	seq_printf(seq, "Module revision     : %s\n", -		   chtostr(result.module_rev, 8)); +		   chtostr(tmp, result.module_rev, 8));  	seq_printf(seq, "Serial number       : ");  	print_serial_number(seq, result.serial_number, sizeof(result) - 36); @@ -1351,6 +1343,8 @@ static int i2o_seq_show_uinfo(struct seq_file *seq, void *v)  		u8 instance_number[4];  	} result; +	char tmp[64 + 1]; +  	token = i2o_parm_field_get(d, 0xF102, -1, &result, sizeof(result));  	if (token < 0) { @@ -1359,13 +1353,13 @@ static int i2o_seq_show_uinfo(struct seq_file *seq, void *v)  	}  	seq_printf(seq, "Device name     : %s\n", -		   chtostr(result.device_name, 64)); +		   chtostr(tmp, result.device_name, 64));  	seq_printf(seq, "Service name    : %s\n", -		   chtostr(result.service_name, 64)); +		   chtostr(tmp, result.service_name, 64));  	seq_printf(seq, "Physical name   : %s\n", -		   chtostr(result.physical_location, 64)); +		   chtostr(tmp, result.physical_location, 64));  	seq_printf(seq, "Instance number : %s\n", -		   chtostr(result.instance_number, 4)); +		   chtostr(tmp, result.instance_number, 4));  	return 0;  } @@ -1605,98 +1599,98 @@ static int i2o_seq_show_sensors(struct seq_file *seq, void *v)  static int i2o_seq_open_hrt(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_hrt, PDE(inode)->data); +	return single_open(file, i2o_seq_show_hrt, PDE_DATA(inode));  };  static int i2o_seq_open_lct(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_lct, PDE(inode)->data); +	return single_open(file, i2o_seq_show_lct, PDE_DATA(inode));  };  static int i2o_seq_open_status(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_status, PDE(inode)->data); +	return single_open(file, i2o_seq_show_status, PDE_DATA(inode));  };  static int i2o_seq_open_hw(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_hw, PDE(inode)->data); +	return single_open(file, i2o_seq_show_hw, PDE_DATA(inode));  };  static int i2o_seq_open_ddm_table(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_ddm_table, PDE(inode)->data); +	return single_open(file, i2o_seq_show_ddm_table, PDE_DATA(inode));  };  static int i2o_seq_open_driver_store(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_driver_store, PDE(inode)->data); +	return single_open(file, i2o_seq_show_driver_store, PDE_DATA(inode));  };  static int i2o_seq_open_drivers_stored(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_drivers_stored, PDE(inode)->data); +	return single_open(file, i2o_seq_show_drivers_stored, PDE_DATA(inode));  };  static int i2o_seq_open_groups(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_groups, PDE(inode)->data); +	return single_open(file, i2o_seq_show_groups, PDE_DATA(inode));  };  static int i2o_seq_open_phys_device(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_phys_device, PDE(inode)->data); +	return single_open(file, i2o_seq_show_phys_device, PDE_DATA(inode));  };  static int i2o_seq_open_claimed(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_claimed, PDE(inode)->data); +	return single_open(file, i2o_seq_show_claimed, PDE_DATA(inode));  };  static int i2o_seq_open_users(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_users, PDE(inode)->data); +	return single_open(file, i2o_seq_show_users, PDE_DATA(inode));  };  static int i2o_seq_open_priv_msgs(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_priv_msgs, PDE(inode)->data); +	return single_open(file, i2o_seq_show_priv_msgs, PDE_DATA(inode));  };  static int i2o_seq_open_authorized_users(struct inode *inode, struct file *file)  {  	return single_open(file, i2o_seq_show_authorized_users, -			   PDE(inode)->data); +			   PDE_DATA(inode));  };  static int i2o_seq_open_dev_identity(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_dev_identity, PDE(inode)->data); +	return single_open(file, i2o_seq_show_dev_identity, PDE_DATA(inode));  };  static int i2o_seq_open_ddm_identity(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_ddm_identity, PDE(inode)->data); +	return single_open(file, i2o_seq_show_ddm_identity, PDE_DATA(inode));  };  static int i2o_seq_open_uinfo(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_uinfo, PDE(inode)->data); +	return single_open(file, i2o_seq_show_uinfo, PDE_DATA(inode));  };  static int i2o_seq_open_sgl_limits(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_sgl_limits, PDE(inode)->data); +	return single_open(file, i2o_seq_show_sgl_limits, PDE_DATA(inode));  };  static int i2o_seq_open_sensors(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_sensors, PDE(inode)->data); +	return single_open(file, i2o_seq_show_sensors, PDE_DATA(inode));  };  static int i2o_seq_open_dev_name(struct inode *inode, struct file *file)  { -	return single_open(file, i2o_seq_show_dev_name, PDE(inode)->data); +	return single_open(file, i2o_seq_show_dev_name, PDE_DATA(inode));  };  static const struct file_operations i2o_seq_fops_lct = { @@ -1901,25 +1895,6 @@ static int i2o_proc_create_entries(struct proc_dir_entry *dir,  }  /** - *	i2o_proc_subdir_remove - Remove child entries from a proc entry - *	@dir: proc dir entry from which the childs should be removed - * - *	Iterate over each i2o proc entry under dir and remove it. If the child - *	also has entries, remove them too. - */ -static void i2o_proc_subdir_remove(struct proc_dir_entry *dir) -{ -	struct proc_dir_entry *pe, *tmp; -	pe = dir->subdir; -	while (pe) { -		tmp = pe->next; -		i2o_proc_subdir_remove(pe); -		remove_proc_entry(pe->name, dir); -		pe = tmp; -	} -}; - -/**   *	i2o_proc_device_add - Add an I2O device to the proc dir   *	@dir: proc dir entry to which the device should be added   *	@dev: I2O device which should be added @@ -1938,14 +1913,12 @@ static void i2o_proc_device_add(struct proc_dir_entry *dir,  	osm_debug("adding device /proc/i2o/%s/%s\n", dev->iop->name, buff); -	devdir = proc_mkdir(buff, dir); +	devdir = proc_mkdir_data(buff, 0, dir, dev);  	if (!devdir) {  		osm_warn("Could not allocate procdir!\n");  		return;  	} -	devdir->data = dev; -  	i2o_proc_create_entries(devdir, generic_dev_entries, dev);  	/* Inform core that we want updates about this device's status */ @@ -1979,12 +1952,10 @@ static int i2o_proc_iop_add(struct proc_dir_entry *dir,  	osm_debug("adding IOP /proc/i2o/%s\n", c->name); -	iopdir = proc_mkdir(c->name, dir); +	iopdir = proc_mkdir_data(c->name, 0, dir, c);  	if (!iopdir)  		return -1; -	iopdir->data = c; -  	i2o_proc_create_entries(iopdir, i2o_proc_generic_iop_entries, c);  	list_for_each_entry(dev, &c->devices, list) @@ -1994,31 +1965,6 @@ static int i2o_proc_iop_add(struct proc_dir_entry *dir,  }  /** - *	i2o_proc_iop_remove - Removes an I2O controller from the i2o proc tree - *	@dir: parent proc dir entry - *	@c: I2O controller which should be removed - * - *	Iterate over each i2o proc entry and search controller c. If it is found - *	remove it from the tree. - */ -static void i2o_proc_iop_remove(struct proc_dir_entry *dir, -				struct i2o_controller *c) -{ -	struct proc_dir_entry *pe, *tmp; - -	pe = dir->subdir; -	while (pe) { -		tmp = pe->next; -		if (pe->data == c) { -			i2o_proc_subdir_remove(pe); -			remove_proc_entry(pe->name, dir); -		} -		osm_debug("removing IOP /proc/i2o/%s\n", c->name); -		pe = tmp; -	} -} - -/**   *	i2o_proc_fs_create - Create the i2o proc fs.   *   *	Iterate over each I2O controller and create the entries for it. @@ -2048,12 +1994,7 @@ static int __init i2o_proc_fs_create(void)   */  static int __exit i2o_proc_fs_destroy(void)  { -	struct i2o_controller *c; - -	list_for_each_entry(c, &i2o_controllers, list) -	    i2o_proc_iop_remove(i2o_proc_dir_root, c); - -	remove_proc_entry("i2o", NULL); +	remove_proc_subtree("i2o", NULL);  	return 0;  }; diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index ea6b2197da8..1d31d7284cb 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c @@ -57,9 +57,8 @@  #include <linux/scatterlist.h>  #include <asm/dma.h> -#include <asm/system.h>  #include <asm/io.h> -#include <asm/atomic.h> +#include <linux/atomic.h>  #include <scsi/scsi.h>  #include <scsi/scsi_host.h> @@ -204,7 +203,7 @@ static int i2o_scsi_remove(struct device *dev)   *	i2o_scsi_probe - verify if dev is a I2O SCSI device and install it   *	@dev: device to verify if it is a I2O SCSI device   * - *	Retrieve channel, id and lun for I2O device. If everthing goes well + *	Retrieve channel, id and lun for I2O device. If everything goes well   *	register the I2O device as SCSI device on the I2O SCSI controller.   *   *	Returns 0 on success or negative error code on failure. @@ -361,7 +360,7 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m,  	 */  	error = le32_to_cpu(msg->body[0]); -	osm_debug("Completed %ld\n", cmd->serial_number); +	osm_debug("Completed %0x%p\n", cmd);  	cmd->result = error & 0xff;  	/* @@ -506,7 +505,7 @@ static struct i2o_driver i2o_scsi_driver = {   *	Locks: takes the controller lock on error path only   */ -static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, +static int i2o_scsi_queuecommand_lck(struct scsi_cmnd *SCpnt,  				 void (*done) (struct scsi_cmnd *))  {  	struct i2o_controller *c; @@ -678,7 +677,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,  	/* Queue the message */  	i2o_msg_post(c, msg); -	osm_debug("Issued %ld\n", SCpnt->serial_number); +	osm_debug("Issued %0x%p\n", SCpnt);  	return 0; @@ -688,7 +687,9 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,        exit:  	return rc; -}; +} + +static DEF_SCSI_QCMD(i2o_scsi_queuecommand)  /**   *	i2o_scsi_abort - abort a running command diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index 090d2a3a654..92752fb5b2d 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c @@ -652,6 +652,44 @@ static int i2o_iop_activate(struct i2o_controller *c)  	return i2o_hrt_get(c);  }; +static void i2o_res_alloc(struct i2o_controller *c, unsigned long flags) +{ +	i2o_status_block *sb = c->status_block.virt; +	struct resource *res = &c->mem_resource; +	resource_size_t size, align; +	int err; + +	res->name = c->pdev->bus->name; +	res->flags = flags; +	res->start = 0; +	res->end = 0; +	osm_info("%s: requires private memory resources.\n", c->name); + +	if (flags & IORESOURCE_MEM) { +		size = sb->desired_mem_size; +		align = 1 << 20;	/* unspecified, use 1Mb and play safe */ +	} else { +		size = sb->desired_io_size; +		align = 1 << 12;	/* unspecified, use 4Kb and play safe */ +	} + +	err = pci_bus_alloc_resource(c->pdev->bus, res, size, align, 0, 0, +				     NULL, NULL); +	if (err < 0) +		return; + +	if (flags & IORESOURCE_MEM) { +		c->mem_alloc = 1; +		sb->current_mem_size = resource_size(res); +		sb->current_mem_base = res->start; +	} else if (flags & IORESOURCE_IO) { +		c->io_alloc = 1; +		sb->current_io_size = resource_size(res); +		sb->current_io_base = res->start; +	} +	osm_info("%s: allocated PCI space %pR\n", c->name, res); +} +  /**   *	i2o_iop_systab_set - Set the I2O System Table of the specified IOP   *	@c: I2O controller to which the system table should be send @@ -665,52 +703,13 @@ static int i2o_iop_systab_set(struct i2o_controller *c)  	struct i2o_message *msg;  	i2o_status_block *sb = c->status_block.virt;  	struct device *dev = &c->pdev->dev; -	struct resource *root;  	int rc; -	if (sb->current_mem_size < sb->desired_mem_size) { -		struct resource *res = &c->mem_resource; -		res->name = c->pdev->bus->name; -		res->flags = IORESOURCE_MEM; -		res->start = 0; -		res->end = 0; -		osm_info("%s: requires private memory resources.\n", c->name); -		root = pci_find_parent_resource(c->pdev, res); -		if (root == NULL) -			osm_warn("%s: Can't find parent resource!\n", c->name); -		if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20,	/* Unspecified, so use 1Mb and play safe */ -					      NULL, NULL) >= 0) { -			c->mem_alloc = 1; -			sb->current_mem_size = 1 + res->end - res->start; -			sb->current_mem_base = res->start; -			osm_info("%s: allocated %llu bytes of PCI memory at " -				"0x%016llX.\n", c->name, -				(unsigned long long)(1 + res->end - res->start), -				(unsigned long long)res->start); -		} -	} +	if (sb->current_mem_size < sb->desired_mem_size) +		i2o_res_alloc(c, IORESOURCE_MEM); -	if (sb->current_io_size < sb->desired_io_size) { -		struct resource *res = &c->io_resource; -		res->name = c->pdev->bus->name; -		res->flags = IORESOURCE_IO; -		res->start = 0; -		res->end = 0; -		osm_info("%s: requires private memory resources.\n", c->name); -		root = pci_find_parent_resource(c->pdev, res); -		if (root == NULL) -			osm_warn("%s: Can't find parent resource!\n", c->name); -		if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20,	/* Unspecified, so use 1Mb and play safe */ -					      NULL, NULL) >= 0) { -			c->io_alloc = 1; -			sb->current_io_size = 1 + res->end - res->start; -			sb->current_mem_base = res->start; -			osm_info("%s: allocated %llu bytes of PCI I/O at " -				"0x%016llX.\n", c->name, -				(unsigned long long)(1 + res->end - res->start), -				(unsigned long long)res->start); -		} -	} +	if (sb->current_io_size < sb->desired_io_size) +		i2o_res_alloc(c, IORESOURCE_IO);  	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);  	if (IS_ERR(msg)) diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index 73e4658af53..0f9f3e1a2b6 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c @@ -31,12 +31,13 @@  #include <linux/interrupt.h>  #include <linux/slab.h>  #include <linux/i2o.h> +#include <linux/module.h>  #include "core.h"  #define OSM_DESCRIPTION	"I2O-subsystem"  /* PCI device id table for all I2O controllers */ -static struct pci_device_id __devinitdata i2o_pci_ids[] = { +static struct pci_device_id i2o_pci_ids[] = {  	{PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)},  	{PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)},  	{.vendor = PCI_VENDOR_ID_INTEL,.device = 0x1962, @@ -83,7 +84,7 @@ static void i2o_pci_free(struct i2o_controller *c)   *   *	Returns 0 on success or negative error code on failure.   */ -static int __devinit i2o_pci_alloc(struct i2o_controller *c) +static int i2o_pci_alloc(struct i2o_controller *c)  {  	struct pci_dev *pdev = c->pdev;  	struct device *dev = &pdev->dev; @@ -314,8 +315,7 @@ static void i2o_pci_irq_disable(struct i2o_controller *c)   *   *	Returns 0 on success or negative error code on failure.   */ -static int __devinit i2o_pci_probe(struct pci_dev *pdev, -				   const struct pci_device_id *id) +static int i2o_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)  {  	struct i2o_controller *c;  	int rc; @@ -452,7 +452,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,   *	Reset the I2O controller, disable interrupts and remove all allocated   *	resources.   */ -static void __devexit i2o_pci_remove(struct pci_dev *pdev) +static void i2o_pci_remove(struct pci_dev *pdev)  {  	struct i2o_controller *c;  	c = pci_get_drvdata(pdev); @@ -473,7 +473,7 @@ static struct pci_driver i2o_pci_driver = {  	.name = "PCI_I2O",  	.id_table = i2o_pci_ids,  	.probe = i2o_pci_probe, -	.remove = __devexit_p(i2o_pci_remove), +	.remove = i2o_pci_remove,  };  /**  | 
