cciss: factor out cciss_enter_performant_mode
authorStephen M. Cameron <scameron@beardog.cce.hp.com>
Mon, 19 Jul 2010 18:46:07 +0000 (13:46 -0500)
committerJens Axboe <jaxboe@fusionio.com>
Sat, 7 Aug 2010 16:52:12 +0000 (18:52 +0200)
cciss: factor out cciss_enter_performant_mode

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
drivers/block/cciss.c

index ee7cfde8a14579d703fff393911c7a6819cbc53a..17e420c13b36ce68178697c6b58113d3e69b5ee9 100644 (file)
@@ -3830,54 +3830,36 @@ static void __devinit cciss_wait_for_mode_change_ack(ctlr_info_t *h)
        }
 }
 
-static void __devinit cciss_put_controller_into_performant_mode(ctlr_info_t *h)
+static __devinit void cciss_enter_performant_mode(ctlr_info_t *h)
 {
-       __u32 trans_support;
+       /* This is a bit complicated.  There are 8 registers on
+        * the controller which we write to to tell it 8 different
+        * sizes of commands which there may be.  It's a way of
+        * reducing the DMA done to fetch each command.  Encoded into
+        * each command's tag are 3 bits which communicate to the controller
+        * which of the eight sizes that command fits within.  The size of
+        * each command depends on how many scatter gather entries there are.
+        * Each SG entry requires 16 bytes.  The eight registers are programmed
+        * with the number of 16-byte blocks a command of that size requires.
+        * The smallest command possible requires 5 such 16 byte blocks.
+        * the largest command possible requires MAXSGENTRIES + 4 16-byte
+        * blocks.  Note, this only extends to the SG entries contained
+        * within the command block, and does not extend to chained blocks
+        * of SG elements.   bft[] contains the eight values we write to
+        * the registers.  They are not evenly distributed, but have more
+        * sizes for small commands, and fewer sizes for larger commands.
+        */
        __u32 trans_offset;
+       int bft[8] = { 5, 6, 8, 10, 12, 20, 28, MAXSGENTRIES + 4};
                        /*
                         *  5 = 1 s/g entry or 4k
                         *  6 = 2 s/g entry or 8k
                         *  8 = 4 s/g entry or 16k
                         * 10 = 6 s/g entry or 24k
                         */
-       int bft[8] = { 5, 6, 8, 10, 12, 20, 28, MAXSGENTRIES + 4};
        unsigned long register_value;
-
        BUILD_BUG_ON(28 > MAXSGENTRIES + 4);
 
-       dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n");
-       /* Attempt to put controller into performant mode if supported */
-       /* Does board support performant mode? */
-       trans_support = readl(&(h->cfgtable->TransportSupport));
-       if (!(trans_support & PERFORMANT_MODE))
-               return;
-
-       printk(KERN_WARNING "cciss%d: Placing controller into "
-                               "performant mode\n", h->ctlr);
-       /* Performant mode demands commands on a 32 byte boundary
-        * pci_alloc_consistent aligns on page boundarys already.
-        * Just need to check if divisible by 32
-        */
-       if ((sizeof(CommandList_struct) % 32) != 0) {
-               printk(KERN_WARNING "%s %d %s\n",
-                       "cciss info: command size[",
-                       (int)sizeof(CommandList_struct),
-                       "] not divisible by 32, no performant mode..\n");
-               return;
-       }
-
-       /* Performant mode ring buffer and supporting data structures */
-       h->reply_pool = (__u64 *)pci_alloc_consistent(
-               h->pdev, h->max_commands * sizeof(__u64),
-               &(h->reply_pool_dhandle));
-
-       /* Need a block fetch table for performant mode */
-       h->blockFetchTable = kmalloc(((h->maxsgentries+1) *
-               sizeof(__u32)), GFP_KERNEL);
-
-       if ((h->reply_pool == NULL) || (h->blockFetchTable == NULL))
-               goto clean_up;
-
        h->reply_pool_wraparound = 1; /* spec: init to 1 */
 
        /* Controller spec: zero out this buffer. */
@@ -3906,18 +3888,56 @@ static void __devinit cciss_put_controller_into_performant_mode(ctlr_info_t *h)
        writel(CFGTBL_Trans_Performant,
                        &(h->cfgtable->HostWrite.TransportRequest));
 
-       h->transMethod = CFGTBL_Trans_Performant;
        writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
        cciss_wait_for_mode_change_ack(h);
        register_value = readl(&(h->cfgtable->TransportActive));
-       if (!(register_value & CFGTBL_Trans_Performant)) {
+       if (!(register_value & CFGTBL_Trans_Performant))
                printk(KERN_WARNING "cciss: unable to get board into"
                                        " performant mode\n");
+}
+
+static void __devinit cciss_put_controller_into_performant_mode(ctlr_info_t *h)
+{
+       __u32 trans_support;
+
+       dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n");
+       /* Attempt to put controller into performant mode if supported */
+       /* Does board support performant mode? */
+       trans_support = readl(&(h->cfgtable->TransportSupport));
+       if (!(trans_support & PERFORMANT_MODE))
+               return;
+
+       printk(KERN_WARNING "cciss%d: Placing controller into "
+                               "performant mode\n", h->ctlr);
+       /* Performant mode demands commands on a 32 byte boundary
+        * pci_alloc_consistent aligns on page boundarys already.
+        * Just need to check if divisible by 32
+        */
+       if ((sizeof(CommandList_struct) % 32) != 0) {
+               printk(KERN_WARNING "%s %d %s\n",
+                       "cciss info: command size[",
+                       (int)sizeof(CommandList_struct),
+                       "] not divisible by 32, no performant mode..\n");
                return;
        }
 
+       /* Performant mode ring buffer and supporting data structures */
+       h->reply_pool = (__u64 *)pci_alloc_consistent(
+               h->pdev, h->max_commands * sizeof(__u64),
+               &(h->reply_pool_dhandle));
+
+       /* Need a block fetch table for performant mode */
+       h->blockFetchTable = kmalloc(((h->maxsgentries+1) *
+               sizeof(__u32)), GFP_KERNEL);
+
+       if ((h->reply_pool == NULL) || (h->blockFetchTable == NULL))
+               goto clean_up;
+
+       cciss_enter_performant_mode(h);
+
        /* Change the access methods to the performant access methods */
        h->access = SA5_performant_access;
+       h->transMethod = CFGTBL_Trans_Performant;
 
        return;
 clean_up: