]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/aacraid/commsup.c
Merge master.kernel.org:/home/rmk/linux-2.6-mmc
[linux-2.6-omap-h63xx.git] / drivers / scsi / aacraid / commsup.c
index 2d6bae661790bab32f941d6924db9ffefd6c4347..a1d303f034808f3e31a2f44860355f1e240d7ee4 100644 (file)
@@ -25,7 +25,7 @@
  *  commsup.c
  *
  * Abstract: Contain all routines that are required for FSA host/adapter
- *    commuication.
+ *    communication.
  *
  */
 
@@ -38,6 +38,7 @@
 #include <linux/slab.h>
 #include <linux/completion.h>
 #include <linux/blkdev.h>
+#include <scsi/scsi_host.h>
 #include <asm/semaphore.h>
 
 #include "aacraid.h"
  
 static int fib_map_alloc(struct aac_dev *dev)
 {
-       if((dev->hw_fib_va = pci_alloc_consistent(dev->pdev, sizeof(struct hw_fib) * AAC_NUM_FIB, &dev->hw_fib_pa))==NULL)
+       dprintk((KERN_INFO
+         "allocate hardware fibs pci_alloc_consistent(%p, %d * (%d + %d), %p)\n",
+         dev->pdev, dev->max_fib_size, dev->scsi_host_ptr->can_queue,
+         AAC_NUM_MGT_FIB, &dev->hw_fib_pa));
+       if((dev->hw_fib_va = pci_alloc_consistent(dev->pdev, dev->max_fib_size
+         * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB),
+         &dev->hw_fib_pa))==NULL)
                return -ENOMEM;
        return 0;
 }
@@ -67,7 +74,7 @@ static int fib_map_alloc(struct aac_dev *dev)
 
 void fib_map_free(struct aac_dev *dev)
 {
-       pci_free_consistent(dev->pdev, sizeof(struct hw_fib) * AAC_NUM_FIB, dev->hw_fib_va, dev->hw_fib_pa);
+       pci_free_consistent(dev->pdev, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB), dev->hw_fib_va, dev->hw_fib_pa);
 }
 
 /**
@@ -84,17 +91,22 @@ int fib_setup(struct aac_dev * dev)
        struct hw_fib *hw_fib_va;
        dma_addr_t hw_fib_pa;
        int i;
-       
-       if(fib_map_alloc(dev)<0)
+
+       while (((i = fib_map_alloc(dev)) == -ENOMEM)
+        && (dev->scsi_host_ptr->can_queue > (64 - AAC_NUM_MGT_FIB))) {
+               dev->init->MaxIoCommands = cpu_to_le32((dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) >> 1);
+               dev->scsi_host_ptr->can_queue = le32_to_cpu(dev->init->MaxIoCommands) - AAC_NUM_MGT_FIB;
+       }
+       if (i<0)
                return -ENOMEM;
                
        hw_fib_va = dev->hw_fib_va;
        hw_fib_pa = dev->hw_fib_pa;
-       memset(hw_fib_va, 0, sizeof(struct hw_fib) * AAC_NUM_FIB);
+       memset(hw_fib_va, 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 < AAC_NUM_FIB; i++, fibptr++) 
+       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;
@@ -102,16 +114,16 @@ int fib_setup(struct aac_dev * dev)
                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 = 0xffffffff;
-               hw_fib_va->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib));
+               hw_fib_va->header.XferState = cpu_to_le32(0xffffffff);
+               hw_fib_va->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 + sizeof(struct hw_fib));
-               hw_fib_pa = hw_fib_pa + sizeof(struct hw_fib); 
+               hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + dev->max_fib_size);
+               hw_fib_pa = hw_fib_pa + dev->max_fib_size;
        }
        /*
         *      Add the fib chain to the free list
         */
-       dev->fibs[AAC_NUM_FIB-1].next = NULL;
+       dev->fibs[dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB - 1].next = NULL;
        /*
         *      Enable this to debug out of queue space
         */
@@ -124,7 +136,7 @@ int fib_setup(struct aac_dev * dev)
  *     @dev: Adapter to allocate the fib for
  *
  *     Allocate a fib from the adapter fib pool. If the pool is empty we
- *     wait for fibs to become free.
+ *     return NULL.
  */
  
 struct fib * fib_alloc(struct aac_dev *dev)
@@ -133,10 +145,10 @@ struct fib * fib_alloc(struct aac_dev *dev)
        unsigned long flags;
        spin_lock_irqsave(&dev->fib_lock, flags);
        fibptr = dev->free_fib; 
-       /* Cannot sleep here or you get hangs. Instead we did the
-          maths at compile time. */
-       if(!fibptr)
-               BUG();
+       if(!fibptr){
+               spin_unlock_irqrestore(&dev->fib_lock, flags);
+               return fibptr;
+       }
        dev->free_fib = fibptr->next;
        spin_unlock_irqrestore(&dev->fib_lock, flags);
        /*
@@ -196,11 +208,11 @@ void fib_init(struct fib *fibptr)
        struct hw_fib *hw_fib = fibptr->hw_fib;
 
        hw_fib->header.StructType = FIB_MAGIC;
-       hw_fib->header.Size = cpu_to_le16(sizeof(struct hw_fib));
-        hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable);
+       hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size);
+       hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable);
        hw_fib->header.SenderFibAddress = cpu_to_le32(fibptr->hw_fib_pa);
        hw_fib->header.ReceiverFibAddress = cpu_to_le32(fibptr->hw_fib_pa);
-       hw_fib->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib));
+       hw_fib->header.SenderSize = cpu_to_le16(fibptr->dev->max_fib_size);
 }
 
 /**
@@ -242,6 +254,7 @@ static void fib_dealloc(struct fib * fibptr)
 static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entry, u32 * index, unsigned long *nonotify)
 {
        struct aac_queue * q;
+       unsigned long idx;
 
        /*
         *      All of the queues wrap when they reach the end, so we check
@@ -251,10 +264,23 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr
         */
 
        q = &dev->queues->queue[qid];
-       
-       *index = le32_to_cpu(*(q->headers.producer));
-       if ((*index - 2) == le32_to_cpu(*(q->headers.consumer)))
+
+       idx = *index = le32_to_cpu(*(q->headers.producer));
+       /* Interrupt Moderation, only interrupt for first two entries */
+       if (idx != le32_to_cpu(*(q->headers.consumer))) {
+               if (--idx == 0) {
+                       if (qid == AdapHighCmdQueue)
+                               idx = ADAP_HIGH_CMD_ENTRIES;
+                       else if (qid == AdapNormCmdQueue)
+                               idx = ADAP_NORM_CMD_ENTRIES;
+                       else if (qid == AdapHighRespQueue) 
+                               idx = ADAP_HIGH_RESP_ENTRIES;
+                       else if (qid == AdapNormRespQueue) 
+                               idx = ADAP_NORM_RESP_ENTRIES;
+               }
+               if (idx != le32_to_cpu(*(q->headers.consumer)))
                        *nonotify = 1; 
+       }
 
        if (qid == AdapHighCmdQueue) {
                if (*index >= ADAP_HIGH_CMD_ENTRIES)
@@ -279,7 +305,7 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr
        }
 
         if ((*index + 1) == le32_to_cpu(*(q->headers.consumer))) { /* Queue is full */
-               printk(KERN_WARNING "Queue %d full, %d outstanding.\n",
+               printk(KERN_WARNING "Queue %d full, %u outstanding.\n",
                                qid, q->numpending);
                return 0;
        } else {
@@ -658,9 +684,8 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size)
                        }
                        if (aac_insert_entry(dev, index, AdapHighRespQueue,  (nointr & (int)aac_config.irq_mod)) != 0) {
                        }
-               }
-               else if (hw_fib->header.XferState & NormalPriority) 
-               {
+               } else if (hw_fib->header.XferState & 
+                               cpu_to_le32(NormalPriority)) {
                        u32 index;
 
                        if (size) {
@@ -744,22 +769,25 @@ int fib_complete(struct fib * fibptr)
 
 void aac_printf(struct aac_dev *dev, u32 val)
 {
-       int length = val & 0xffff;
-       int level = (val >> 16) & 0xffff;
        char *cp = dev->printfbuf;
-       
-       /*
-        *      The size of the printfbuf is set in port.c
-        *      There is no variable or define for it
-        */
-       if (length > 255)
-               length = 255;
-       if (cp[length] != 0)
-               cp[length] = 0;
-       if (level == LOG_AAC_HIGH_ERROR)
-               printk(KERN_WARNING "aacraid:%s", cp);
-       else
-               printk(KERN_INFO "aacraid:%s", cp);
+       if (dev->printf_enabled)
+       {
+               int length = val & 0xffff;
+               int level = (val >> 16) & 0xffff;
+               
+               /*
+                *      The size of the printfbuf is set in port.c
+                *      There is no variable or define for it
+                */
+               if (length > 255)
+                       length = 255;
+               if (cp[length] != 0)
+                       cp[length] = 0;
+               if (level == LOG_AAC_HIGH_ERROR)
+                       printk(KERN_WARNING "aacraid:%s", cp);
+               else
+                       printk(KERN_INFO "aacraid:%s", cp);
+       }
        memset(cp, 0,  256);
 }
 
@@ -832,8 +860,8 @@ int aac_command_thread(struct aac_dev * dev)
                        aifcmd = (struct aac_aifcmd *) hw_fib->data;
                        if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) {
                                /* Handle Driver Notify Events */
-                               *(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
-                               fib_adapter_complete(fib, sizeof(u32));
+                               *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
+                               fib_adapter_complete(fib, (u16)sizeof(u32));
                        } else {
                                struct list_head *entry;
                                /* The u32 here is important and intended. We are using
@@ -916,7 +944,7 @@ int aac_command_thread(struct aac_dev * dev)
                                /*
                                 *      Set the status of this FIB
                                 */
-                               *(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
+                               *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
                                fib_adapter_complete(fib, sizeof(u32));
                                spin_unlock_irqrestore(&dev->fib_lock, flagv);
                        }