From 4ff42a669a9ad3eb8274da31c7baabd968c2d365 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 17 May 2006 18:06:52 -0500 Subject: [SCSI] mptspi: reset handler shouldn't be called for other bus protocols All registered reset callback handlers are called during reset processing. The mptspi modules has its own reset callback handler, just recently added for issuing domain validation after host reset. If either the mptsas or mptfc driver are loaded, this callback could be called. Thus resulting in domain validation being issued for sas or fibre end devices. Fix this by having mptbase.c check the bus type against the driver type and only call the reset handler if they match (or if it's a non-bus specific reset handler). Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 9080853fe283..a30084076ac8 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1605,6 +1605,21 @@ mpt_resume(struct pci_dev *pdev) } #endif +static int +mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase) +{ + if ((MptDriverClass[index] == MPTSPI_DRIVER && + ioc->bus_type != SPI) || + (MptDriverClass[index] == MPTFC_DRIVER && + ioc->bus_type != FC) || + (MptDriverClass[index] == MPTSAS_DRIVER && + ioc->bus_type != SAS)) + /* make sure we only call the relevant reset handler + * for the bus */ + return 0; + return (MptResetHandlers[index])(ioc, reset_phase); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mpt_do_ioc_recovery - Initialize or recover MPT adapter. @@ -1885,14 +1900,14 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if ((ret == 0) && MptResetHandlers[ii]) { dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n", ioc->name, ii)); - rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET); + rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET); handlers++; } if (alt_ioc_ready && MptResetHandlers[ii]) { drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n", ioc->name, ioc->alt_ioc->name, ii)); - rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET); + rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET); handlers++; } } @@ -3267,11 +3282,11 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) if (MptResetHandlers[ii]) { dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n", ioc->name, ii)); - r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET); + r += mpt_signal_reset(ii, ioc, MPT_IOC_PRE_RESET); if (ioc->alt_ioc) { dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n", ioc->name, ioc->alt_ioc->name, ii)); - r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET); + r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET); } } } @@ -5706,11 +5721,11 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) if (MptResetHandlers[ii]) { dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n", ioc->name, ii)); - r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET); + r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET); if (ioc->alt_ioc) { dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n", ioc->name, ioc->alt_ioc->name, ii)); - r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET); + r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET); } } } -- cgit v1.2.1 From 9bf0a28c9a24e2cee5deecf89d118254374c75ba Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Thu, 27 Apr 2006 02:33:13 -0700 Subject: [SCSI] kdump: mpt fusion driver initialization failure fix MPT fusion driver initialization fails while second kernel is booting, after a system crash (if kdump kernel is configured). Oops message is pasted below. ***************************************************************************** Fusion MPT base driver 3.03.08 Copyright (c) 1999-2005 LSI Logic Corporation Fusion MPT SAS Host driver 3.03.08 ACPI: PCI Interrupt 0000:01:00.0[A] -> Link [LNKA] -> GSI 5 (level, low) -> IRQ 5 mptbase: Initiating ioc0 bringup BUG: unable to handle kernel paging request at virtual address 00002608 printing eip: c11782fd *pde = 00000000 Oops: 0000 [#1] Modules linked in: CPU: 0 EIP: 0060:[] Not tainted VLI EFLAGS: 00010046 (2.6.17-rc1-16M #2) EIP is at mptscsih_io_done+0x27/0x3a3 eax: c4fed000 ebx: c4fed000 ecx: 00002600 edx: 00000298 esi: c11782d6 edi: 00002600 ebp: 00000000 esp: c1332f74 ds: 007b es: 007b ss: 0068 Process swapper (pid: 0, threadinfo=c1332000 task=c128f9c0) Stack: <0>0000006c 00000020 00000298 00002600 c4fed000 c4fed000 c11782d6 0000260 0 00000000 c1172c49 c4fed000 c1305b40 00000005 00000000 c1172d75 c48877e0 c1029687 00000000 c1307fb8 00000000 c1305a00 00000001 00000000 c1307fb8 Call Trace: mptscsih_io_done+0x0/0x3a3 mpt_turbo_reply+0xbb/0xd3 mpt_interrupt+0x22/0x2b misrouted_irq+0x63/0xcb note_interrupt+0x43/0x98 __do_IRQ+0x68/0x8f do_IRQ+0x36/0x4e ======================= common_interrupt+0x1a/0x20 mwait_idle+0x1a/0x2a cpu_idle+0x40/0x5c start_kernel+0x17a/0x17c Code: 5e 5f 5d c3 55 89 cd 57 56 53 83 ec 14 89 54 24 0c 89 44 24 10 8b 90 cc 00 00 00 8b 4c 24 0c 81 c2 98 02 00 00 85 ed 89 54 24 08 <0f> b7 79 08 89 fe 74 04 0f b7 75 08 66 39 f7 75 0d 8b 44 24 0c ******************************************************************************* o Kdump capture kernel boot fails during initialization of MPT fusion driver. (LSI Logic / Symbios Logic SAS1064E PCI-Express Fusion-MPT SAS (rev 01)) o Problem is easily reproducible, if system crashed while some disk activity like cp operation was going on. o After a system crash, devices are not shutdown and capture kernel starts booting while skipping BIOS. Hence underlying device is left in operational state. In this case scsi contoller was left with interrupt line asserted reply FIFO was not empty. When driver starts initializing in the second kernel, it receives the interrupt the moment request_irq() is called. Interrupt handler, reads the message from reply FIFO and tries to access the associated message frame and panics, as in the new kernel's context that message frame is not valid at all. o In this scenario, probably we should delay the request_irq() call. First bring up the IOC, reset it if needed and then should register for irq. o I have tested the patch with SAS1064E and 53c1030 controllers. Signed-off-by: Vivek Goyal Signed-off-by: Andrew Morton Acked-by: "Moore, Eric Dean" Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 88 +++++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 38 deletions(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 266414ca2814..bb7ad4d0678a 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1387,39 +1387,6 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) /* Set lookup ptr. */ list_add_tail(&ioc->list, &ioc_list); - ioc->pci_irq = -1; - if (pdev->irq) { - if (mpt_msi_enable && !pci_enable_msi(pdev)) - printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", ioc->name); - - r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc); - - if (r < 0) { -#ifndef __sparc__ - printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n", - ioc->name, pdev->irq); -#else - printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n", - ioc->name, __irq_itoa(pdev->irq)); -#endif - list_del(&ioc->list); - iounmap(mem); - kfree(ioc); - return -EBUSY; - } - - ioc->pci_irq = pdev->irq; - - pci_set_master(pdev); /* ?? */ - pci_set_drvdata(pdev, ioc); - -#ifndef __sparc__ - dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq)); -#else - dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq))); -#endif - } - /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets. */ mpt_detect_bound_ports(ioc, pdev); @@ -1429,11 +1396,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) printk(KERN_WARNING MYNAM ": WARNING - %s did not initialize properly! (%d)\n", ioc->name, r); - list_del(&ioc->list); - free_irq(ioc->pci_irq, ioc); - if (mpt_msi_enable) - pci_disable_msi(pdev); if (ioc->alt_ioc) ioc->alt_ioc->alt_ioc = NULL; iounmap(mem); @@ -1637,6 +1600,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) int handlers; int ret = 0; int reset_alt_ioc_active = 0; + int irq_allocated = 0; printk(KERN_INFO MYNAM ": Initiating %s %s\n", ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery"); @@ -1720,6 +1684,48 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) } } + /* + * Device is reset now. It must have de-asserted the interrupt line + * (if it was asserted) and it should be safe to register for the + * interrupt now. + */ + if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { + ioc->pci_irq = -1; + if (ioc->pcidev->irq) { + if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev)) + printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", + ioc->name); + rc = request_irq(ioc->pcidev->irq, mpt_interrupt, + SA_SHIRQ, ioc->name, ioc); + if (rc < 0) { +#ifndef __sparc__ + printk(MYIOC_s_ERR_FMT "Unable to allocate " + "interrupt %d!\n", ioc->name, + ioc->pcidev->irq); +#else + printk(MYIOC_s_ERR_FMT "Unable to allocate " + "interrupt %s!\n", ioc->name, + __irq_itoa(ioc->pcidev->irq)); +#endif + if (mpt_msi_enable) + pci_disable_msi(ioc->pcidev); + return -EBUSY; + } + irq_allocated = 1; + ioc->pci_irq = ioc->pcidev->irq; + pci_set_master(ioc->pcidev); /* ?? */ + pci_set_drvdata(ioc->pcidev, ioc); +#ifndef __sparc__ + dprintk((KERN_INFO MYNAM ": %s installed at interrupt " + "%d\n", ioc->name, ioc->pcidev->irq)); +#else + dprintk((KERN_INFO MYNAM ": %s installed at interrupt " + "%s\n", ioc->name, + __irq_itoa(ioc->pcidev->irq))); +#endif + } + } + /* Prime reply & request queues! * (mucho alloc's) Must be done prior to * init as upper addresses are needed for init. @@ -1819,7 +1825,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) ret = mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); if(ret != 0) - return -1; + goto out; } /* Find IM volumes @@ -1900,6 +1906,12 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) /* FIXME? Examine results here? */ } +out: + if ((ret != 0) && irq_allocated) { + free_irq(ioc->pci_irq, ioc); + if (mpt_msi_enable) + pci_disable_msi(ioc->pcidev); + } return ret; } -- cgit v1.2.1 From c29ca9d1812f2abacaefa7daa31e085600128938 Mon Sep 17 00:00:00 2001 From: "Tom \"spot\" Callaway" Date: Fri, 9 Jun 2006 17:01:48 -0700 Subject: [FUSION]: Fix mptspi.c build with CONFIG_PM not set. Signed-off-by: Tom "spot" Callaway Signed-off-by: David S. Miller --- drivers/message/fusion/mptspi.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index f2a4d382ea19..3201de053943 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -831,6 +831,7 @@ mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) return rc; } +#ifdef CONFIG_PM /* * spi module resume handler */ @@ -846,6 +847,7 @@ mptspi_resume(struct pci_dev *pdev) return rc; } +#endif /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -- cgit v1.2.1 From 57a62fed871eb2a95f296fe6c5c250ce21b81a79 Mon Sep 17 00:00:00 2001 From: Markus Lidel Date: Sat, 10 Jun 2006 09:54:14 -0700 Subject: [PATCH] I2O: Bugfixes to get I2O working again From: Markus Lidel - Fixed locking of struct i2o_exec_wait in Executive-OSM - Removed LCT Notify in i2o_exec_probe() which caused freeing memory and accessing freed memory during first enumeration of I2O devices - Added missing locking in i2o_exec_lct_notify() - removed put_device() of I2O controller in i2o_iop_remove() which caused the controller structure get freed to early - Fixed size of mempool in i2o_iop_alloc() - Fixed access to freed memory in i2o_msg_get() See http://bugzilla.kernel.org/show_bug.cgi?id=6561 Signed-off-by: Markus Lidel Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/message/i2o/exec-osm.c | 72 ++++++++++++++++++++++-------------------- drivers/message/i2o/iop.c | 4 +-- 2 files changed, 38 insertions(+), 38 deletions(-) (limited to 'drivers/message') diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 5ea133c59afb..7bd4d85d0b42 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -55,6 +55,7 @@ struct i2o_exec_wait { u32 m; /* message id */ struct i2o_message *msg; /* pointer to the reply message */ struct list_head list; /* node in global wait list */ + spinlock_t lock; /* lock before modifying */ }; /* Work struct needed to handle LCT NOTIFY replies */ @@ -87,6 +88,7 @@ static struct i2o_exec_wait *i2o_exec_wait_alloc(void) return NULL; INIT_LIST_HEAD(&wait->list); + spin_lock_init(&wait->lock); return wait; }; @@ -125,6 +127,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg, DECLARE_WAIT_QUEUE_HEAD(wq); struct i2o_exec_wait *wait; static u32 tcntxt = 0x80000000; + long flags; int rc = 0; wait = i2o_exec_wait_alloc(); @@ -146,33 +149,28 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg, wait->tcntxt = tcntxt++; msg->u.s.tcntxt = cpu_to_le32(wait->tcntxt); + wait->wq = &wq; + /* + * we add elements to the head, because if a entry in the list will + * never be removed, we have to iterate over it every time + */ + list_add(&wait->list, &i2o_exec_wait_list); + /* * Post the message to the controller. At some point later it will * return. If we time out before it returns then complete will be zero. */ i2o_msg_post(c, msg); - if (!wait->complete) { - wait->wq = &wq; - /* - * we add elements add the head, because if a entry in the list - * will never be removed, we have to iterate over it every time - */ - list_add(&wait->list, &i2o_exec_wait_list); - - wait_event_interruptible_timeout(wq, wait->complete, - timeout * HZ); + wait_event_interruptible_timeout(wq, wait->complete, timeout * HZ); - wait->wq = NULL; - } + spin_lock_irqsave(&wait->lock, flags); - barrier(); + wait->wq = NULL; - if (wait->complete) { + if (wait->complete) rc = le32_to_cpu(wait->msg->body[0]) >> 24; - i2o_flush_reply(c, wait->m); - i2o_exec_wait_free(wait); - } else { + else { /* * We cannot remove it now. This is important. When it does * terminate (which it must do if the controller has not @@ -186,6 +184,13 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg, rc = -ETIMEDOUT; } + spin_unlock_irqrestore(&wait->lock, flags); + + if (rc != -ETIMEDOUT) { + i2o_flush_reply(c, wait->m); + i2o_exec_wait_free(wait); + } + return rc; }; @@ -213,7 +218,6 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, { struct i2o_exec_wait *wait, *tmp; unsigned long flags; - static spinlock_t lock = SPIN_LOCK_UNLOCKED; int rc = 1; /* @@ -223,23 +227,24 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, * already expired. Not much we can do about that except log it for * debug purposes, increase timeout, and recompile. */ - spin_lock_irqsave(&lock, flags); list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) { if (wait->tcntxt == context) { - list_del(&wait->list); + spin_lock_irqsave(&wait->lock, flags); - spin_unlock_irqrestore(&lock, flags); + list_del(&wait->list); wait->m = m; wait->msg = msg; wait->complete = 1; - barrier(); - - if (wait->wq) { - wake_up_interruptible(wait->wq); + if (wait->wq) rc = 0; - } else { + else + rc = -1; + + spin_unlock_irqrestore(&wait->lock, flags); + + if (rc) { struct device *dev; dev = &c->pdev->dev; @@ -248,15 +253,13 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, c->name); i2o_dma_free(dev, &wait->dma); i2o_exec_wait_free(wait); - rc = -1; - } + } else + wake_up_interruptible(wait->wq); return rc; } } - spin_unlock_irqrestore(&lock, flags); - osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name, context); @@ -322,14 +325,9 @@ static DEVICE_ATTR(product_id, S_IRUGO, i2o_exec_show_product_id, NULL); static int i2o_exec_probe(struct device *dev) { struct i2o_device *i2o_dev = to_i2o_device(dev); - struct i2o_controller *c = i2o_dev->iop; i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff); - c->exec = i2o_dev; - - i2o_exec_lct_notify(c, c->lct->change_ind + 1); - device_create_file(dev, &dev_attr_vendor_id); device_create_file(dev, &dev_attr_product_id); @@ -523,6 +521,8 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) struct device *dev; struct i2o_message *msg; + down(&c->lct_lock); + dev = &c->pdev->dev; if (i2o_dma_realloc @@ -545,6 +545,8 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) i2o_msg_post(c, msg); + up(&c->lct_lock); + return 0; }; diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index 492167446936..febbdd4e0605 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c @@ -804,8 +804,6 @@ void i2o_iop_remove(struct i2o_controller *c) /* Ask the IOP to switch to RESET state */ i2o_iop_reset(c); - - put_device(&c->device); } /** @@ -1059,7 +1057,7 @@ struct i2o_controller *i2o_iop_alloc(void) snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name); if (i2o_pool_alloc - (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4, + (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4 + sizeof(u32), I2O_MSG_INPOOL_MIN)) { kfree(c); return ERR_PTR(-ENOMEM); -- cgit v1.2.1 From 80d3ac77a84987d5132726f3d7cef342a280f7d9 Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Wed, 24 May 2006 15:07:09 -0500 Subject: [SCSI] mptfusion: move fc event/reset handling to mptfc Move fibre channel event and reset handling to mptfc. This will result in fewer changes over time that need to be applied to either mptbase.c or mptscsih.c. Signed-off-by: Michael Reed Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 112 ----------------------- drivers/message/fusion/mptbase.h | 1 - drivers/message/fusion/mptfc.c | 187 +++++++++++++++++++++++++++++++++++++- drivers/message/fusion/mptscsih.c | 21 ----- 4 files changed, 184 insertions(+), 137 deletions(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 164375eea896..330c29080e3c 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1188,7 +1188,6 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ioc->pcidev = pdev; ioc->diagPending = 0; spin_lock_init(&ioc->diagLock); - spin_lock_init(&ioc->fc_rescan_work_lock); spin_lock_init(&ioc->initializing_hba_lock); /* Initialize the event logging. @@ -1847,14 +1846,6 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) mpt_findImVolumes(ioc); } else if (ioc->bus_type == FC) { - /* - * Pre-fetch FC port WWN and stuff... - * (FCPortPage0_t stuff) - */ - for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { - (void) mptbase_GetFcPortPage0(ioc, ii); - } - if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) && (ioc->lan_cnfg_page0.Header.PageLength == 0)) { /* @@ -4184,108 +4175,6 @@ GetLanConfigPages(MPT_ADAPTER *ioc) return rc; } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptbase_GetFcPortPage0 - Fetch FCPort config Page0. - * @ioc: Pointer to MPT_ADAPTER structure - * @portnum: IOC Port number - * - * Return: 0 for success - * -ENOMEM if no memory available - * -EPERM if not allowed due to ISR context - * -EAGAIN if no msg frames currently available - * -EFAULT for non-successful reply or no reply (timeout) - */ -int -mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) -{ - ConfigPageHeader_t hdr; - CONFIGPARMS cfg; - FCPortPage0_t *ppage0_alloc; - FCPortPage0_t *pp0dest; - dma_addr_t page0_dma; - int data_sz; - int copy_sz; - int rc; - int count = 400; - - - /* Get FCPort Page 0 header */ - hdr.PageVersion = 0; - hdr.PageLength = 0; - hdr.PageNumber = 0; - hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; - cfg.cfghdr.hdr = &hdr; - cfg.physAddr = -1; - cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; - cfg.dir = 0; - cfg.pageAddr = portnum; - cfg.timeout = 0; - - if ((rc = mpt_config(ioc, &cfg)) != 0) - return rc; - - if (hdr.PageLength == 0) - return 0; - - data_sz = hdr.PageLength * 4; - rc = -ENOMEM; - ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma); - if (ppage0_alloc) { - - try_again: - memset((u8 *)ppage0_alloc, 0, data_sz); - cfg.physAddr = page0_dma; - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - - if ((rc = mpt_config(ioc, &cfg)) == 0) { - /* save the data */ - pp0dest = &ioc->fc_port_page0[portnum]; - copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz); - memcpy(pp0dest, ppage0_alloc, copy_sz); - - /* - * Normalize endianness of structure data, - * by byte-swapping all > 1 byte fields! - */ - pp0dest->Flags = le32_to_cpu(pp0dest->Flags); - pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier); - pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low); - pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High); - pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low); - pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High); - pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass); - pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds); - pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed); - pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize); - pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low); - pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High); - pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low); - pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High); - pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount); - pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators); - - /* - * if still doing discovery, - * hang loose a while until finished - */ - if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) { - if (count-- > 0) { - msleep_interruptible(100); - goto try_again; - } - printk(MYIOC_s_INFO_FMT "Firmware discovery not" - " complete.\n", - ioc->name); - } - } - - pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); - } - - return rc; -} - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table @@ -6495,7 +6384,6 @@ EXPORT_SYMBOL(mpt_findImVolumes); EXPORT_SYMBOL(mpt_alloc_fw_memory); EXPORT_SYMBOL(mpt_free_fw_memory); EXPORT_SYMBOL(mptbase_sas_persist_operation); -EXPORT_SYMBOL(mptbase_GetFcPortPage0); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index f673cca507e1..693c95c9034a 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -1027,7 +1027,6 @@ extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size); extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); extern int mpt_findImVolumes(MPT_ADAPTER *ioc); extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); -extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); /* * Public data decl's... diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 856487741ef4..e518bc97f8ce 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -596,6 +596,110 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) return err; } +/* + * mptfc_GetFcPortPage0 - Fetch FCPort config Page0. + * @ioc: Pointer to MPT_ADAPTER structure + * @portnum: IOC Port number + * + * Return: 0 for success + * -ENOMEM if no memory available + * -EPERM if not allowed due to ISR context + * -EAGAIN if no msg frames currently available + * -EFAULT for non-successful reply or no reply (timeout) + * -EINVAL portnum arg out of range (hardwired to two elements) + */ +static int +mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) +{ + ConfigPageHeader_t hdr; + CONFIGPARMS cfg; + FCPortPage0_t *ppage0_alloc; + FCPortPage0_t *pp0dest; + dma_addr_t page0_dma; + int data_sz; + int copy_sz; + int rc; + int count = 400; + + if (portnum > 1) + return -EINVAL; + + /* Get FCPort Page 0 header */ + hdr.PageVersion = 0; + hdr.PageLength = 0; + hdr.PageNumber = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; + cfg.cfghdr.hdr = &hdr; + cfg.physAddr = -1; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; + cfg.pageAddr = portnum; + cfg.timeout = 0; + + if ((rc = mpt_config(ioc, &cfg)) != 0) + return rc; + + if (hdr.PageLength == 0) + return 0; + + data_sz = hdr.PageLength * 4; + rc = -ENOMEM; + ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma); + if (ppage0_alloc) { + + try_again: + memset((u8 *)ppage0_alloc, 0, data_sz); + cfg.physAddr = page0_dma; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + if ((rc = mpt_config(ioc, &cfg)) == 0) { + /* save the data */ + pp0dest = &ioc->fc_port_page0[portnum]; + copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz); + memcpy(pp0dest, ppage0_alloc, copy_sz); + + /* + * Normalize endianness of structure data, + * by byte-swapping all > 1 byte fields! + */ + pp0dest->Flags = le32_to_cpu(pp0dest->Flags); + pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier); + pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low); + pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High); + pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low); + pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High); + pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass); + pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds); + pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed); + pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize); + pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low); + pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High); + pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low); + pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High); + pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount); + pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators); + + /* + * if still doing discovery, + * hang loose a while until finished + */ + if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) { + if (count-- > 0) { + msleep_interruptible(100); + goto try_again; + } + printk(MYIOC_s_INFO_FMT "Firmware discovery not" + " complete.\n", + ioc->name); + } + } + + pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); + } + + return rc; +} + static void mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) { @@ -651,7 +755,7 @@ mptfc_rescan_devices(void *arg) * will reregister existing rports */ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { - (void) mptbase_GetFcPortPage0(ioc, ii); + (void) mptfc_GetFcPortPage0(ioc, ii); mptfc_init_host_attr(ioc,ii); /* refresh */ mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev); } @@ -753,6 +857,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto out_mptfc_probe; } + spin_lock_init(&ioc->fc_rescan_work_lock); INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc); spin_lock_irqsave(&ioc->FreeQlock, flags); @@ -888,6 +993,14 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (!ioc->fc_rescan_work_q) goto out_mptfc_probe; + /* + * Pre-fetch FC port WWN and stuff... + * (FCPortPage0_t stuff) + */ + for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { + (void) mptfc_GetFcPortPage0(ioc, ii); + } + /* * scan for rports - * by doing it via the workqueue, some locking is eliminated @@ -917,6 +1030,74 @@ static struct pci_driver mptfc_driver = { #endif }; +static int +mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) +{ + MPT_SCSI_HOST *hd; + u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; + unsigned long flags; + int rc=1; + + devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", + ioc->name, event)); + + if (ioc->sh == NULL || + ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) + return 1; + + switch (event) { + case MPI_EVENT_RESCAN: + spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); + if (ioc->fc_rescan_work_q) { + if (ioc->fc_rescan_work_count++ == 0) { + queue_work(ioc->fc_rescan_work_q, + &ioc->fc_rescan_work); + } + } + spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); + break; + default: + rc = mptscsih_event_process(ioc,pEvReply); + break; + } + return rc; +} + +static int +mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) +{ + int rc; + unsigned long flags; + + rc = mptscsih_ioc_reset(ioc,reset_phase); + if (rc == 0) + return rc; + + + dtmprintk((KERN_WARNING MYNAM + ": IOC %s_reset routed to FC host driver!\n", + reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( + reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); + + if (reset_phase == MPT_IOC_SETUP_RESET) { + } + + else if (reset_phase == MPT_IOC_PRE_RESET) { + } + + else { /* MPT_IOC_POST_RESET */ + spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); + if (ioc->fc_rescan_work_q) { + if (ioc->fc_rescan_work_count++ == 0) { + queue_work(ioc->fc_rescan_work_q, + &ioc->fc_rescan_work); + } + } + spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); + } + return 1; +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptfc_init - Register MPT adapter(s) as SCSI host(s) with @@ -945,12 +1126,12 @@ mptfc_init(void) mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER); mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); - if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) { + if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) { devtverboseprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); } - if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) { + if (mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset) == 0) { dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n")); } diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 84fa271eb8f4..2d81831cf628 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -2521,18 +2521,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) hd->cmdPtr = NULL; } - /* 7. FC: Rescan for blocked rports which might have returned. - */ - if (ioc->bus_type == FC) { - spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); - if (ioc->fc_rescan_work_q) { - if (ioc->fc_rescan_work_count++ == 0) { - queue_work(ioc->fc_rescan_work_q, - &ioc->fc_rescan_work); - } - } - spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); - } dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name)); } @@ -2546,7 +2534,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) { MPT_SCSI_HOST *hd; u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; - unsigned long flags; devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", ioc->name, event)); @@ -2569,14 +2556,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) break; case MPI_EVENT_RESCAN: /* 06 */ - spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); - if (ioc->fc_rescan_work_q) { - if (ioc->fc_rescan_work_count++ == 0) { - queue_work(ioc->fc_rescan_work_q, - &ioc->fc_rescan_work); - } - } - spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); break; /* -- cgit v1.2.1 From ca2f938efe71ca48cbc689db4df8d4f04b5d8f07 Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Wed, 24 May 2006 15:07:24 -0500 Subject: [SCSI] mptfc: set fibre channel fw target missing timers to one second The fibre channel firmware provides a timer which is similar in purpose to the fibre channel transport's device loss timer. The effect of this timer is to extend the total time that a target will be missing beyond the value associated with the transport's timer. This patch changes the firmware timer to a default of one second which significantly reduces the lag between when a target goes missing and the notification of the fibre channel transport. Signed-off-by: Michael Reed Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 10 +++ drivers/message/fusion/mptfc.c | 171 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 172 insertions(+), 9 deletions(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 693c95c9034a..29f6b986946f 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -487,6 +487,15 @@ typedef struct _RaidCfgData { int isRaid; /* bit field, 1 if RAID */ }RaidCfgData; +typedef struct _FcCfgData { + /* will ultimately hold fc_port_page0 also */ + struct { + FCPortPage1_t *data; + dma_addr_t dma; + int pg_sz; + } fc_port_page1[2]; +} FcCfgData; + #define MPT_RPORT_INFO_FLAGS_REGISTERED 0x01 /* rport registered */ #define MPT_RPORT_INFO_FLAGS_MISSING 0x02 /* missing from DevPage0 scan */ @@ -565,6 +574,7 @@ typedef struct _MPT_ADAPTER SpiCfgData spi_data; /* Scsi config. data */ RaidCfgData raid_data; /* Raid config. data */ SasCfgData sas_data; /* Sas config. data */ + FcCfgData fc_data; /* Fc config. data */ MPT_IOCTL *ioctl; /* ioctl data pointer */ struct proc_dir_entry *ioc_dentry; struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */ diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index e518bc97f8ce..918aca0146ff 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -169,13 +169,6 @@ static struct fc_function_template mptfc_transport_functions = { }; -/* FIXME! values controlling firmware RESCAN event - * need to be set low to allow dev_loss_tmo to - * work as expected. Currently, firmware doesn't - * notify driver of RESCAN event until some number - * of seconds elapse. This value can be set via - * lsiutil. - */ static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) { @@ -700,6 +693,153 @@ mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) return rc; } +static int +mptfc_WriteFcPortPage1(MPT_ADAPTER *ioc, int portnum) +{ + ConfigPageHeader_t hdr; + CONFIGPARMS cfg; + int rc; + + if (portnum > 1) + return -EINVAL; + + if (!(ioc->fc_data.fc_port_page1[portnum].data)) + return -EINVAL; + + /* get fcport page 1 header */ + hdr.PageVersion = 0; + hdr.PageLength = 0; + hdr.PageNumber = 1; + hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; + cfg.cfghdr.hdr = &hdr; + cfg.physAddr = -1; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; + cfg.pageAddr = portnum; + cfg.timeout = 0; + + if ((rc = mpt_config(ioc, &cfg)) != 0) + return rc; + + if (hdr.PageLength == 0) + return -ENODEV; + + if (hdr.PageLength*4 != ioc->fc_data.fc_port_page1[portnum].pg_sz) + return -EINVAL; + + cfg.physAddr = ioc->fc_data.fc_port_page1[portnum].dma; + cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; + cfg.dir = 1; + + rc = mpt_config(ioc, &cfg); + + return rc; +} + +static int +mptfc_GetFcPortPage1(MPT_ADAPTER *ioc, int portnum) +{ + ConfigPageHeader_t hdr; + CONFIGPARMS cfg; + FCPortPage1_t *page1_alloc; + dma_addr_t page1_dma; + int data_sz; + int rc; + + if (portnum > 1) + return -EINVAL; + + /* get fcport page 1 header */ + hdr.PageVersion = 0; + hdr.PageLength = 0; + hdr.PageNumber = 1; + hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; + cfg.cfghdr.hdr = &hdr; + cfg.physAddr = -1; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; + cfg.pageAddr = portnum; + cfg.timeout = 0; + + if ((rc = mpt_config(ioc, &cfg)) != 0) + return rc; + + if (hdr.PageLength == 0) + return -ENODEV; + +start_over: + + if (ioc->fc_data.fc_port_page1[portnum].data == NULL) { + data_sz = hdr.PageLength * 4; + if (data_sz < sizeof(FCPortPage1_t)) + data_sz = sizeof(FCPortPage1_t); + + page1_alloc = (FCPortPage1_t *) pci_alloc_consistent(ioc->pcidev, + data_sz, + &page1_dma); + if (!page1_alloc) + return -ENOMEM; + } + else { + page1_alloc = ioc->fc_data.fc_port_page1[portnum].data; + page1_dma = ioc->fc_data.fc_port_page1[portnum].dma; + data_sz = ioc->fc_data.fc_port_page1[portnum].pg_sz; + if (hdr.PageLength * 4 > data_sz) { + ioc->fc_data.fc_port_page1[portnum].data = NULL; + pci_free_consistent(ioc->pcidev, data_sz, (u8 *) + page1_alloc, page1_dma); + goto start_over; + } + } + + memset(page1_alloc,0,data_sz); + + cfg.physAddr = page1_dma; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + if ((rc = mpt_config(ioc, &cfg)) == 0) { + ioc->fc_data.fc_port_page1[portnum].data = page1_alloc; + ioc->fc_data.fc_port_page1[portnum].pg_sz = data_sz; + ioc->fc_data.fc_port_page1[portnum].dma = page1_dma; + } + else { + ioc->fc_data.fc_port_page1[portnum].data = NULL; + pci_free_consistent(ioc->pcidev, data_sz, (u8 *) + page1_alloc, page1_dma); + } + + return rc; +} + +static void +mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc) +{ + int ii; + FCPortPage1_t *pp1; + + #define MPTFC_FW_DEVICE_TIMEOUT (1) + #define MPTFC_FW_IO_PEND_TIMEOUT (1) + #define ON_FLAGS (MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY) + #define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS) + + for (ii=0; iifacts.NumberOfPorts; ii++) { + if (mptfc_GetFcPortPage1(ioc, ii) != 0) + continue; + pp1 = ioc->fc_data.fc_port_page1[ii].data; + if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT) + && (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT) + && ((pp1->Flags & ON_FLAGS) == ON_FLAGS) + && ((pp1->Flags & OFF_FLAGS) == 0)) + continue; + pp1->InitiatorDeviceTimeout = MPTFC_FW_DEVICE_TIMEOUT; + pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT; + pp1->Flags &= ~OFF_FLAGS; + pp1->Flags |= ON_FLAGS; + mptfc_WriteFcPortPage1(ioc, ii); + } +} + + static void mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) { @@ -1000,6 +1140,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { (void) mptfc_GetFcPortPage0(ioc, ii); } + mptfc_SetFcPortPage1_defaults(ioc); /* * scan for rports - @@ -1086,6 +1227,7 @@ mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) } else { /* MPT_IOC_POST_RESET */ + mptfc_SetFcPortPage1_defaults(ioc); spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); if (ioc->fc_rescan_work_q) { if (ioc->fc_rescan_work_count++ == 0) { @@ -1112,8 +1254,8 @@ mptfc_init(void) show_mptmod_ver(my_NAME, my_VERSION); - /* sanity check module parameter */ - if (mptfc_dev_loss_tmo == 0) + /* sanity check module parameters */ + if (mptfc_dev_loss_tmo <= 0) mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; mptfc_transport_template = @@ -1156,6 +1298,7 @@ mptfc_remove(struct pci_dev *pdev) struct mptfc_rport_info *p, *n; struct workqueue_struct *work_q; unsigned long flags; + int ii; /* destroy workqueue */ if ((work_q=ioc->fc_rescan_work_q)) { @@ -1172,6 +1315,16 @@ mptfc_remove(struct pci_dev *pdev) kfree(p); } + for (ii=0; iifacts.NumberOfPorts; ii++) { + if (ioc->fc_data.fc_port_page1[ii].data) { + pci_free_consistent(ioc->pcidev, + ioc->fc_data.fc_port_page1[ii].pg_sz, + (u8 *) ioc->fc_data.fc_port_page1[ii].data, + ioc->fc_data.fc_port_page1[ii].dma); + ioc->fc_data.fc_port_page1[ii].data = NULL; + } + } + mptscsih_remove(pdev); } -- cgit v1.2.1 From 419835e285c3e39cd62c8c8426da0aebea9cd89f Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Wed, 24 May 2006 15:07:40 -0500 Subject: [SCSI] mptfc: fix fibre channel infinite request/response loop While doing board reset testing I was able to put the system in an infinite request/response loop between the scsi layer and mptscsih_qcmd() by aborting the reset. This patch installs a "SETUP RESET" handler which calls fc_remote_port_delete() for all registered rports. This blocks the target which prevents the loop. Additionally, should the reset fail to complete, the transport will now terminate i/o to the target. Signed-off-by: Michael Reed Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 1 + drivers/message/fusion/mptfc.c | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 29f6b986946f..6d36ff5ee721 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -635,6 +635,7 @@ typedef struct _MPT_ADAPTER int num_ports; struct work_struct mptscsih_persistTask; + struct work_struct fc_setup_reset_work; struct list_head fc_rports; spinlock_t fc_rescan_work_lock; int fc_rescan_work_count; diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 918aca0146ff..770df553047a 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -580,10 +580,10 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) #ifdef DMPT_DEBUG_FC if (unlikely(err)) { dfcprintk ((MYIOC_s_INFO_FMT - "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero.\n", + "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero, (%x).\n", ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name, ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no, - SCpnt->device->id,SCpnt->device->lun)); + SCpnt->device->id,SCpnt->device->lun,err)); } #endif return err; @@ -872,6 +872,31 @@ mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN; } +static void +mptfc_setup_reset(void *arg) +{ + MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + u64 pn; + struct mptfc_rport_info *ri; + + /* reset about to happen, delete (block) all rports */ + list_for_each_entry(ri, &ioc->fc_rports, list) { + if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) { + ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED; + fc_remote_port_delete(ri->rport); /* won't sleep */ + ri->rport = NULL; + + pn = (u64)ri->pg0.WWPN.High << 32 | + (u64)ri->pg0.WWPN.Low; + dfcprintk ((MYIOC_s_INFO_FMT + "mptfc_setup_reset.%d: %llx deleted\n", + ioc->name, + ioc->sh->host_no, + (unsigned long long)pn)); + } + } +} + static void mptfc_rescan_devices(void *arg) { @@ -999,6 +1024,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) spin_lock_init(&ioc->fc_rescan_work_lock); INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc); + INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset, (void *)ioc); spin_lock_irqsave(&ioc->FreeQlock, flags); @@ -1221,6 +1247,12 @@ mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); if (reset_phase == MPT_IOC_SETUP_RESET) { + spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); + if (ioc->fc_rescan_work_q) { + queue_work(ioc->fc_rescan_work_q, + &ioc->fc_setup_reset_work); + } + spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); } else if (reset_phase == MPT_IOC_PRE_RESET) { -- cgit v1.2.1 From d6be06c84da9626b10443c664ee55bda96fb3514 Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Wed, 24 May 2006 15:07:57 -0500 Subject: [SCSI] mptfc: abort of board reset leaves port dead requiring reboot The driver uses msleep_interruptible() in the code path responsible for resetting the card's ports via the lsiutil command. If a is received during the reset it can leave a port in such a state that the only way to regain its use is to reboot the system. Changing from msleep_interruptible() to msleep() corrects the problem. Signed-off-by: Michael Reed Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 30 +++++++++++++++--------------- drivers/message/fusion/mptfc.c | 2 +- drivers/message/fusion/mptscsih.c | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 330c29080e3c..08779d79a1f0 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -2291,7 +2291,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) } if (sleepFlag == CAN_SLEEP) { - msleep_interruptible(1); + msleep(1); } else { mdelay (1); /* 1 msec delay */ } @@ -2679,7 +2679,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) state = mpt_GetIocState(ioc, 1); while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) { if (sleepFlag == CAN_SLEEP) { - msleep_interruptible(1); + msleep(1); } else { mdelay(1); } @@ -2931,7 +2931,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) /* wait 1 msec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible(1); + msleep(1); } else { mdelay (1); } @@ -2948,7 +2948,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) } /* wait .1 sec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (100); + msleep (100); } else { mdelay (100); } @@ -3038,7 +3038,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) /* wait 1 msec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (1); + msleep (1); } else { mdelay (1); } @@ -3086,7 +3086,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) return 0; } if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (10); + msleep (10); } else { mdelay (10); } @@ -3137,7 +3137,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag); if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (1000); + msleep (1000); } else { mdelay (1000); } @@ -3159,7 +3159,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) return hard_reset_done; } if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (10); + msleep (10); } else { mdelay (10); } @@ -3230,7 +3230,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* wait 100 msec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (100); + msleep (100); } else { mdelay (100); } @@ -3309,7 +3309,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* wait 1 sec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (1000); + msleep (1000); } else { mdelay (1000); } @@ -3337,7 +3337,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* wait 1 sec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (1000); + msleep (1000); } else { mdelay (1000); } @@ -3371,7 +3371,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* wait 100 msec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (100); + msleep (100); } else { mdelay (100); } @@ -3465,7 +3465,7 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) } if (sleepFlag == CAN_SLEEP) { - msleep_interruptible(1); + msleep(1); } else { mdelay (1); /* 1 msec delay */ } @@ -3905,7 +3905,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) intstat = CHIPREG_READ32(&ioc->chip->IntStatus); if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS)) break; - msleep_interruptible (1); + msleep (1); count++; } } else { @@ -3954,7 +3954,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) intstat = CHIPREG_READ32(&ioc->chip->IntStatus); if (intstat & MPI_HIS_DOORBELL_INTERRUPT) break; - msleep_interruptible(1); + msleep(1); count++; } } else { diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 770df553047a..74714e5bcf03 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -678,7 +678,7 @@ mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) */ if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) { if (count-- > 0) { - msleep_interruptible(100); + msleep(100); goto try_again; } printk(MYIOC_s_INFO_FMT "Firmware discovery not" diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 2d81831cf628..8242b16e3168 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1922,7 +1922,7 @@ mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ) break; } spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - msleep_interruptible(250); + msleep(250); } while (--loop_count); return status; -- cgit v1.2.1 From 1951d099dfd8fa529e86f4ac81d1a34554fbe302 Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Wed, 24 May 2006 15:08:10 -0500 Subject: [SCSI] mptfusion: change driver revision to 3.03.10 Bump driver version number to reflect addition of various fibre channel patches. Signed-off-by: Michael Reed Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 6d36ff5ee721..4720f9ae86aa 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -76,8 +76,8 @@ #define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.03.09" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.09" +#define MPT_LINUX_VERSION_COMMON "3.03.10" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.10" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ -- cgit v1.2.1 From beb40487508290f5d6565598c60a3f44261beef2 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 10 Jun 2006 18:01:03 +0200 Subject: [SCSI] remove scsi_request infrastructure With Achim patch the last user (gdth) is switched away from scsi_request so we an kill it now. Also disables some code in i2o_scsi that was broken since the sg driver stopped using scsi_requests. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/message/i2o/i2o_scsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/message') diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index c08ddac3717d..6ebf38213f9f 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c @@ -65,9 +65,7 @@ #include #include #include -#include #include -#include #define OSM_NAME "scsi-osm" #define OSM_VERSION "1.316" @@ -588,6 +586,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, mptr = &msg->body[0]; +#if 0 /* this code can't work */ #ifdef CONFIG_I2O_EXT_ADAPTEC if (c->adaptec) { u32 adpt_flags = 0; @@ -624,6 +623,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC); *mptr++ = cpu_to_le32(adpt_flags | tid); } +#endif #endif msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid); -- cgit v1.2.1 From c6387a48cf5958e43c201fc27a158c328927531a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 20 Jun 2006 01:21:29 -0700 Subject: [SPARC]: Kill __irq_itoa(). This ugly hack was long overdue to die. It was a way to print out Sparc interrupts in a more freindly format, since IRQ numbers were arbitrary opaque 32-bit integers which vectored into PIL levels. These 32-bit integers were not necessarily in the 0-->NR_IRQS range, but the PILs they vectored to were. The idea now is that we will increase NR_IRQS a little bit and use a virtual<-->real IRQ number mapping scheme similar to PowerPC. That makes this IRQ printing hack irrelevant, and furthermore only a handful of drivers actually used __irq_itoa() making it even less useful. Signed-off-by: David S. Miller --- drivers/message/fusion/mptbase.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'drivers/message') diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index a30084076ac8..59690cbabfca 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -63,9 +63,6 @@ #ifdef CONFIG_MTRR #include #endif -#ifdef __sparc__ -#include /* needed for __irq_itoa() proto */ -#endif #include "mptbase.h" @@ -1394,13 +1391,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc); if (r < 0) { -#ifndef __sparc__ printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n", ioc->name, pdev->irq); -#else - printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n", - ioc->name, __irq_itoa(pdev->irq)); -#endif list_del(&ioc->list); iounmap(mem); kfree(ioc); @@ -1412,11 +1404,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_master(pdev); /* ?? */ pci_set_drvdata(pdev, ioc); -#ifndef __sparc__ dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq)); -#else - dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq))); -#endif } /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets. @@ -5647,11 +5635,7 @@ mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int sh a[5], a[4], a[3], a[2], a[1], a[0]); } -#ifndef __sparc__ y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq); -#else - y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq)); -#endif if (!ioc->active) y += sprintf(buffer+len+y, " (disabled)"); -- cgit v1.2.1