aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/cciss.c98
1 files changed, 59 insertions, 39 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index ee7cfde8a145..17e420c13b36 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -3830,54 +3830,36 @@ static void __devinit cciss_wait_for_mode_change_ack(ctlr_info_t *h)
3830 } 3830 }
3831} 3831}
3832 3832
3833static void __devinit cciss_put_controller_into_performant_mode(ctlr_info_t *h) 3833static __devinit void cciss_enter_performant_mode(ctlr_info_t *h)
3834{ 3834{
3835 __u32 trans_support; 3835 /* This is a bit complicated. There are 8 registers on
3836 * the controller which we write to to tell it 8 different
3837 * sizes of commands which there may be. It's a way of
3838 * reducing the DMA done to fetch each command. Encoded into
3839 * each command's tag are 3 bits which communicate to the controller
3840 * which of the eight sizes that command fits within. The size of
3841 * each command depends on how many scatter gather entries there are.
3842 * Each SG entry requires 16 bytes. The eight registers are programmed
3843 * with the number of 16-byte blocks a command of that size requires.
3844 * The smallest command possible requires 5 such 16 byte blocks.
3845 * the largest command possible requires MAXSGENTRIES + 4 16-byte
3846 * blocks. Note, this only extends to the SG entries contained
3847 * within the command block, and does not extend to chained blocks
3848 * of SG elements. bft[] contains the eight values we write to
3849 * the registers. They are not evenly distributed, but have more
3850 * sizes for small commands, and fewer sizes for larger commands.
3851 */
3836 __u32 trans_offset; 3852 __u32 trans_offset;
3853 int bft[8] = { 5, 6, 8, 10, 12, 20, 28, MAXSGENTRIES + 4};
3837 /* 3854 /*
3838 * 5 = 1 s/g entry or 4k 3855 * 5 = 1 s/g entry or 4k
3839 * 6 = 2 s/g entry or 8k 3856 * 6 = 2 s/g entry or 8k
3840 * 8 = 4 s/g entry or 16k 3857 * 8 = 4 s/g entry or 16k
3841 * 10 = 6 s/g entry or 24k 3858 * 10 = 6 s/g entry or 24k
3842 */ 3859 */
3843 int bft[8] = { 5, 6, 8, 10, 12, 20, 28, MAXSGENTRIES + 4};
3844 unsigned long register_value; 3860 unsigned long register_value;
3845
3846 BUILD_BUG_ON(28 > MAXSGENTRIES + 4); 3861 BUILD_BUG_ON(28 > MAXSGENTRIES + 4);
3847 3862
3848 dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n");
3849 /* Attempt to put controller into performant mode if supported */
3850 /* Does board support performant mode? */
3851 trans_support = readl(&(h->cfgtable->TransportSupport));
3852 if (!(trans_support & PERFORMANT_MODE))
3853 return;
3854
3855 printk(KERN_WARNING "cciss%d: Placing controller into "
3856 "performant mode\n", h->ctlr);
3857 /* Performant mode demands commands on a 32 byte boundary
3858 * pci_alloc_consistent aligns on page boundarys already.
3859 * Just need to check if divisible by 32
3860 */
3861 if ((sizeof(CommandList_struct) % 32) != 0) {
3862 printk(KERN_WARNING "%s %d %s\n",
3863 "cciss info: command size[",
3864 (int)sizeof(CommandList_struct),
3865 "] not divisible by 32, no performant mode..\n");
3866 return;
3867 }
3868
3869 /* Performant mode ring buffer and supporting data structures */
3870 h->reply_pool = (__u64 *)pci_alloc_consistent(
3871 h->pdev, h->max_commands * sizeof(__u64),
3872 &(h->reply_pool_dhandle));
3873
3874 /* Need a block fetch table for performant mode */
3875 h->blockFetchTable = kmalloc(((h->maxsgentries+1) *
3876 sizeof(__u32)), GFP_KERNEL);
3877
3878 if ((h->reply_pool == NULL) || (h->blockFetchTable == NULL))
3879 goto clean_up;
3880
3881 h->reply_pool_wraparound = 1; /* spec: init to 1 */ 3863 h->reply_pool_wraparound = 1; /* spec: init to 1 */
3882 3864
3883 /* Controller spec: zero out this buffer. */ 3865 /* Controller spec: zero out this buffer. */
@@ -3906,18 +3888,56 @@ static void __devinit cciss_put_controller_into_performant_mode(ctlr_info_t *h)
3906 writel(CFGTBL_Trans_Performant, 3888 writel(CFGTBL_Trans_Performant,
3907 &(h->cfgtable->HostWrite.TransportRequest)); 3889 &(h->cfgtable->HostWrite.TransportRequest));
3908 3890
3909 h->transMethod = CFGTBL_Trans_Performant;
3910 writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); 3891 writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
3911 cciss_wait_for_mode_change_ack(h); 3892 cciss_wait_for_mode_change_ack(h);
3912 register_value = readl(&(h->cfgtable->TransportActive)); 3893 register_value = readl(&(h->cfgtable->TransportActive));
3913 if (!(register_value & CFGTBL_Trans_Performant)) { 3894 if (!(register_value & CFGTBL_Trans_Performant))
3914 printk(KERN_WARNING "cciss: unable to get board into" 3895 printk(KERN_WARNING "cciss: unable to get board into"
3915 " performant mode\n"); 3896 " performant mode\n");
3897}
3898
3899static void __devinit cciss_put_controller_into_performant_mode(ctlr_info_t *h)
3900{
3901 __u32 trans_support;
3902
3903 dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n");
3904 /* Attempt to put controller into performant mode if supported */
3905 /* Does board support performant mode? */
3906 trans_support = readl(&(h->cfgtable->TransportSupport));
3907 if (!(trans_support & PERFORMANT_MODE))
3908 return;
3909
3910 printk(KERN_WARNING "cciss%d: Placing controller into "
3911 "performant mode\n", h->ctlr);
3912 /* Performant mode demands commands on a 32 byte boundary
3913 * pci_alloc_consistent aligns on page boundarys already.
3914 * Just need to check if divisible by 32
3915 */
3916 if ((sizeof(CommandList_struct) % 32) != 0) {
3917 printk(KERN_WARNING "%s %d %s\n",
3918 "cciss info: command size[",
3919 (int)sizeof(CommandList_struct),
3920 "] not divisible by 32, no performant mode..\n");
3916 return; 3921 return;
3917 } 3922 }
3918 3923
3924 /* Performant mode ring buffer and supporting data structures */
3925 h->reply_pool = (__u64 *)pci_alloc_consistent(
3926 h->pdev, h->max_commands * sizeof(__u64),
3927 &(h->reply_pool_dhandle));
3928
3929 /* Need a block fetch table for performant mode */
3930 h->blockFetchTable = kmalloc(((h->maxsgentries+1) *
3931 sizeof(__u32)), GFP_KERNEL);
3932
3933 if ((h->reply_pool == NULL) || (h->blockFetchTable == NULL))
3934 goto clean_up;
3935
3936 cciss_enter_performant_mode(h);
3937
3919 /* Change the access methods to the performant access methods */ 3938 /* Change the access methods to the performant access methods */
3920 h->access = SA5_performant_access; 3939 h->access = SA5_performant_access;
3940 h->transMethod = CFGTBL_Trans_Performant;
3921 3941
3922 return; 3942 return;
3923clean_up: 3943clean_up: