]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/scsi/aacraid/commsup.c
[SCSI] aacraid: Improved error handling
[mirror_ubuntu-artful-kernel.git] / drivers / scsi / aacraid / commsup.c
index 3f27419c66af6c7abac2af838304b3650a8756c8..a23d7e5de5b086b527b9e637f88b3d8ca4436e85 100644 (file)
@@ -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
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
+#include <linux/interrupt.h>
+#include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
+#include <scsi/scsi_cmnd.h>
 #include <asm/semaphore.h>
 
 #include "aacraid.h"
@@ -91,7 +94,7 @@ void aac_fib_map_free(struct aac_dev *dev)
 int aac_fib_setup(struct aac_dev * dev)
 {
        struct fib *fibptr;
-       struct hw_fib *hw_fib_va;
+       struct hw_fib *hw_fib;
        dma_addr_t hw_fib_pa;
        int i;
 
@@ -103,24 +106,24 @@ int aac_fib_setup(struct aac_dev * dev)
        if (i<0)
                return -ENOMEM;
                
-       hw_fib_va = dev->hw_fib_va;
+       hw_fib = dev->hw_fib_va;
        hw_fib_pa = dev->hw_fib_pa;
-       memset(hw_fib_va, 0, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB));
+       memset(hw_fib, 0, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB));
        /*
         *      Initialise the fibs
         */
        for (i = 0, fibptr = &dev->fibs[i]; i < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); i++, fibptr++) 
        {
                fibptr->dev = dev;
-               fibptr->hw_fib = hw_fib_va;
-               fibptr->data = (void *) fibptr->hw_fib->data;
+               fibptr->hw_fib_va = hw_fib;
+               fibptr->data = (void *) fibptr->hw_fib_va->data;
                fibptr->next = fibptr+1;        /* Forward chain the fibs */
                init_MUTEX_LOCKED(&fibptr->event_wait);
                spin_lock_init(&fibptr->event_lock);
-               hw_fib_va->header.XferState = cpu_to_le32(0xffffffff);
-               hw_fib_va->header.SenderSize = cpu_to_le16(dev->max_fib_size);
+               hw_fib->header.XferState = cpu_to_le32(0xffffffff);
+               hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size);
                fibptr->hw_fib_pa = hw_fib_pa;
-               hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + dev->max_fib_size);
+               hw_fib = (struct hw_fib *)((unsigned char *)hw_fib + dev->max_fib_size);
                hw_fib_pa = hw_fib_pa + dev->max_fib_size;
        }
        /*
@@ -163,7 +166,7 @@ struct fib *aac_fib_alloc(struct aac_dev *dev)
         *      Null out fields that depend on being zero at the start of
         *      each I/O
         */
-       fibptr->hw_fib->header.XferState = 0;
+       fibptr->hw_fib_va->header.XferState = 0;
        fibptr->callback = NULL;
        fibptr->callback_data = NULL;
 
@@ -175,7 +178,6 @@ struct fib *aac_fib_alloc(struct aac_dev *dev)
  *     @fibptr: fib to free up
  *
  *     Frees up a fib and places it on the appropriate queue
- *     (either free or timed out)
  */
  
 void aac_fib_free(struct fib *fibptr)
@@ -183,19 +185,15 @@ void aac_fib_free(struct fib *fibptr)
        unsigned long flags;
 
        spin_lock_irqsave(&fibptr->dev->fib_lock, flags);
-       if (fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT) {
+       if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT))
                aac_config.fib_timeouts++;
-               fibptr->next = fibptr->dev->timeout_fib;
-               fibptr->dev->timeout_fib = fibptr;
-       } else {
-               if (fibptr->hw_fib->header.XferState != 0) {
-                       printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n",
-                                (void*)fibptr, 
-                                le32_to_cpu(fibptr->hw_fib->header.XferState));
-               }
-               fibptr->next = fibptr->dev->free_fib;
-               fibptr->dev->free_fib = fibptr;
-       }       
+       if (fibptr->hw_fib_va->header.XferState != 0) {
+               printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n",
+                        (void*)fibptr,
+                        le32_to_cpu(fibptr->hw_fib_va->header.XferState));
+       }
+       fibptr->next = fibptr->dev->free_fib;
+       fibptr->dev->free_fib = fibptr;
        spin_unlock_irqrestore(&fibptr->dev->fib_lock, flags);
 }
 
@@ -208,7 +206,7 @@ void aac_fib_free(struct fib *fibptr)
  
 void aac_fib_init(struct fib *fibptr)
 {
-       struct hw_fib *hw_fib = fibptr->hw_fib;
+       struct hw_fib *hw_fib = fibptr->hw_fib_va;
 
        hw_fib->header.StructType = FIB_MAGIC;
        hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size);
@@ -228,7 +226,7 @@ void aac_fib_init(struct fib *fibptr)
  
 static void fib_dealloc(struct fib * fibptr)
 {
-       struct hw_fib *hw_fib = fibptr->hw_fib;
+       struct hw_fib *hw_fib = fibptr->hw_fib_va;
        BUG_ON(hw_fib->header.StructType != FIB_MAGIC);
        hw_fib->header.XferState = 0;        
 }
@@ -314,7 +312,7 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr
  *     success.
  */
 
-static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify)
+int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify)
 {
        struct aac_entry * entry = NULL;
        int map = 0;
@@ -383,8 +381,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
                void *callback_data)
 {
        struct aac_dev * dev = fibptr->dev;
-       struct hw_fib * hw_fib = fibptr->hw_fib;
-       struct aac_queue * q;
+       struct hw_fib * hw_fib = fibptr->hw_fib_va;
        unsigned long flags = 0;
        unsigned long qflags;
 
@@ -428,7 +425,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
         */
        hw_fib->header.Command = cpu_to_le16(command);
        hw_fib->header.XferState |= cpu_to_le32(SentFromHost);
-       fibptr->hw_fib->header.Flags = 0;       /* 0 the flags field - internal only*/
+       fibptr->hw_fib_va->header.Flags = 0;    /* 0 the flags field - internal only*/
        /*
         *      Set the size of the Fib we want to send to the adapter
         */
@@ -460,42 +457,16 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
        dprintk((KERN_DEBUG "  Command =               %d.\n", le32_to_cpu(hw_fib->header.Command)));
        dprintk((KERN_DEBUG "  SubCommand =            %d.\n", le32_to_cpu(((struct aac_query_mount *)fib_data(fibptr))->command)));
        dprintk((KERN_DEBUG "  XferState  =            %x.\n", le32_to_cpu(hw_fib->header.XferState)));
-       dprintk((KERN_DEBUG "  hw_fib va being sent=%p\n",fibptr->hw_fib));
+       dprintk((KERN_DEBUG "  hw_fib va being sent=%p\n",fibptr->hw_fib_va));
        dprintk((KERN_DEBUG "  hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa));
        dprintk((KERN_DEBUG "  fib being sent=%p\n",fibptr));
 
-       q = &dev->queues->queue[AdapNormCmdQueue];
+       if (!dev->queues)
+               return -EBUSY;
 
        if(wait)
                spin_lock_irqsave(&fibptr->event_lock, flags);
-       spin_lock_irqsave(q->lock, qflags);
-       if (dev->new_comm_interface) {
-               unsigned long count = 10000000L; /* 50 seconds */
-               q->numpending++;
-               spin_unlock_irqrestore(q->lock, qflags);
-               while (aac_adapter_send(fibptr) != 0) {
-                       if (--count == 0) {
-                               if (wait)
-                                       spin_unlock_irqrestore(&fibptr->event_lock, flags);
-                               spin_lock_irqsave(q->lock, qflags);
-                               q->numpending--;
-                               spin_unlock_irqrestore(q->lock, qflags);
-                               return -ETIMEDOUT;
-                       }
-                       udelay(5);
-               }
-       } else {
-               u32 index;
-               unsigned long nointr = 0;
-               aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr);
-
-               q->numpending++;
-               *(q->headers.producer) = cpu_to_le32(index + 1);
-               spin_unlock_irqrestore(q->lock, qflags);
-               dprintk((KERN_DEBUG "aac_fib_send: inserting a queue entry at index %d.\n",index));
-               if (!(nointr & aac_config.irq_mod))
-                       aac_adapter_notify(dev, AdapNormCmdQueue);
-       }
+       aac_adapter_deliver(fibptr);
 
        /*
         *      If the caller wanted us to wait for response wait now. 
@@ -513,7 +484,9 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
                         */
                        unsigned long count = 36000000L; /* 3 minutes */
                        while (down_trylock(&fibptr->event_wait)) {
+                               int blink;
                                if (--count == 0) {
+                                       struct aac_queue * q = &dev->queues->queue[AdapNormCmdQueue];
                                        spin_lock_irqsave(q->lock, qflags);
                                        q->numpending--;
                                        spin_unlock_irqrestore(q->lock, qflags);
@@ -525,10 +498,25 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
                                        }
                                        return -ETIMEDOUT;
                                }
+                               if ((blink = aac_adapter_check_health(dev)) > 0) {
+                                       if (wait == -1) {
+                                               printk(KERN_ERR "aacraid: aac_fib_send: adapter blinkLED 0x%x.\n"
+                                                 "Usually a result of a serious unrecoverable hardware problem\n",
+                                                 blink);
+                                       }
+                                       return -EFAULT;
+                               }
                                udelay(5);
                        }
                } else
-                       down(&fibptr->event_wait);
+                       (void)down_interruptible(&fibptr->event_wait);
+               spin_lock_irqsave(&fibptr->event_lock, flags);
+               if (fibptr->done == 0) {
+                       fibptr->done = 2; /* Tell interrupt we aborted */
+                       spin_unlock_irqrestore(&fibptr->event_lock, flags);
+                       return -EINTR;
+               }
+               spin_unlock_irqrestore(&fibptr->event_lock, flags);
                BUG_ON(fibptr->done == 0);
                        
                if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){
@@ -631,14 +619,14 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid)
 
 int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
 {
-       struct hw_fib * hw_fib = fibptr->hw_fib;
+       struct hw_fib * hw_fib = fibptr->hw_fib_va;
        struct aac_dev * dev = fibptr->dev;
        struct aac_queue * q;
        unsigned long nointr = 0;
        unsigned long qflags;
 
        if (hw_fib->header.XferState == 0) {
-               if (dev->new_comm_interface)
+               if (dev->comm_interface == AAC_COMM_MESSAGE)
                        kfree (hw_fib);
                return 0;
        }
@@ -646,7 +634,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
         *      If we plan to do anything check the structure type first.
         */ 
        if ( hw_fib->header.StructType != FIB_MAGIC ) {
-               if (dev->new_comm_interface)
+               if (dev->comm_interface == AAC_COMM_MESSAGE)
                        kfree (hw_fib);
                return -EINVAL;
        }
@@ -658,7 +646,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
         *      send the completed cdb to the adapter.
         */
        if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) {
-               if (dev->new_comm_interface) {
+               if (dev->comm_interface == AAC_COMM_MESSAGE) {
                        kfree (hw_fib);
                } else {
                        u32 index;
@@ -695,7 +683,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
  
 int aac_fib_complete(struct fib *fibptr)
 {
-       struct hw_fib * hw_fib = fibptr->hw_fib;
+       struct hw_fib * hw_fib = fibptr->hw_fib_va;
 
        /*
         *      Check for a fib which has already been completed
@@ -781,9 +769,8 @@ void aac_printf(struct aac_dev *dev, u32 val)
 #define AIF_SNIFF_TIMEOUT      (30*HZ)
 static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
 {
-       struct hw_fib * hw_fib = fibptr->hw_fib;
+       struct hw_fib * hw_fib = fibptr->hw_fib_va;
        struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data;
-       int busy;
        u32 container;
        struct scsi_device *device;
        enum {
@@ -795,7 +782,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
 
        /* Sniff for container changes */
 
-       if (!dev)
+       if (!dev || !dev->fsa_dev)
                return;
        container = (u32)-1;
 
@@ -995,9 +982,6 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
         * behind you.
         */
 
-       busy = 0;
-
-
        /*
         *      Find the scsi_device associated with the SCSI address,
         * and mark it as changed, invalidating the cache. This deals
@@ -1022,13 +1006,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
        if (device) {
                switch (device_config_needed) {
                case DELETE:
-                       scsi_remove_device(device);
-                       break;
                case CHANGE:
-                       if (!dev->fsa_dev[container].valid) {
-                               scsi_remove_device(device);
-                               break;
-                       }
                        scsi_rescan_device(&device->sdev_gendev);
 
                default:
@@ -1045,6 +1023,269 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
 
 }
 
+static int _aac_reset_adapter(struct aac_dev *aac)
+{
+       int index, quirks;
+       int retval;
+       struct Scsi_Host *host;
+       struct scsi_device *dev;
+       struct scsi_cmnd *command;
+       struct scsi_cmnd *command_list;
+
+       /*
+        * Assumptions:
+        *      - host is locked.
+        *      - in_reset is asserted, so no new i/o is getting to the
+        *        card.
+        *      - The card is dead.
+        */
+       host = aac->scsi_host_ptr;
+       scsi_block_requests(host);
+       aac_adapter_disable_int(aac);
+       spin_unlock_irq(host->host_lock);
+       kthread_stop(aac->thread);
+
+       /*
+        *      If a positive health, means in a known DEAD PANIC
+        * state and the adapter could be reset to `try again'.
+        */
+       retval = aac_adapter_restart(aac, aac_adapter_check_health(aac));
+
+       if (retval)
+               goto out;
+
+       /*
+        *      Loop through the fibs, close the synchronous FIBS
+        */
+       for (retval = 1, index = 0; index < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); index++) {
+               struct fib *fib = &aac->fibs[index];
+               if (!(fib->hw_fib_va->header.XferState & cpu_to_le32(NoResponseExpected | Async)) &&
+                 (fib->hw_fib_va->header.XferState & cpu_to_le32(ResponseExpected))) {
+                       unsigned long flagv;
+                       spin_lock_irqsave(&fib->event_lock, flagv);
+                       up(&fib->event_wait);
+                       spin_unlock_irqrestore(&fib->event_lock, flagv);
+                       schedule();
+                       retval = 0;
+               }
+       }
+       /* Give some extra time for ioctls to complete. */
+       if (retval == 0)
+               ssleep(2);
+       index = aac->cardtype;
+
+       /*
+        * Re-initialize the adapter, first free resources, then carefully
+        * apply the initialization sequence to come back again. Only risk
+        * is a change in Firmware dropping cache, it is assumed the caller
+        * will ensure that i/o is queisced and the card is flushed in that
+        * case.
+        */
+       aac_fib_map_free(aac);
+       aac->hw_fib_va = NULL;
+       aac->hw_fib_pa = 0;
+       pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
+       aac->comm_addr = NULL;
+       aac->comm_phys = 0;
+       kfree(aac->queues);
+       aac->queues = NULL;
+       free_irq(aac->pdev->irq, aac);
+       kfree(aac->fsa_dev);
+       aac->fsa_dev = NULL;
+       if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT) {
+               if (((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK))) ||
+                 ((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_32BIT_MASK))))
+                       goto out;
+       } else {
+               if (((retval = pci_set_dma_mask(aac->pdev, 0x7FFFFFFFULL))) ||
+                 ((retval = pci_set_consistent_dma_mask(aac->pdev, 0x7FFFFFFFULL))))
+                       goto out;
+       }
+       if ((retval = (*(aac_get_driver_ident(index)->init))(aac)))
+               goto out;
+       if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT)
+               if ((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK)))
+                       goto out;
+       aac->thread = kthread_run(aac_command_thread, aac, aac->name);
+       if (IS_ERR(aac->thread)) {
+               retval = PTR_ERR(aac->thread);
+               goto out;
+       }
+       (void)aac_get_adapter_info(aac);
+       quirks = aac_get_driver_ident(index)->quirks;
+       if ((quirks & AAC_QUIRK_34SG) && (host->sg_tablesize > 34)) {
+               host->sg_tablesize = 34;
+               host->max_sectors = (host->sg_tablesize * 8) + 112;
+       }
+       if ((quirks & AAC_QUIRK_17SG) && (host->sg_tablesize > 17)) {
+               host->sg_tablesize = 17;
+               host->max_sectors = (host->sg_tablesize * 8) + 112;
+       }
+       aac_get_config_status(aac, 1);
+       aac_get_containers(aac);
+       /*
+        * This is where the assumption that the Adapter is quiesced
+        * is important.
+        */
+       command_list = NULL;
+       __shost_for_each_device(dev, host) {
+               unsigned long flags;
+               spin_lock_irqsave(&dev->list_lock, flags);
+               list_for_each_entry(command, &dev->cmd_list, list)
+                       if (command->SCp.phase == AAC_OWNER_FIRMWARE) {
+                               command->SCp.buffer = (struct scatterlist *)command_list;
+                               command_list = command;
+                       }
+               spin_unlock_irqrestore(&dev->list_lock, flags);
+       }
+       while ((command = command_list)) {
+               command_list = (struct scsi_cmnd *)command->SCp.buffer;
+               command->SCp.buffer = NULL;
+               command->result = DID_OK << 16
+                 | COMMAND_COMPLETE << 8
+                 | SAM_STAT_TASK_SET_FULL;
+               command->SCp.phase = AAC_OWNER_ERROR_HANDLER;
+               command->scsi_done(command);
+       }
+       retval = 0;
+
+out:
+       aac->in_reset = 0;
+       scsi_unblock_requests(host);
+       spin_lock_irq(host->host_lock);
+       return retval;
+}
+
+int aac_check_health(struct aac_dev * aac)
+{
+       int BlinkLED;
+       unsigned long time_now, flagv = 0;
+       struct list_head * entry;
+       struct Scsi_Host * host;
+
+       /* Extending the scope of fib_lock slightly to protect aac->in_reset */
+       if (spin_trylock_irqsave(&aac->fib_lock, flagv) == 0)
+               return 0;
+
+       if (aac->in_reset || !(BlinkLED = aac_adapter_check_health(aac))) {
+               spin_unlock_irqrestore(&aac->fib_lock, flagv);
+               return 0; /* OK */
+       }
+
+       aac->in_reset = 1;
+
+       /* Fake up an AIF:
+        *      aac_aifcmd.command = AifCmdEventNotify = 1
+        *      aac_aifcmd.seqnum = 0xFFFFFFFF
+        *      aac_aifcmd.data[0] = AifEnExpEvent = 23
+        *      aac_aifcmd.data[1] = AifExeFirmwarePanic = 3
+        *      aac.aifcmd.data[2] = AifHighPriority = 3
+        *      aac.aifcmd.data[3] = BlinkLED
+        */
+
+       time_now = jiffies/HZ;
+       entry = aac->fib_list.next;
+
+       /*
+        * For each Context that is on the
+        * fibctxList, make a copy of the
+        * fib, and then set the event to wake up the
+        * thread that is waiting for it.
+        */
+       while (entry != &aac->fib_list) {
+               /*
+                * Extract the fibctx
+                */
+               struct aac_fib_context *fibctx = list_entry(entry, struct aac_fib_context, next);
+               struct hw_fib * hw_fib;
+               struct fib * fib;
+               /*
+                * Check if the queue is getting
+                * backlogged
+                */
+               if (fibctx->count > 20) {
+                       /*
+                        * It's *not* jiffies folks,
+                        * but jiffies / HZ, so do not
+                        * panic ...
+                        */
+                       u32 time_last = fibctx->jiffies;
+                       /*
+                        * Has it been > 2 minutes
+                        * since the last read off
+                        * the queue?
+                        */
+                       if ((time_now - time_last) > aif_timeout) {
+                               entry = entry->next;
+                               aac_close_fib_context(aac, fibctx);
+                               continue;
+                       }
+               }
+               /*
+                * Warning: no sleep allowed while
+                * holding spinlock
+                */
+               hw_fib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC);
+               fib = kmalloc(sizeof(struct fib), GFP_ATOMIC);
+               if (fib && hw_fib) {
+                       struct aac_aifcmd * aif;
+
+                       memset(hw_fib, 0, sizeof(struct hw_fib));
+                       memset(fib, 0, sizeof(struct fib));
+                       fib->hw_fib_va = hw_fib;
+                       fib->dev = aac;
+                       aac_fib_init(fib);
+                       fib->type = FSAFS_NTC_FIB_CONTEXT;
+                       fib->size = sizeof (struct fib);
+                       fib->data = hw_fib->data;
+                       aif = (struct aac_aifcmd *)hw_fib->data;
+                       aif->command = cpu_to_le32(AifCmdEventNotify);
+                       aif->seqnum = cpu_to_le32(0xFFFFFFFF);
+                       aif->data[0] = cpu_to_le32(AifEnExpEvent);
+                       aif->data[1] = cpu_to_le32(AifExeFirmwarePanic);
+                       aif->data[2] = cpu_to_le32(AifHighPriority);
+                       aif->data[3] = cpu_to_le32(BlinkLED);
+
+                       /*
+                        * Put the FIB onto the
+                        * fibctx's fibs
+                        */
+                       list_add_tail(&fib->fiblink, &fibctx->fib_list);
+                       fibctx->count++;
+                       /*
+                        * Set the event to wake up the
+                        * thread that will waiting.
+                        */
+                       up(&fibctx->wait_sem);
+               } else {
+                       printk(KERN_WARNING "aifd: didn't allocate NewFib.\n");
+                       kfree(fib);
+                       kfree(hw_fib);
+               }
+               entry = entry->next;
+       }
+
+       spin_unlock_irqrestore(&aac->fib_lock, flagv);
+
+       if (BlinkLED < 0) {
+               printk(KERN_ERR "%s: Host adapter dead %d\n", aac->name, BlinkLED);
+               goto out;
+       }
+
+       printk(KERN_ERR "%s: Host adapter BLINK LED 0x%x\n", aac->name, BlinkLED);
+
+       host = aac->scsi_host_ptr;
+       spin_lock_irqsave(host->host_lock, flagv);
+       BlinkLED = _aac_reset_adapter(aac);
+       spin_unlock_irqrestore(host->host_lock, flagv);
+       return BlinkLED;
+
+out:
+       aac->in_reset = 0;
+       return BlinkLED;
+}
+
+
 /**
  *     aac_command_thread      -       command processing thread
  *     @dev: Adapter to monitor
@@ -1097,11 +1338,11 @@ int aac_command_thread(void *data)
                         *      do anything at this point since we don't have
                         *      anything defined for this thread to do.
                         */
-                       hw_fib = fib->hw_fib;
+                       hw_fib = fib->hw_fib_va;
                        memset(fib, 0, sizeof(struct fib));
                        fib->type = FSAFS_NTC_FIB_CONTEXT;
                        fib->size = sizeof( struct fib );
-                       fib->hw_fib = hw_fib;
+                       fib->hw_fib_va = hw_fib;
                        fib->data = hw_fib->data;
                        fib->dev = dev;
                        /*
@@ -1228,7 +1469,7 @@ int aac_command_thread(void *data)
                                                 */
                                                memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib));
                                                memcpy(newfib, fib, sizeof(struct fib));
-                                               newfib->hw_fib = hw_newfib;
+                                               newfib->hw_fib_va = hw_newfib;
                                                /*
                                                 * Put the FIB onto the
                                                 * fibctx's fibs