diff options
Diffstat (limited to 'drivers/message')
-rw-r--r-- | drivers/message/fusion/mptbase.c | 300 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.h | 38 | ||||
-rw-r--r-- | drivers/message/fusion/mptctl.c | 38 | ||||
-rw-r--r-- | drivers/message/fusion/mptfc.c | 9 | ||||
-rw-r--r-- | drivers/message/fusion/mptlan.c | 4 | ||||
-rw-r--r-- | drivers/message/fusion/mptsas.c | 278 | ||||
-rw-r--r-- | drivers/message/fusion/mptsas.h | 1 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 54 | ||||
-rw-r--r-- | drivers/message/fusion/mptspi.c | 9 | ||||
-rw-r--r-- | drivers/message/i2o/exec-osm.c | 8 | ||||
-rw-r--r-- | drivers/message/i2o/i2o_block.c | 33 | ||||
-rw-r--r-- | drivers/message/i2o/i2o_config.c | 18 | ||||
-rw-r--r-- | drivers/message/i2o/i2o_scsi.c | 3 |
13 files changed, 544 insertions, 249 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index a6a57011ba6c..6837a8ef9371 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -50,6 +50,7 @@ #include <linux/module.h> #include <linux/errno.h> #include <linux/init.h> +#include <linux/seq_file.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/pci.h> @@ -109,12 +110,12 @@ MODULE_PARM_DESC(mpt_debug_level, " debug level - refer to mptdebug.h \ int mpt_fwfault_debug; EXPORT_SYMBOL(mpt_fwfault_debug); -module_param_call(mpt_fwfault_debug, param_set_int, param_get_int, - &mpt_fwfault_debug, 0600); +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)"); +static char MptCallbacksName[MPT_MAX_PROTOCOL_DRIVERS][50]; #ifdef MFCNT static int mfcounter = 0; @@ -199,12 +200,9 @@ static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_valu static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init); #ifdef CONFIG_PROC_FS -static int procmpt_summary_read(char *buf, char **start, off_t offset, - int request, int *eof, void *data); -static int procmpt_version_read(char *buf, char **start, off_t offset, - int request, int *eof, void *data); -static int procmpt_iocinfo_read(char *buf, char **start, off_t offset, - int request, int *eof, void *data); +static const struct file_operations mpt_summary_proc_fops; +static const struct file_operations mpt_version_proc_fops; +static const struct file_operations mpt_iocinfo_proc_fops; #endif static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc); @@ -213,7 +211,7 @@ static int ProcessEventNotification(MPT_ADAPTER *ioc, static void mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); -static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); +static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info , u8 cb_idx); static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); static void mpt_inactive_raid_list_free(MPT_ADAPTER *ioc); @@ -490,7 +488,7 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa) else if (ioc->bus_type == SPI) mpt_spi_log_info(ioc, log_info); else if (ioc->bus_type == SAS) - mpt_sas_log_info(ioc, log_info); + mpt_sas_log_info(ioc, log_info, cb_idx); } if (ioc_stat & MPI_IOCSTATUS_MASK) @@ -628,6 +626,7 @@ mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) * mpt_register - Register protocol-specific main callback handler. * @cbfunc: callback function pointer * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value) + * @func_name: call function's name * * This routine is called by a protocol-specific driver (SCSI host, * LAN, SCSI target) to register its reply callback routine. Each @@ -644,7 +643,7 @@ mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) * considered an error by the caller. */ u8 -mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass) +mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass, char *func_name) { u8 cb_idx; last_drv_idx = MPT_MAX_PROTOCOL_DRIVERS; @@ -659,6 +658,8 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass) 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)); break; } } @@ -1632,6 +1633,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; } } else { @@ -1645,6 +1647,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; } } @@ -1675,6 +1678,7 @@ 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; } ioc->memmap = mem; @@ -1719,7 +1723,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) u8 pcixcmd; static int mpt_ids = 0; #ifdef CONFIG_PROC_FS - struct proc_dir_entry *dent, *ent; + struct proc_dir_entry *dent; #endif ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC); @@ -1770,7 +1774,6 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */ ioc->reply_sz = MPT_REPLY_FRAME_SIZE; - ioc->pcidev = pdev; spin_lock_init(&ioc->taskmgmt_lock); mutex_init(&ioc->internal_cmds.mutex); @@ -1794,7 +1797,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ioc->sh = NULL; ioc->cached_fw = NULL; - /* Initilize SCSI Config Data structure + /* Initialize SCSI Config Data structure */ memset(&ioc->spi_data, 0, sizeof(SpiCfgData)); @@ -1913,6 +1916,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ioc->msi_enable = 0; break; } + + ioc->fw_events_off = 1; + if (ioc->errata_flag_1064) pci_disable_io_access(pdev); @@ -1972,16 +1978,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) */ dent = proc_mkdir(ioc->name, mpt_proc_root_dir); if (dent) { - ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent); - if (ent) { - ent->read_proc = procmpt_iocinfo_read; - ent->data = ioc; - } - ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent); - if (ent) { - ent->read_proc = procmpt_summary_read; - ent->data = ioc; - } + proc_create_data("info", S_IRUGO, dent, &mpt_iocinfo_proc_fops, ioc); + proc_create_data("summary", S_IRUGO, dent, &mpt_summary_proc_fops, ioc); } #endif @@ -2051,7 +2049,6 @@ mpt_detach(struct pci_dev *pdev) mpt_adapter_dispose(ioc); - pci_set_drvdata(pdev, NULL); } /************************************************************************** @@ -2471,7 +2468,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { /* - * Initalize link list for inactive raid volumes. + * Initialize link list for inactive raid volumes. */ mutex_init(&ioc->raid_data.inactive_list_mutex); INIT_LIST_HEAD(&ioc->raid_data.inactive_list); @@ -5062,8 +5059,9 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) goto out; if (!timeleft) { - printk(KERN_DEBUG "%s: Issuing Reset from %s!!\n", - ioc->name, __func__); + printk(MYIOC_s_WARN_FMT + "Issuing Reset from %s!!, doorbell=0x%08x\n", + ioc->name, __func__, mpt_GetIocState(ioc, 0)); mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); mpt_free_msg_frame(ioc, mf); } @@ -6454,8 +6452,9 @@ out: mutex_unlock(&ioc->mptbase_cmds.mutex); if (issue_hard_reset) { issue_hard_reset = 0; - printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", - ioc->name, __func__); + printk(MYIOC_s_WARN_FMT + "Issuing Reset from %s!!, doorbell=0x%08x\n", + ioc->name, __func__, mpt_GetIocState(ioc, 0)); if (retry_count == 0) { if (mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP) != 0) retry_count++; @@ -6537,20 +6536,12 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) static int procmpt_create(void) { - struct proc_dir_entry *ent; - mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL); if (mpt_proc_root_dir == NULL) return -ENOTDIR; - ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir); - if (ent) - ent->read_proc = procmpt_summary_read; - - ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir); - if (ent) - ent->read_proc = procmpt_version_read; - + proc_create("summary", S_IRUGO, mpt_proc_root_dir, &mpt_summary_proc_fops); + proc_create("version", S_IRUGO, mpt_proc_root_dir, &mpt_version_proc_fops); return 0; } @@ -6569,71 +6560,47 @@ procmpt_destroy(void) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * procmpt_summary_read - Handle read request of a summary file - * @buf: Pointer to area to write information - * @start: Pointer to start pointer - * @offset: Offset to start writing - * @request: Amount of read data requested - * @eof: Pointer to EOF integer - * @data: Pointer - * +/* * Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary. - * Returns number of characters written to process performing the read. */ -static int -procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data) -{ - MPT_ADAPTER *ioc; - char *out = buf; - int len; +static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan); - if (data) { - int more = 0; - - ioc = data; - mpt_print_ioc_summary(ioc, out, &more, 0, 1); +static int mpt_summary_proc_show(struct seq_file *m, void *v) +{ + MPT_ADAPTER *ioc = m->private; - out += more; + if (ioc) { + seq_mpt_print_ioc_summary(ioc, m, 1); } else { list_for_each_entry(ioc, &ioc_list, list) { - int more = 0; - - mpt_print_ioc_summary(ioc, out, &more, 0, 1); - - out += more; - if ((out-buf) >= request) - break; + seq_mpt_print_ioc_summary(ioc, m, 1); } } - len = out - buf; + return 0; +} - MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len); +static int mpt_summary_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, mpt_summary_proc_show, PDE(inode)->data); } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * procmpt_version_read - Handle read request from /proc/mpt/version. - * @buf: Pointer to area to write information - * @start: Pointer to start pointer - * @offset: Offset to start writing - * @request: Amount of read data requested - * @eof: Pointer to EOF integer - * @data: Pointer - * - * Returns number of characters written to process performing the read. - */ -static int -procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data) +static const struct file_operations mpt_summary_proc_fops = { + .owner = THIS_MODULE, + .open = mpt_summary_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int mpt_version_proc_show(struct seq_file *m, void *v) { u8 cb_idx; int scsi, fc, sas, lan, ctl, targ, dmp; char *drvname; - int len; - len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON); - len += sprintf(buf+len, " Fusion MPT base driver\n"); + seq_printf(m, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON); + seq_printf(m, " Fusion MPT base driver\n"); scsi = fc = sas = lan = ctl = targ = dmp = 0; for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { @@ -6661,98 +6628,97 @@ procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eo } if (drvname) - len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname); + seq_printf(m, " Fusion MPT %s driver\n", drvname); } } - MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len); + return 0; } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info. - * @buf: Pointer to area to write information - * @start: Pointer to start pointer - * @offset: Offset to start writing - * @request: Amount of read data requested - * @eof: Pointer to EOF integer - * @data: Pointer - * - * Returns number of characters written to process performing the read. - */ -static int -procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data) +static int mpt_version_proc_open(struct inode *inode, struct file *file) { - MPT_ADAPTER *ioc = data; - int len; + return single_open(file, mpt_version_proc_show, NULL); +} + +static const struct file_operations mpt_version_proc_fops = { + .owner = THIS_MODULE, + .open = mpt_version_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int mpt_iocinfo_proc_show(struct seq_file *m, void *v) +{ + MPT_ADAPTER *ioc = m->private; char expVer[32]; int sz; int p; mpt_get_fw_exp_ver(expVer, ioc); - len = sprintf(buf, "%s:", ioc->name); + seq_printf(m, "%s:", ioc->name); if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) - len += sprintf(buf+len, " (f/w download boot flag set)"); + seq_printf(m, " (f/w download boot flag set)"); // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL) -// len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!"); +// seq_printf(m, " CONFIG_CHECKSUM_FAIL!"); - len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n", + seq_printf(m, "\n ProductID = 0x%04x (%s)\n", ioc->facts.ProductID, ioc->prod_name); - len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer); + seq_printf(m, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer); if (ioc->facts.FWImageSize) - len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize); - len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion); - len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit); - len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState); + seq_printf(m, " (fw_size=%d)", ioc->facts.FWImageSize); + seq_printf(m, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion); + seq_printf(m, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit); + seq_printf(m, " EventState = 0x%02x\n", ioc->facts.EventState); - len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n", + seq_printf(m, " CurrentHostMfaHighAddr = 0x%08x\n", ioc->facts.CurrentHostMfaHighAddr); - len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n", + seq_printf(m, " CurrentSenseBufferHighAddr = 0x%08x\n", ioc->facts.CurrentSenseBufferHighAddr); - len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth); - len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize); + seq_printf(m, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth); + seq_printf(m, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize); - len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n", + seq_printf(m, " RequestFrames @ 0x%p (Dma @ 0x%p)\n", (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma); /* * Rounding UP to nearest 4-kB boundary here... */ sz = (ioc->req_sz * ioc->req_depth) + 128; sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000; - len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n", + seq_printf(m, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n", ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz); - len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n", + seq_printf(m, " {MaxReqSz=%d} {MaxReqDepth=%d}\n", 4*ioc->facts.RequestFrameSize, ioc->facts.GlobalCredits); - len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n", + seq_printf(m, " Frames @ 0x%p (Dma @ 0x%p)\n", (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma); sz = (ioc->reply_sz * ioc->reply_depth) + 128; - len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n", + seq_printf(m, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n", ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz); - len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n", + seq_printf(m, " {MaxRepSz=%d} {MaxRepDepth=%d}\n", ioc->facts.CurReplyFrameSize, ioc->facts.ReplyQueueDepth); - len += sprintf(buf+len, " MaxDevices = %d\n", + seq_printf(m, " MaxDevices = %d\n", (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices); - len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses); + seq_printf(m, " MaxBuses = %d\n", ioc->facts.MaxBuses); /* per-port info */ for (p=0; p < ioc->facts.NumberOfPorts; p++) { - len += sprintf(buf+len, " PortNumber = %d (of %d)\n", + seq_printf(m, " PortNumber = %d (of %d)\n", p+1, ioc->facts.NumberOfPorts); if (ioc->bus_type == FC) { if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; - len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", + seq_printf(m, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", a[5], a[4], a[3], a[2], a[1], a[0]); } - len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n", + seq_printf(m, " WWN = %08X%08X:%08X%08X\n", ioc->fc_port_page0[p].WWNN.High, ioc->fc_port_page0[p].WWNN.Low, ioc->fc_port_page0[p].WWPN.High, @@ -6760,9 +6726,21 @@ procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eo } } - MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len); + return 0; +} + +static int mpt_iocinfo_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, mpt_iocinfo_proc_show, PDE(inode)->data); } +static const struct file_operations mpt_iocinfo_proc_fops = { + .owner = THIS_MODULE, + .open = mpt_iocinfo_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; #endif /* CONFIG_PROC_FS } */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -6828,6 +6806,39 @@ mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int sh *size = y; } + +static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan) +{ + char expVer[32]; + + mpt_get_fw_exp_ver(expVer, ioc); + + /* + * Shorter summary of attached ioc's... + */ + seq_printf(m, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d", + ioc->name, + ioc->prod_name, + MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */ + ioc->facts.FWVersion.Word, + expVer, + ioc->facts.NumberOfPorts, + ioc->req_depth); + + if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) { + u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; + seq_printf(m, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X", + a[5], a[4], a[3], a[2], a[1], a[0]); + } + + seq_printf(m, ", IRQ=%d", ioc->pci_irq); + + if (!ioc->active) + seq_printf(m, " (disabled)"); + + seq_putc(m, '\n'); +} + /** * mpt_set_taskmgmt_in_progress_flag - set flags associated with task management * @ioc: Pointer to MPT_ADAPTER structure @@ -6913,7 +6924,6 @@ EXPORT_SYMBOL(mpt_halt_firmware); * mpt_SoftResetHandler - Issues a less expensive reset * @ioc: Pointer to MPT_ADAPTER structure * @sleepFlag: Indicates if sleep or schedule must be called. - * * Returns 0 for SUCCESS or -1 if FAILED. * @@ -6971,6 +6981,7 @@ mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag) spin_lock_irqsave(&ioc->taskmgmt_lock, flags); if (ioc->taskmgmt_in_progress) { + ioc->ioc_reset_in_progress = 0; spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); return -1; } @@ -7057,7 +7068,6 @@ mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag) * mpt_Soft_Hard_ResetHandler - Try less expensive reset * @ioc: Pointer to MPT_ADAPTER structure * @sleepFlag: Indicates if sleep or schedule must be called. - * * Returns 0 for SUCCESS or -1 if FAILED. * Try for softreset first, only if it fails go for expensive @@ -7144,7 +7154,8 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag); if (rc != 0) { printk(KERN_WARNING MYNAM - ": WARNING - (%d) Cannot recover %s\n", rc, ioc->name); + ": WARNING - (%d) Cannot recover %s, doorbell=0x%08x\n", + rc, ioc->name, mpt_GetIocState(ioc, 0)); } else { if (ioc->hard_resets < -1) ioc->hard_resets++; @@ -7993,11 +8004,12 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) * mpt_sas_log_info - Log information returned from SAS IOC. * @ioc: Pointer to MPT_ADAPTER structure * @log_info: U32 LogInfo reply word from the IOC + * @cb_idx: callback function's handle * * Refer to lsi/mpi_log_sas.h. **/ static void -mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info) +mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info, u8 cb_idx) { union loginfo_type { u32 loginfo; @@ -8039,7 +8051,7 @@ union loginfo_type { code_desc = ir_code_str[sas_loginfo.dw.code]; if (sas_loginfo.dw.subcode >= ARRAY_SIZE(raid_sub_code_str)) - break; + break; if (sas_loginfo.dw.code == 0) sub_code_desc = raid_sub_code_str[sas_loginfo.dw.subcode]; @@ -8051,21 +8063,22 @@ union loginfo_type { if (sub_code_desc != NULL) printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): Originator={%s}, Code={%s}," - " SubCode={%s}\n", + " SubCode={%s} cb_idx %s\n", ioc->name, log_info, originator_desc, code_desc, - sub_code_desc); + sub_code_desc, MptCallbacksName[cb_idx]); else if (code_desc != NULL) printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): Originator={%s}, Code={%s}," - " SubCode(0x%04x)\n", + " SubCode(0x%04x) cb_idx %s\n", ioc->name, log_info, originator_desc, code_desc, - sas_loginfo.dw.subcode); + sas_loginfo.dw.subcode, MptCallbacksName[cb_idx]); else printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x)," - " SubCode(0x%04x)\n", + " SubCode(0x%04x) cb_idx %s\n", ioc->name, log_info, originator_desc, - sas_loginfo.dw.code, sas_loginfo.dw.subcode); + sas_loginfo.dw.code, sas_loginfo.dw.subcode, + MptCallbacksName[cb_idx]); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -8430,7 +8443,8 @@ fusion_init(void) /* Register ourselves (mptbase) in order to facilitate * EventNotification handling. */ - mpt_base_index = mpt_register(mptbase_reply, MPTBASE_DRIVER); + mpt_base_index = mpt_register(mptbase_reply, MPTBASE_DRIVER, + "mptbase_reply"); /* Register for hard reset handling callbacks. */ diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index b613eb3d4706..f71f22948477 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.15" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.15" +#define MPT_LINUX_VERSION_COMMON "3.04.17" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.17" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -396,6 +396,8 @@ typedef struct _VirtTarget { u8 raidVolume; /* set, if RAID Volume */ u8 type; /* byte 0 of Inquiry data */ u8 deleted; /* target in process of being removed */ + u8 inDMD; /* currently in the device + removal delay timer */ u32 num_luns; } VirtTarget; @@ -418,31 +420,6 @@ typedef struct _VirtDevice { #define MPT_TARGET_FLAGS_LED_ON 0x80 /* - * /proc/mpt interface - */ -typedef struct { - const char *name; - mode_t mode; - int pad; - read_proc_t *read_proc; - write_proc_t *write_proc; -} mpt_proc_entry_t; - -#define MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len) \ -do { \ - len -= offset; \ - if (len < request) { \ - *eof = 1; \ - if (len <= 0) \ - return 0; \ - } else \ - len = request; \ - *start = buf + offset; \ - return len; \ -} while (0) - - -/* * IOCTL structure and associated defines */ @@ -580,6 +557,7 @@ struct mptfc_rport_info 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); /* * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS @@ -601,7 +579,7 @@ typedef struct _MPT_ADAPTER u16 nvdata_version_default; int debug_level; u8 io_missing_delay; - u8 device_missing_delay; + u16 device_missing_delay; SYSIF_REGS __iomem *chip; /* == c8817000 (mmap) */ SYSIF_REGS __iomem *pio_chip; /* Programmed IO (downloadboot) */ u8 bus_type; @@ -738,6 +716,7 @@ typedef struct _MPT_ADAPTER int taskmgmt_in_progress; u8 taskmgmt_quiesce_io; u8 ioc_reset_in_progress; + MPT_SCHEDULE_TARGET_RESET schedule_target_reset; struct work_struct sas_persist_task; struct work_struct fc_setup_reset_work; @@ -922,7 +901,8 @@ extern void mpt_detach(struct pci_dev *pdev); extern int mpt_suspend(struct pci_dev *pdev, pm_message_t state); extern int mpt_resume(struct pci_dev *pdev); #endif -extern u8 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass); +extern u8 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass, + char *func_name); extern void mpt_deregister(u8 cb_idx); extern int mpt_event_register(u8 cb_idx, MPT_EVHANDLER ev_cbfunc); extern void mpt_event_deregister(u8 cb_idx); diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index f06b29193b4e..d8ddfdf8be14 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -261,10 +261,16 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) /* We are done, issue wake up */ if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_PENDING) { - if (req->u.hdr.Function == MPI_FUNCTION_SCSI_TASK_MGMT) + if (req->u.hdr.Function == MPI_FUNCTION_SCSI_TASK_MGMT) { mpt_clear_taskmgmt_in_progress_flag(ioc); - ioc->ioctl_cmds.status &= ~MPT_MGMT_STATUS_PENDING; - complete(&ioc->ioctl_cmds.done); + ioc->ioctl_cmds.status &= ~MPT_MGMT_STATUS_PENDING; + complete(&ioc->ioctl_cmds.done); + if (ioc->bus_type == SAS) + ioc->schedule_target_reset(ioc); + } else { + ioc->ioctl_cmds.status &= ~MPT_MGMT_STATUS_PENDING; + complete(&ioc->ioctl_cmds.done); + } } out_continuation: @@ -298,6 +304,8 @@ mptctl_taskmgmt_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) mpt_clear_taskmgmt_in_progress_flag(ioc); ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING; complete(&ioc->taskmgmt_cmds.done); + if (ioc->bus_type == SAS) + ioc->schedule_target_reset(ioc); return 1; } return 0; @@ -946,9 +954,12 @@ retry_wait: mpt_free_msg_frame(iocp, mf); goto fwdl_out; } - if (!timeleft) + if (!timeleft) { + printk(MYIOC_s_WARN_FMT + "FW download timeout, doorbell=0x%08x\n", + iocp->name, mpt_GetIocState(iocp, 0)); mptctl_timeout_expired(iocp, mf); - else + } else goto retry_wait; goto fwdl_out; } @@ -2293,6 +2304,10 @@ retry_wait: goto done_free_mem; } if (!timeleft) { + printk(MYIOC_s_WARN_FMT + "mpt cmd timeout, doorbell=0x%08x" + " function=0x%x\n", + ioc->name, mpt_GetIocState(ioc, 0), function); if (function == MPI_FUNCTION_SCSI_TASK_MGMT) mutex_unlock(&ioc->taskmgmt_cmds.mutex); mptctl_timeout_expired(ioc, mf); @@ -2600,9 +2615,12 @@ retry_wait: mpt_free_msg_frame(ioc, mf); goto out; } - if (!timeleft) + if (!timeleft) { + printk(MYIOC_s_WARN_FMT + "HOST INFO command timeout, doorbell=0x%08x\n", + ioc->name, mpt_GetIocState(ioc, 0)); mptctl_timeout_expired(ioc, mf); - else + } else goto retry_wait; goto out; } @@ -3000,7 +3018,8 @@ static int __init mptctl_init(void) * Install our handler */ ++where; - mptctl_id = mpt_register(mptctl_reply, MPTCTL_DRIVER); + mptctl_id = mpt_register(mptctl_reply, MPTCTL_DRIVER, + "mptctl_reply"); if (!mptctl_id || mptctl_id >= MPT_MAX_PROTOCOL_DRIVERS) { printk(KERN_ERR MYNAM ": ERROR: Failed to register with Fusion MPT base driver\n"); misc_deregister(&mptctl_miscdev); @@ -3008,7 +3027,8 @@ static int __init mptctl_init(void) goto out_fail; } - mptctl_taskmgmt_id = mpt_register(mptctl_taskmgmt_reply, MPTCTL_DRIVER); + mptctl_taskmgmt_id = mpt_register(mptctl_taskmgmt_reply, MPTCTL_DRIVER, + "mptctl_taskmgmt_reply"); if (!mptctl_taskmgmt_id || mptctl_taskmgmt_id >= MPT_MAX_PROTOCOL_DRIVERS) { printk(KERN_ERR MYNAM ": ERROR: Failed to register with Fusion MPT base driver\n"); mpt_deregister(mptctl_id); diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index b5f03ad81568..e15220ff52fc 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -1472,9 +1472,12 @@ mptfc_init(void) if (!mptfc_transport_template) return -ENODEV; - mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER); - mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER); - mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); + mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER, + "mptscsih_scandv_complete"); + mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER, + "mptscsih_scandv_complete"); + mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER, + "mptscsih_scandv_complete"); mpt_event_register(mptfcDoneCtx, mptfc_event_process); mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset); diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 4fa9665cbe93..cbe96072a6cc 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -1452,7 +1452,9 @@ static int __init mpt_lan_init (void) { show_mptmod_ver(LANAME, LANVER); - if ((LanCtx = mpt_register(lan_reply, MPTLAN_DRIVER)) <= 0) { + LanCtx = mpt_register(lan_reply, MPTLAN_DRIVER, + "lan_reply"); + if (LanCtx <= 0) { printk (KERN_ERR MYNAM ": Failed to register with MPT base driver\n"); return -EBUSY; } diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index ac000e83db0e..83a5115f0251 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -57,6 +57,7 @@ #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> #include <scsi/scsi_transport_sas.h> +#include <scsi/scsi_transport.h> #include <scsi/scsi_dbg.h> #include "mptbase.h" @@ -126,6 +127,7 @@ static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc); static void mptsas_broadcast_primative_work(struct fw_event_work *fw_event); static void mptsas_handle_queue_full_event(struct fw_event_work *fw_event); static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id); +void mptsas_schedule_target_reset(void *ioc); static void mptsas_print_phy_data(MPT_ADAPTER *ioc, MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) @@ -1139,6 +1141,44 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc, } /** + * mptsas_schedule_target_reset- send pending target reset + * @iocp: per adapter object + * + * 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. + */ + +void +mptsas_schedule_target_reset(void *iocp) +{ + MPT_ADAPTER *ioc = (MPT_ADAPTER *)(iocp); + MPT_SCSI_HOST *hd = shost_priv(ioc->sh); + struct list_head *head = &hd->target_reset_list; + struct mptsas_target_reset_event *target_reset_list; + u8 id, channel; + /* + * issue target reset to next device in the queue + */ + + head = &hd->target_reset_list; + if (list_empty(head)) + return; + + target_reset_list = list_entry(head->next, + struct mptsas_target_reset_event, list); + + id = target_reset_list->sas_event_data.TargetID; + channel = target_reset_list->sas_event_data.Bus; + target_reset_list->time_count = jiffies; + + if (mptsas_target_reset(ioc, channel, id)) + target_reset_list->target_reset_issued = 1; + return; +} + + +/** * mptsas_taskmgmt_complete - complete SAS task management function * @ioc: Pointer to MPT_ADAPTER structure * @@ -1222,28 +1262,12 @@ mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) * enable work queue to remove device from upper layers */ list_del(&target_reset_list->list); - if ((mptsas_find_vtarget(ioc, channel, id)) && !ioc->fw_events_off) + if (!ioc->fw_events_off) mptsas_queue_device_delete(ioc, &target_reset_list->sas_event_data); - /* - * issue target reset to next device in the queue - */ - - head = &hd->target_reset_list; - if (list_empty(head)) - return 1; - - target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, - list); - - id = target_reset_list->sas_event_data.TargetID; - channel = target_reset_list->sas_event_data.Bus; - target_reset_list->time_count = jiffies; - - if (mptsas_target_reset(ioc, channel, id)) - target_reset_list->target_reset_issued = 1; + ioc->schedule_target_reset(ioc); return 1; } @@ -1889,6 +1913,48 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) return mptscsih_qcmd(SCpnt,done); } +/** + * mptsas_mptsas_eh_timed_out - resets the scsi_cmnd timeout + * if the device under question is currently in the + * device removal delay. + * @sc: scsi command that the midlayer is about to time out + * + **/ +static enum blk_eh_timer_return mptsas_eh_timed_out(struct scsi_cmnd *sc) +{ + MPT_SCSI_HOST *hd; + MPT_ADAPTER *ioc; + VirtDevice *vdevice; + enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED; + + hd = shost_priv(sc->device->host); + if (hd == NULL) { + printk(KERN_ERR MYNAM ": %s: Can't locate host! (sc=%p)\n", + __func__, sc); + goto done; + } + + ioc = hd->ioc; + if (ioc->bus_type != SAS) { + printk(KERN_ERR MYNAM ": %s: Wrong bus type (sc=%p)\n", + __func__, sc); + goto done; + } + + vdevice = sc->device->hostdata; + if (vdevice && vdevice->vtarget && (vdevice->vtarget->inDMD + || vdevice->vtarget->deleted)) { + dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: target removed " + "or in device removal delay (sc=%p)\n", + ioc->name, __func__, sc)); + rc = BLK_EH_RESET_TIMER; + goto done; + } + +done: + return rc; +} + static struct scsi_host_template mptsas_driver_template = { .module = THIS_MODULE, @@ -2364,7 +2430,7 @@ mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc) SasIOUnitPage1_t *buffer; dma_addr_t dma_handle; int error; - u16 device_missing_delay; + u8 device_missing_delay; memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t)); memset(&cfg, 0, sizeof(CONFIGPARMS)); @@ -2401,7 +2467,7 @@ mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc) ioc->io_missing_delay = le16_to_cpu(buffer->IODeviceMissingDelay); - device_missing_delay = le16_to_cpu(buffer->ReportDeviceMissingDelay); + device_missing_delay = buffer->ReportDeviceMissingDelay; ioc->device_missing_delay = (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) ? (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16 : device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK; @@ -2549,6 +2615,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, device_info->sas_address = le64_to_cpu(sas_address); device_info->device_info = le32_to_cpu(buffer->DeviceInfo); + device_info->flags = le16_to_cpu(buffer->Flags); out_free_consistent: pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, @@ -2960,6 +3027,7 @@ static int mptsas_probe_one_phy(struct device *dev, struct sas_phy *phy; struct sas_port *port; int error = 0; + VirtTarget *vtarget; if (!dev) { error = -ENODEV; @@ -3182,6 +3250,16 @@ static int mptsas_probe_one_phy(struct device *dev, rphy_to_expander_device(rphy)); } + /* If the device exists,verify it wasn't previously flagged + as a missing device. If so, clear it */ + vtarget = mptsas_find_vtarget(ioc, + phy_info->attached.channel, + phy_info->attached.id); + if (vtarget && vtarget->inDMD) { + printk(KERN_INFO "Device returned, unsetting inDMD\n"); + vtarget->inDMD = 0; + } + out: return error; } @@ -3635,9 +3713,42 @@ mptsas_send_link_status_event(struct fw_event_work *fw_event) MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION) phy_info->phy->negotiated_linkrate = SAS_LINK_RATE_FAILED; - else + else { phy_info->phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN; + if (ioc->device_missing_delay && + mptsas_is_end_device(&phy_info->attached)) { + struct scsi_device *sdev; + VirtDevice *vdevice; + u8 channel, id; + id = phy_info->attached.id; + channel = phy_info->attached.channel; + devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Link down for fw_id %d:fw_channel %d\n", + ioc->name, phy_info->attached.id, + phy_info->attached.channel)); + + shost_for_each_device(sdev, ioc->sh) { + vdevice = sdev->hostdata; + if ((vdevice == NULL) || + (vdevice->vtarget == NULL)) + continue; + if ((vdevice->vtarget->tflags & + MPT_TARGET_FLAGS_RAID_COMPONENT || + vdevice->vtarget->raidVolume)) + continue; + if (vdevice->vtarget->id == id && + vdevice->vtarget->channel == + channel) + devtprintk(ioc, + printk(MYIOC_s_DEBUG_FMT + "SDEV OUTSTANDING CMDS" + "%d\n", ioc->name, + sdev->device_busy)); + } + + } + } } out: mptsas_free_fw_event(ioc, fw_event); @@ -3840,6 +3951,13 @@ mptsas_probe_devices(MPT_ADAPTER *ioc) MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0) continue; + /* If there is no FW B_T mapping for this device then continue + * */ + if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT) + || !(sas_device.flags & + MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED)) + continue; + phy_info = mptsas_refreshing_device_handles(ioc, &sas_device); if (!phy_info) continue; @@ -4149,6 +4267,14 @@ mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id) phys_disk.PhysDiskID)) continue; + /* If there is no FW B_T mapping for this device then continue + * */ + if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT) + || !(sas_device.flags & + MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED)) + continue; + + phy_info = mptsas_find_phyinfo_by_sas_address(ioc, sas_device.sas_address); mptsas_add_end_device(ioc, phy_info); @@ -4171,6 +4297,7 @@ mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event, struct mptsas_devinfo sas_device; VirtTarget *vtarget; int i; + struct mptsas_portinfo *port_info; switch (hot_plug_info->event_type) { @@ -4199,12 +4326,47 @@ mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event, (hot_plug_info->channel << 8) + hot_plug_info->id); + /* If there is no FW B_T mapping for this device then break + * */ + if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT) + || !(sas_device.flags & + MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED)) + break; + if (!sas_device.handle) return; phy_info = mptsas_refreshing_device_handles(ioc, &sas_device); - if (!phy_info) + /* Only For SATA Device ADD */ + if (!phy_info && (sas_device.device_info & + MPI_SAS_DEVICE_INFO_SATA_DEVICE)) { + devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "%s %d SATA HOT PLUG: " + "parent handle of device %x\n", ioc->name, + __func__, __LINE__, sas_device.handle_parent)); + port_info = mptsas_find_portinfo_by_handle(ioc, + sas_device.handle_parent); + + if (port_info == ioc->hba_port_info) + mptsas_probe_hba_phys(ioc); + else if (port_info) + mptsas_expander_refresh(ioc, port_info); + else { + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT + "%s %d port info is NULL\n", + ioc->name, __func__, __LINE__)); + break; + } + phy_info = mptsas_refreshing_device_handles + (ioc, &sas_device); + } + + if (!phy_info) { + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT + "%s %d phy info is NULL\n", + ioc->name, __func__, __LINE__)); break; + } if (mptsas_get_rphy(phy_info)) break; @@ -4241,6 +4403,13 @@ mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event, break; } + /* If there is no FW B_T mapping for this device then break + * */ + if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT) + || !(sas_device.flags & + MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED)) + break; + phy_info = mptsas_find_phyinfo_by_sas_address( ioc, sas_device.sas_address); @@ -4294,6 +4463,13 @@ mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event, break; } + /* If there is no FW B_T mapping for this device then break + * */ + if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT) + || !(sas_device.flags & + MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED)) + break; + phy_info = mptsas_find_phyinfo_by_sas_address(ioc, sas_device.sas_address); if (!phy_info) { @@ -4727,8 +4903,9 @@ mptsas_broadcast_primative_work(struct fw_event_work *fw_event) mutex_unlock(&ioc->taskmgmt_cmds.mutex); if (issue_reset) { - printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", - ioc->name, __func__); + printk(MYIOC_s_WARN_FMT + "Issuing Reset from %s!! doorbell=0x%08x\n", + ioc->name, __func__, mpt_GetIocState(ioc, 0)); mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); } mptsas_free_fw_event(ioc, fw_event); @@ -4816,12 +4993,47 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) { EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data = (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data; + u16 ioc_stat; + ioc_stat = le16_to_cpu(reply->IOCStatus); if (sas_event_data->ReasonCode == MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING) { mptsas_target_reset_queue(ioc, sas_event_data); return 0; } + if (sas_event_data->ReasonCode == + MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET && + ioc->device_missing_delay && + (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; + + vtarget = mptsas_find_vtarget(ioc, channel, id); + if (vtarget) { + devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "LogInfo (0x%x) available for " + "INTERNAL_DEVICE_RESET" + "fw_id %d fw_channel %d\n", ioc->name, + log_info, id, channel)); + if (vtarget->raidVolume) { + devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Skipping Raid Volume for inDMD\n", + ioc->name)); + } else { + devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Setting device flag inDMD\n", + ioc->name)); + vtarget->inDMD = 1; + } + + } + + } + break; } case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE: @@ -4924,7 +5136,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->DoneCtx = mptsasDoneCtx; ioc->TaskCtx = mptsasTaskCtx; ioc->InternalCtx = mptsasInternalCtx; - + ioc->schedule_target_reset = &mptsas_schedule_target_reset; /* Added sanity check on readiness of the MPT adapter. */ if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) { @@ -5154,14 +5366,20 @@ mptsas_init(void) sas_attach_transport(&mptsas_transport_functions); if (!mptsas_transport_template) return -ENODEV; + mptsas_transport_template->eh_timed_out = mptsas_eh_timed_out; - mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER); - mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER); + mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER, + "mptscsih_io_done"); + mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER, + "mptscsih_taskmgmt_complete"); mptsasInternalCtx = - mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); - mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); + mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER, + "mptscsih_scandv_complete"); + mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER, + "mptsas_mgmt_done"); mptsasDeviceResetCtx = - mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER); + mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER, + "mptsas_taskmgmt_complete"); mpt_event_register(mptsasDoneCtx, mptsas_event_process); mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset); diff --git a/drivers/message/fusion/mptsas.h b/drivers/message/fusion/mptsas.h index 7b249edbda78..57e86ab77661 100644 --- a/drivers/message/fusion/mptsas.h +++ b/drivers/message/fusion/mptsas.h @@ -140,6 +140,7 @@ struct mptsas_devinfo { u64 sas_address; /* WWN of this device, SATA is assigned by HBA,expander */ u32 device_info; /* bitfield detailed info about this device */ + u16 flags; /* sas device pg0 flags */ }; /* diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 5c53624e0e87..59b8f53d1ece 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -664,6 +664,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) u32 log_info; status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK; + scsi_state = pScsiReply->SCSIState; scsi_status = pScsiReply->SCSIStatus; xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); @@ -738,13 +739,36 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ if ( ioc->bus_type == SAS ) { - u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus); - if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { - if ((log_info & SAS_LOGINFO_MASK) - == SAS_LOGINFO_NEXUS_LOSS) { - sc->result = (DID_BUS_BUSY << 16); - break; - } + u16 ioc_status = + le16_to_cpu(pScsiReply->IOCStatus); + if ((ioc_status & + MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) + && + ((log_info & SAS_LOGINFO_MASK) == + SAS_LOGINFO_NEXUS_LOSS)) { + VirtDevice *vdevice = + sc->device->hostdata; + + /* flag the device as being in + * device removal delay so we can + * notify the midlayer to hold off + * on timeout eh */ + if (vdevice && vdevice-> + vtarget && + vdevice->vtarget-> + raidVolume) + printk(KERN_INFO + "Skipping Raid Volume" + "for inDMD\n"); + else if (vdevice && + vdevice->vtarget) + vdevice->vtarget-> + inDMD = 1; + + sc->result = + (DID_TRANSPORT_DISRUPTED + << 16); + break; } } else if (ioc->bus_type == FC) { /* @@ -1704,8 +1728,9 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status) if (issue_hard_reset) { - printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", - ioc->name, __func__); + 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); mpt_free_msg_frame(ioc, mf); } @@ -2132,6 +2157,8 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, mpt_clear_taskmgmt_in_progress_flag(ioc); ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING; complete(&ioc->taskmgmt_cmds.done); + if (ioc->bus_type == SAS) + ioc->schedule_target_reset(ioc); return 1; } return 0; @@ -2459,6 +2486,8 @@ mptscsih_slave_configure(struct scsi_device *sdev) ioc->name,sdev->tagged_supported, sdev->simple_tags, sdev->ordered_tags)); + blk_queue_dma_alignment (sdev->request_queue, 512 - 1); + return 0; } @@ -3045,8 +3074,11 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) goto out; } if (!timeleft) { - printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", - ioc->name, __func__); + printk(MYIOC_s_WARN_FMT + "Issuing Reset from %s!! doorbell=0x%08xh" + " cmd=0x%02x\n", + ioc->name, __func__, mpt_GetIocState(ioc, 0), + cmd); mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); mpt_free_msg_frame(ioc, mf); } diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 1abaa5d01ae3..0e2803155ae2 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -1551,9 +1551,12 @@ mptspi_init(void) if (!mptspi_transport_template) return -ENODEV; - mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER); - mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER); - mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER); + mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER, + "mptscsih_io_done"); + mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER, + "mptscsih_taskmgmt_complete"); + mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, + MPTSPI_DRIVER, "mptscsih_scandv_complete"); mpt_event_register(mptspiDoneCtx, mptspi_event_process); mpt_reset_register(mptspiDoneCtx, mptspi_ioc_reset); diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 06c655c55587..a3970e56ae53 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -389,12 +389,16 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) dev = &c->pdev->dev; if (i2o_dma_realloc(dev, &c->dlct, - le32_to_cpu(sb->expected_lct_size))) + le32_to_cpu(sb->expected_lct_size))) { + mutex_unlock(&c->lct_lock); return -ENOMEM; + } msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) + if (IS_ERR(msg)) { + mutex_unlock(&c->lct_lock); return PTR_ERR(msg); + } msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); msg->u.head[1] = cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index fc593fbab696..f0f1e667000f 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -53,6 +53,7 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/i2o.h> +#include <linux/smp_lock.h> #include <linux/mempool.h> @@ -577,6 +578,7 @@ static int i2o_block_open(struct block_device *bdev, fmode_t mode) if (!dev->i2o_dev) return -ENODEV; + lock_kernel(); if (dev->power > 0x1f) i2o_block_device_power(dev, 0x02); @@ -585,6 +587,7 @@ static int i2o_block_open(struct block_device *bdev, fmode_t mode) i2o_block_device_lock(dev->i2o_dev, -1); osm_debug("Ready.\n"); + unlock_kernel(); return 0; }; @@ -615,6 +618,7 @@ static int i2o_block_release(struct gendisk *disk, fmode_t mode) if (!dev->i2o_dev) return 0; + lock_kernel(); i2o_block_device_flush(dev->i2o_dev); i2o_block_device_unlock(dev->i2o_dev, -1); @@ -625,6 +629,7 @@ static int i2o_block_release(struct gendisk *disk, fmode_t mode) operation = 0x24; i2o_block_device_power(dev, operation); + unlock_kernel(); return 0; } @@ -652,30 +657,40 @@ static int i2o_block_ioctl(struct block_device *bdev, fmode_t mode, { struct gendisk *disk = bdev->bd_disk; struct i2o_block_device *dev = disk->private_data; + int ret = -ENOTTY; /* Anyone capable of this syscall can do *real bad* things */ if (!capable(CAP_SYS_ADMIN)) return -EPERM; + lock_kernel(); switch (cmd) { case BLKI2OGRSTRAT: - return put_user(dev->rcache, (int __user *)arg); + ret = put_user(dev->rcache, (int __user *)arg); + break; case BLKI2OGWSTRAT: - return put_user(dev->wcache, (int __user *)arg); + ret = put_user(dev->wcache, (int __user *)arg); + break; case BLKI2OSRSTRAT: + ret = -EINVAL; if (arg < 0 || arg > CACHE_SMARTFETCH) - return -EINVAL; + break; dev->rcache = arg; + ret = 0; break; case BLKI2OSWSTRAT: + ret = -EINVAL; if (arg != 0 && (arg < CACHE_WRITETHROUGH || arg > CACHE_SMARTBACK)) - return -EINVAL; + break; dev->wcache = arg; + ret = 0; break; } - return -ENOTTY; + unlock_kernel(); + + return ret; }; /** @@ -712,7 +727,7 @@ static int i2o_block_transfer(struct request *req) { struct i2o_block_device *dev = req->rq_disk->private_data; struct i2o_controller *c; - u32 tid = dev->i2o_dev->lct_data.tid; + u32 tid; struct i2o_message *msg; u32 *mptr; struct i2o_block_request *ireq = req->special; @@ -728,6 +743,7 @@ static int i2o_block_transfer(struct request *req) goto exit; } + tid = dev->i2o_dev->lct_data.tid; c = dev->i2o_dev->iop; msg = i2o_msg_get(c); @@ -883,7 +899,7 @@ static void i2o_block_request_fn(struct request_queue *q) if (!req) break; - if (blk_fs_request(req)) { + if (req->cmd_type == REQ_TYPE_FS) { struct i2o_block_delayed_request *dreq; struct i2o_block_request *ireq = req->special; unsigned int queue_depth; @@ -930,7 +946,8 @@ static const struct block_device_operations i2o_block_fops = { .owner = THIS_MODULE, .open = i2o_block_open, .release = i2o_block_release, - .locked_ioctl = i2o_block_ioctl, + .ioctl = i2o_block_ioctl, + .compat_ioctl = i2o_block_ioctl, .getgeo = i2o_block_getgeo, .media_changed = i2o_block_media_changed }; diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index c4b117f5fb70..068ba0785bb4 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c @@ -111,11 +111,11 @@ static int i2o_cfg_gethrt(unsigned long arg) len = 8 + ((hrt->entry_len * hrt->num_entries) << 2); - /* We did a get user...so assuming mem is ok...is this bad? */ - put_user(len, kcmd.reslen); - if (len > reslen) + if (put_user(len, kcmd.reslen)) + ret = -EFAULT; + else if (len > reslen) ret = -ENOBUFS; - if (copy_to_user(kcmd.resbuf, (void *)hrt, len)) + else if (copy_to_user(kcmd.resbuf, (void *)hrt, len)) ret = -EFAULT; return ret; @@ -147,8 +147,9 @@ static int i2o_cfg_getlct(unsigned long arg) lct = (i2o_lct *) c->lct; len = (unsigned int)lct->table_size << 2; - put_user(len, kcmd.reslen); - if (len > reslen) + if (put_user(len, kcmd.reslen)) + ret = -EFAULT; + else if (len > reslen) ret = -ENOBUFS; else if (copy_to_user(kcmd.resbuf, lct, len)) ret = -EFAULT; @@ -208,8 +209,9 @@ static int i2o_cfg_parms(unsigned long arg, unsigned int type) return -EAGAIN; } - put_user(len, kcmd.reslen); - if (len > reslen) + if (put_user(len, kcmd.reslen)) + ret = -EFAULT; + else if (len > reslen) ret = -ENOBUFS; else if (copy_to_user(kcmd.resbuf, res, len)) ret = -EFAULT; diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index 3d45817e6dcd..ea6b2197da8a 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c @@ -528,7 +528,6 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, * Do the incoming paperwork */ i2o_dev = SCpnt->device->hostdata; - c = i2o_dev->iop; SCpnt->scsi_done = done; @@ -538,7 +537,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, done(SCpnt); goto exit; } - + c = i2o_dev->iop; tid = i2o_dev->lct_data.tid; osm_debug("qcmd: Tid = %03x\n", tid); |