From 8418852d11f0bbaeebeedd4243560d8fdc85410d Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Thu, 15 Mar 2007 10:26:05 -0700 Subject: [SCSI] aacraid: add restart adapter platform function Received from Mark Salyzyn, This patch updates the adapter restart function to deal with some adapters that have specific IOP reset needs. Since the code for restarting the adapter was in two places, changed over to utilizing a platform function in one place. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/rx.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) (limited to 'drivers/scsi/aacraid/rx.c') diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index d242e2611d6..00e3cba9d8e 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -460,22 +460,31 @@ static int aac_rx_ioremap(struct aac_dev * dev, u32 size) return 0; } -static int aac_rx_restart_adapter(struct aac_dev *dev) +static int aac_rx_restart_adapter(struct aac_dev *dev, int bled) { u32 var; - printk(KERN_ERR "%s%d: adapter kernel panic'd.\n", - dev->name, dev->id); - - if (aac_rx_check_health(dev) <= 0) - return 1; - if (rx_sync_cmd(dev, IOP_RESET, 0, 0, 0, 0, 0, 0, - &var, NULL, NULL, NULL, NULL)) - return 1; + if (bled) + printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n", + dev->name, dev->id, bled); + else + bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, + 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); + if (bled) + bled = aac_adapter_sync_cmd(dev, IOP_RESET, + 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); + + if (bled) + return -EINVAL; + if (var == 0x3803000F) { /* USE_OTHER_METHOD */ + rx_writel(dev, MUnit.reserved2, 3); + msleep(5000); /* Delay 5 seconds */ + var = 0x00000001; + } if (var != 0x00000001) - return 1; + return -EINVAL; if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) - return 1; + return -ENODEV; return 0; } @@ -532,9 +541,12 @@ int _aac_rx_init(struct aac_dev *dev) * Check to see if the board panic'd while booting. */ status = rx_readl(dev, MUnit.OMRx[0]); - if (status & KERNEL_PANIC) - if (aac_rx_restart_adapter(dev)) + if (status & KERNEL_PANIC) { + if ((status = aac_rx_check_health(dev)) <= 0) goto error_iounmap; + if (aac_rx_restart_adapter(dev, status)) + goto error_iounmap; + } /* * Check to see if the board failed any self tests. */ @@ -572,6 +584,7 @@ int _aac_rx_init(struct aac_dev *dev) dev->a_ops.adapter_notify = aac_rx_notify_adapter; dev->a_ops.adapter_sync_cmd = rx_sync_cmd; dev->a_ops.adapter_check_health = aac_rx_check_health; + dev->a_ops.adapter_restart = aac_rx_restart_adapter; /* * First clear out all interrupts. Then enable the one's that we -- cgit v1.2.3 From a8166a52968216ae079a5530ac3269147de2ef31 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Thu, 15 Mar 2007 10:26:22 -0700 Subject: [SCSI] aacraid: Fix struct element name issue Received from Mark Salyzyn, This patch is to resolve a namespace issue that will result from a patch expected in the future that adds a new interface; rationalized as correcting a long term issue where hw_fib, instead of hw_fib_va, refers to the virtual address space and hw_fib_pa refers to the physical address space. A small fragment of this patch also cleans up an unused variable that was close to the patch fragments. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/rx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/aacraid/rx.c') diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 00e3cba9d8e..6f8a19462e4 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -387,7 +387,7 @@ static int aac_rx_deliver_producer(struct fib * fib) unsigned long nointr = 0; spin_lock_irqsave(q->lock, qflags); - aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib, 1, fib, &nointr); + aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib_va, 1, fib, &nointr); q->numpending++; *(q->headers.producer) = cpu_to_le32(Index + 1); @@ -437,7 +437,7 @@ static int aac_rx_deliver_message(struct fib * fib) device += sizeof(u32); writel((u32)(addr >> 32), device); device += sizeof(u32); - writel(le16_to_cpu(fib->hw_fib->header.Size), device); + writel(le16_to_cpu(fib->hw_fib_va->header.Size), device); rx_writel(dev, MUnit.InboundQueue, Index); return 0; } -- cgit v1.2.3 From 912d4e8851389eee5c289ce0a7953e9067198232 Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Mon, 26 Mar 2007 09:21:14 -0400 Subject: [SCSI] aacraid: Add likely() and unlikely() Add some likely() and unlikely() compiler hints in some of the aacraid hardware interface layers. There should be no operational side effects resulting from this patch and the changes should be mostly benign on x86 platforms. Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley --- drivers/scsi/aacraid/rx.c | 50 ++++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 27 deletions(-) (limited to 'drivers/scsi/aacraid/rx.c') diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 6f8a19462e4..391d4751338 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -5,7 +5,7 @@ * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,25 +57,25 @@ static irqreturn_t aac_rx_intr_producer(int irq, void *dev_id) * been enabled. * Check to see if this is our interrupt. If it isn't just return */ - if (intstat & ~(dev->OIMR)) { + if (likely(intstat & ~(dev->OIMR))) { bellbits = rx_readl(dev, OutboundDoorbellReg); - if (bellbits & DoorBellPrintfReady) { + if (unlikely(bellbits & DoorBellPrintfReady)) { aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5])); rx_writel(dev, MUnit.ODR,DoorBellPrintfReady); rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); } - else if (bellbits & DoorBellAdapterNormCmdReady) { + else if (unlikely(bellbits & DoorBellAdapterNormCmdReady)) { rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); } - else if (bellbits & DoorBellAdapterNormRespReady) { + else if (likely(bellbits & DoorBellAdapterNormRespReady)) { rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); aac_response_normal(&dev->queues->queue[HostNormRespQueue]); } - else if (bellbits & DoorBellAdapterNormCmdNotFull) { + else if (unlikely(bellbits & DoorBellAdapterNormCmdNotFull)) { rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); } - else if (bellbits & DoorBellAdapterNormRespNotFull) { + else if (unlikely(bellbits & DoorBellAdapterNormRespNotFull)) { rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); } @@ -88,11 +88,11 @@ static irqreturn_t aac_rx_intr_message(int irq, void *dev_id) { struct aac_dev *dev = dev_id; u32 Index = rx_readl(dev, MUnit.OutboundQueue); - if (Index == 0xFFFFFFFFL) + if (unlikely(Index == 0xFFFFFFFFL)) Index = rx_readl(dev, MUnit.OutboundQueue); - if (Index != 0xFFFFFFFFL) { + if (likely(Index != 0xFFFFFFFFL)) { do { - if (aac_intr_normal(dev, Index)) { + if (unlikely(aac_intr_normal(dev, Index))) { rx_writel(dev, MUnit.OutboundQueue, Index); rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady); } @@ -204,7 +204,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, */ msleep(1); } - if (ok != 1) { + if (unlikely(ok != 1)) { /* * Restore interrupt mask even though we timed out */ @@ -319,12 +319,12 @@ static int aac_rx_check_health(struct aac_dev *dev) /* * Check to see if the board failed any self tests. */ - if (status & SELF_TEST_FAILED) + if (unlikely(status & SELF_TEST_FAILED)) return -1; /* * Check to see if the board panic'd. */ - if (status & KERNEL_PANIC) { + if (unlikely(status & KERNEL_PANIC)) { char * buffer; struct POSTSTATUS { __le32 Post_Command; @@ -333,15 +333,15 @@ static int aac_rx_check_health(struct aac_dev *dev) dma_addr_t paddr, baddr; int ret; - if ((status & 0xFF000000L) == 0xBC000000L) + if (likely((status & 0xFF000000L) == 0xBC000000L)) return (status >> 16) & 0xFF; buffer = pci_alloc_consistent(dev->pdev, 512, &baddr); ret = -2; - if (buffer == NULL) + if (unlikely(buffer == NULL)) return ret; post = pci_alloc_consistent(dev->pdev, sizeof(struct POSTSTATUS), &paddr); - if (post == NULL) { + if (unlikely(post == NULL)) { pci_free_consistent(dev->pdev, 512, buffer, baddr); return ret; } @@ -353,7 +353,7 @@ static int aac_rx_check_health(struct aac_dev *dev) NULL, NULL, NULL, NULL, NULL); pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS), post, paddr); - if ((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X'))) { + if (likely((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X')))) { ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10); ret <<= 4; ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10); @@ -364,7 +364,7 @@ static int aac_rx_check_health(struct aac_dev *dev) /* * Wait for the adapter to be up and running. */ - if (!(status & KERNEL_UP_AND_RUNNING)) + if (unlikely(!(status & KERNEL_UP_AND_RUNNING))) return -3; /* * Everything is OK @@ -419,9 +419,9 @@ static int aac_rx_deliver_message(struct fib * fib) spin_unlock_irqrestore(q->lock, qflags); for(;;) { Index = rx_readl(dev, MUnit.InboundQueue); - if (Index == 0xFFFFFFFFL) + if (unlikely(Index == 0xFFFFFFFFL)) Index = rx_readl(dev, MUnit.InboundQueue); - if (Index != 0xFFFFFFFFL) + if (likely(Index != 0xFFFFFFFFL)) break; if (--count == 0) { spin_lock_irqsave(q->lock, qflags); @@ -526,11 +526,8 @@ int _aac_rx_init(struct aac_dev *dev) { unsigned long start; unsigned long status; - int instance; - const char * name; - - instance = dev->id; - name = dev->name; + int instance = dev->id; + const char * name = dev->name; if (aac_adapter_ioremap(dev, dev->base_size)) { printk(KERN_WARNING "%s: unable to map adapter.\n", name); @@ -568,8 +565,7 @@ int _aac_rx_init(struct aac_dev *dev) */ while (!((status = rx_readl(dev, MUnit.OMRx[0])) & KERNEL_UP_AND_RUNNING)) { - if(time_after(jiffies, start+startup_timeout*HZ)) - { + if(time_after(jiffies, start+startup_timeout*HZ)) { printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", dev->name, instance, status); goto error_iounmap; -- cgit v1.2.3 From 9695a25dbff788f26225966c43425e8bae7f06e8 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 26 Mar 2007 21:59:35 -0800 Subject: [SCSI] aacraid: cleanups - proper prototypes for global code in aacraid.h - aac_rx_start_adapter() can now become static Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Acked-by: "Salyzyn, Mark" Signed-off-by: James Bottomley --- drivers/scsi/aacraid/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/aacraid/rx.c') diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 391d4751338..3e23aa6cac0 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -294,7 +294,7 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event) * Start up processing on an i960 based AAC adapter */ -void aac_rx_start_adapter(struct aac_dev *dev) +static void aac_rx_start_adapter(struct aac_dev *dev) { struct aac_init *init; -- cgit v1.2.3 From 18a6598f2d3bb7275dadba77df5f06bc996a77d4 Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Fri, 30 Mar 2007 10:30:48 -0400 Subject: [SCSI] aacraid: [Fastboot] Panics for AACRAID driver during 'insmod' for kexec test. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Attached is the patch I feel will address this issue. As an added 'perk' I have also added the code to detect if the controller was previously initialized for interrupted operations by ANY operating system should the reset_devices kernel parameter not be set and we are dealing with a naïve kexec without the addition of this kernel parameter. The reset handler is also improved. Related to reset operations, but not pertinent specifically to this issue, I have also altered the handling somewhat so that we reset the adapter if we feel it is taking too long (three minutes) to start up. We have not unit tested the reset_devices flag propagation to this driver code, nor have we unit tested the check for the interrupted operations under the conditions of a naively issued kexec. We are submitting this modified driver to our Q/A department for integration testing in our current programs. I would appreciate an ACK to this patch should it resolve the issue described in this thread... Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley --- drivers/scsi/aacraid/rx.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'drivers/scsi/aacraid/rx.c') diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 3e23aa6cac0..0c71315cbf1 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -467,16 +467,19 @@ static int aac_rx_restart_adapter(struct aac_dev *dev, int bled) if (bled) printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n", dev->name, dev->id, bled); - else + else { bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); - if (bled) + if (!bled && (var != 0x00000001)) + bled = -EINVAL; + } + if (bled && (bled != -ETIMEDOUT)) bled = aac_adapter_sync_cmd(dev, IOP_RESET, 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); - if (bled) + if (bled && (bled != -ETIMEDOUT)) return -EINVAL; - if (var == 0x3803000F) { /* USE_OTHER_METHOD */ + if (bled || (var == 0x3803000F)) { /* USE_OTHER_METHOD */ rx_writel(dev, MUnit.reserved2, 3); msleep(5000); /* Delay 5 seconds */ var = 0x00000001; @@ -526,6 +529,7 @@ int _aac_rx_init(struct aac_dev *dev) { unsigned long start; unsigned long status; + int restart = 0; int instance = dev->id; const char * name = dev->name; @@ -534,15 +538,19 @@ int _aac_rx_init(struct aac_dev *dev) goto error_iounmap; } + /* Failure to reset here is an option ... */ + dev->OIMR = status = rx_readb (dev, MUnit.OIMR); + if ((((status & 0xff) != 0xff) || reset_devices) && + !aac_rx_restart_adapter(dev, 0)) + ++restart; /* * Check to see if the board panic'd while booting. */ status = rx_readl(dev, MUnit.OMRx[0]); if (status & KERNEL_PANIC) { - if ((status = aac_rx_check_health(dev)) <= 0) - goto error_iounmap; - if (aac_rx_restart_adapter(dev, status)) + if (aac_rx_restart_adapter(dev, aac_rx_check_health(dev))) goto error_iounmap; + ++restart; } /* * Check to see if the board failed any self tests. @@ -565,11 +573,23 @@ int _aac_rx_init(struct aac_dev *dev) */ while (!((status = rx_readl(dev, MUnit.OMRx[0])) & KERNEL_UP_AND_RUNNING)) { - if(time_after(jiffies, start+startup_timeout*HZ)) { + if ((restart && + (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) || + time_after(jiffies, start+HZ*startup_timeout)) { printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", dev->name, instance, status); goto error_iounmap; } + if (!restart && + ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) || + time_after(jiffies, start + HZ * + ((startup_timeout > 60) + ? (startup_timeout - 60) + : (startup_timeout / 2))))) { + if (likely(!aac_rx_restart_adapter(dev, aac_rx_check_health(dev)))) + start = jiffies; + ++restart; + } msleep(1); } /* -- cgit v1.2.3