aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoseph Handzik <joseph.t.handzik@beardog.cce.hp.com>2011-08-08 05:40:15 -0400
committerJens Axboe <jaxboe@fusionio.com>2011-08-08 05:40:15 -0400
commit13049537007dee73a76f0a30fcbc24d02c6fa9e4 (patch)
tree2bc62c056f42ef8792c3912fef5ce5ca318df993
parent322a8b034003c0d46d39af85bf24fee27b902f48 (diff)
cciss: Adds simple mode functionality
Signed-off-by: Joseph Handzik <joseph.t.handzik@beardog.cce.hp.com> Acked-by: Stephen M. Cameron <scameron@beardog.cce.hp.com> Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
-rw-r--r--Documentation/blockdev/cciss.txt10
-rw-r--r--drivers/block/cciss.c56
-rw-r--r--drivers/block/cciss.h1
3 files changed, 56 insertions, 11 deletions
diff --git a/Documentation/blockdev/cciss.txt b/Documentation/blockdev/cciss.txt
index c00c6a5ab21f..71464e09ec18 100644
--- a/Documentation/blockdev/cciss.txt
+++ b/Documentation/blockdev/cciss.txt
@@ -78,6 +78,16 @@ The device naming scheme is:
78/dev/cciss/c1d1p2 Controller 1, disk 1, partition 2 78/dev/cciss/c1d1p2 Controller 1, disk 1, partition 2
79/dev/cciss/c1d1p3 Controller 1, disk 1, partition 3 79/dev/cciss/c1d1p3 Controller 1, disk 1, partition 3
80 80
81CCISS simple mode support
82-------------------------
83
84The "cciss_simple_mode=1" boot parameter may be used to prevent the driver
85from putting the controller into "performant" mode. The difference is that
86with simple mode, each command completion requires an interrupt, while with
87"performant mode" (the default, and ordinarily better performing) it is
88possible to have multiple command completions indicated by a single
89interrupt.
90
81SCSI tape drive and medium changer support 91SCSI tape drive and medium changer support
82------------------------------------------ 92------------------------------------------
83 93
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 8f4ef656a1af..61f0b5b6a415 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -68,6 +68,10 @@ static int cciss_tape_cmds = 6;
68module_param(cciss_tape_cmds, int, 0644); 68module_param(cciss_tape_cmds, int, 0644);
69MODULE_PARM_DESC(cciss_tape_cmds, 69MODULE_PARM_DESC(cciss_tape_cmds,
70 "number of commands to allocate for tape devices (default: 6)"); 70 "number of commands to allocate for tape devices (default: 6)");
71static int cciss_simple_mode;
72module_param(cciss_simple_mode, int, S_IRUGO|S_IWUSR);
73MODULE_PARM_DESC(cciss_simple_mode,
74 "Use 'simple mode' rather than 'performant mode'");
71 75
72static DEFINE_MUTEX(cciss_mutex); 76static DEFINE_MUTEX(cciss_mutex);
73static struct proc_dir_entry *proc_cciss; 77static struct proc_dir_entry *proc_cciss;
@@ -176,6 +180,7 @@ static void cciss_geometry_inquiry(ctlr_info_t *h, int logvol,
176 unsigned int block_size, InquiryData_struct *inq_buff, 180 unsigned int block_size, InquiryData_struct *inq_buff,
177 drive_info_struct *drv); 181 drive_info_struct *drv);
178static void __devinit cciss_interrupt_mode(ctlr_info_t *); 182static void __devinit cciss_interrupt_mode(ctlr_info_t *);
183static int __devinit cciss_enter_simple_mode(struct ctlr_info *h);
179static void start_io(ctlr_info_t *h); 184static void start_io(ctlr_info_t *h);
180static int sendcmd_withirq(ctlr_info_t *h, __u8 cmd, void *buff, size_t size, 185static int sendcmd_withirq(ctlr_info_t *h, __u8 cmd, void *buff, size_t size,
181 __u8 page_code, unsigned char scsi3addr[], 186 __u8 page_code, unsigned char scsi3addr[],
@@ -388,7 +393,7 @@ static void cciss_seq_show_header(struct seq_file *seq)
388 h->product_name, 393 h->product_name,
389 (unsigned long)h->board_id, 394 (unsigned long)h->board_id,
390 h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], 395 h->firm_ver[0], h->firm_ver[1], h->firm_ver[2],
391 h->firm_ver[3], (unsigned int)h->intr[PERF_MODE_INT], 396 h->firm_ver[3], (unsigned int)h->intr[h->intr_mode],
392 h->num_luns, 397 h->num_luns,
393 h->Qdepth, h->commands_outstanding, 398 h->Qdepth, h->commands_outstanding,
394 h->maxQsinceinit, h->max_outstanding, h->maxSG); 399 h->maxQsinceinit, h->max_outstanding, h->maxSG);
@@ -3984,6 +3989,9 @@ static void __devinit cciss_put_controller_into_performant_mode(ctlr_info_t *h)
3984{ 3989{
3985 __u32 trans_support; 3990 __u32 trans_support;
3986 3991
3992 if (cciss_simple_mode)
3993 return;
3994
3987 dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n"); 3995 dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n");
3988 /* Attempt to put controller into performant mode if supported */ 3996 /* Attempt to put controller into performant mode if supported */
3989 /* Does board support performant mode? */ 3997 /* Does board support performant mode? */
@@ -4081,7 +4089,7 @@ static void __devinit cciss_interrupt_mode(ctlr_info_t *h)
4081default_int_mode: 4089default_int_mode:
4082#endif /* CONFIG_PCI_MSI */ 4090#endif /* CONFIG_PCI_MSI */
4083 /* if we get here we're going to use the default interrupt mode */ 4091 /* if we get here we're going to use the default interrupt mode */
4084 h->intr[PERF_MODE_INT] = h->pdev->irq; 4092 h->intr[h->intr_mode] = h->pdev->irq;
4085 return; 4093 return;
4086} 4094}
4087 4095
@@ -4341,6 +4349,9 @@ static int __devinit cciss_pci_init(ctlr_info_t *h)
4341 } 4349 }
4342 cciss_enable_scsi_prefetch(h); 4350 cciss_enable_scsi_prefetch(h);
4343 cciss_p600_dma_prefetch_quirk(h); 4351 cciss_p600_dma_prefetch_quirk(h);
4352 err = cciss_enter_simple_mode(h);
4353 if (err)
4354 goto err_out_free_res;
4344 cciss_put_controller_into_performant_mode(h); 4355 cciss_put_controller_into_performant_mode(h);
4345 return 0; 4356 return 0;
4346 4357
@@ -4843,20 +4854,20 @@ static int cciss_request_irq(ctlr_info_t *h,
4843 irqreturn_t (*intxhandler)(int, void *)) 4854 irqreturn_t (*intxhandler)(int, void *))
4844{ 4855{
4845 if (h->msix_vector || h->msi_vector) { 4856 if (h->msix_vector || h->msi_vector) {
4846 if (!request_irq(h->intr[PERF_MODE_INT], msixhandler, 4857 if (!request_irq(h->intr[h->intr_mode], msixhandler,
4847 IRQF_DISABLED, h->devname, h)) 4858 IRQF_DISABLED, h->devname, h))
4848 return 0; 4859 return 0;
4849 dev_err(&h->pdev->dev, "Unable to get msi irq %d" 4860 dev_err(&h->pdev->dev, "Unable to get msi irq %d"
4850 " for %s\n", h->intr[PERF_MODE_INT], 4861 " for %s\n", h->intr[h->intr_mode],
4851 h->devname); 4862 h->devname);
4852 return -1; 4863 return -1;
4853 } 4864 }
4854 4865
4855 if (!request_irq(h->intr[PERF_MODE_INT], intxhandler, 4866 if (!request_irq(h->intr[h->intr_mode], intxhandler,
4856 IRQF_DISABLED, h->devname, h)) 4867 IRQF_DISABLED, h->devname, h))
4857 return 0; 4868 return 0;
4858 dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n", 4869 dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n",
4859 h->intr[PERF_MODE_INT], h->devname); 4870 h->intr[h->intr_mode], h->devname);
4860 return -1; 4871 return -1;
4861} 4872}
4862 4873
@@ -4887,7 +4898,7 @@ static void cciss_undo_allocations_after_kdump_soft_reset(ctlr_info_t *h)
4887{ 4898{
4888 int ctlr = h->ctlr; 4899 int ctlr = h->ctlr;
4889 4900
4890 free_irq(h->intr[PERF_MODE_INT], h); 4901 free_irq(h->intr[h->intr_mode], h);
4891#ifdef CONFIG_PCI_MSI 4902#ifdef CONFIG_PCI_MSI
4892 if (h->msix_vector) 4903 if (h->msix_vector)
4893 pci_disable_msix(h->pdev); 4904 pci_disable_msix(h->pdev);
@@ -4953,6 +4964,7 @@ reinit_after_soft_reset:
4953 h = hba[i]; 4964 h = hba[i];
4954 h->pdev = pdev; 4965 h->pdev = pdev;
4955 h->busy_initializing = 1; 4966 h->busy_initializing = 1;
4967 h->intr_mode = cciss_simple_mode ? SIMPLE_MODE_INT : PERF_MODE_INT;
4956 INIT_LIST_HEAD(&h->cmpQ); 4968 INIT_LIST_HEAD(&h->cmpQ);
4957 INIT_LIST_HEAD(&h->reqQ); 4969 INIT_LIST_HEAD(&h->reqQ);
4958 mutex_init(&h->busy_shutting_down); 4970 mutex_init(&h->busy_shutting_down);
@@ -5009,7 +5021,7 @@ reinit_after_soft_reset:
5009 5021
5010 dev_info(&h->pdev->dev, "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n", 5022 dev_info(&h->pdev->dev, "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n",
5011 h->devname, pdev->device, pci_name(pdev), 5023 h->devname, pdev->device, pci_name(pdev),
5012 h->intr[PERF_MODE_INT], dac ? "" : " not"); 5024 h->intr[h->intr_mode], dac ? "" : " not");
5013 5025
5014 if (cciss_allocate_cmd_pool(h)) 5026 if (cciss_allocate_cmd_pool(h))
5015 goto clean4; 5027 goto clean4;
@@ -5056,7 +5068,7 @@ reinit_after_soft_reset:
5056 spin_lock_irqsave(&h->lock, flags); 5068 spin_lock_irqsave(&h->lock, flags);
5057 h->access.set_intr_mask(h, CCISS_INTR_OFF); 5069 h->access.set_intr_mask(h, CCISS_INTR_OFF);
5058 spin_unlock_irqrestore(&h->lock, flags); 5070 spin_unlock_irqrestore(&h->lock, flags);
5059 free_irq(h->intr[PERF_MODE_INT], h); 5071 free_irq(h->intr[h->intr_mode], h);
5060 rc = cciss_request_irq(h, cciss_msix_discard_completions, 5072 rc = cciss_request_irq(h, cciss_msix_discard_completions,
5061 cciss_intx_discard_completions); 5073 cciss_intx_discard_completions);
5062 if (rc) { 5074 if (rc) {
@@ -5133,7 +5145,7 @@ clean4:
5133 cciss_free_cmd_pool(h); 5145 cciss_free_cmd_pool(h);
5134 cciss_free_scatterlists(h); 5146 cciss_free_scatterlists(h);
5135 cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds); 5147 cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds);
5136 free_irq(h->intr[PERF_MODE_INT], h); 5148 free_irq(h->intr[h->intr_mode], h);
5137clean2: 5149clean2:
5138 unregister_blkdev(h->major, h->devname); 5150 unregister_blkdev(h->major, h->devname);
5139clean1: 5151clean1:
@@ -5172,9 +5184,31 @@ static void cciss_shutdown(struct pci_dev *pdev)
5172 if (return_code != IO_OK) 5184 if (return_code != IO_OK)
5173 dev_warn(&h->pdev->dev, "Error flushing cache\n"); 5185 dev_warn(&h->pdev->dev, "Error flushing cache\n");
5174 h->access.set_intr_mask(h, CCISS_INTR_OFF); 5186 h->access.set_intr_mask(h, CCISS_INTR_OFF);
5175 free_irq(h->intr[PERF_MODE_INT], h); 5187 free_irq(h->intr[h->intr_mode], h);
5176} 5188}
5177 5189
5190static int __devinit cciss_enter_simple_mode(struct ctlr_info *h)
5191{
5192 u32 trans_support;
5193
5194 trans_support = readl(&(h->cfgtable->TransportSupport));
5195 if (!(trans_support & SIMPLE_MODE))
5196 return -ENOTSUPP;
5197
5198 h->max_commands = readl(&(h->cfgtable->CmdsOutMax));
5199 writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest));
5200 writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
5201 cciss_wait_for_mode_change_ack(h);
5202 print_cfg_table(h);
5203 if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) {
5204 dev_warn(&h->pdev->dev, "unable to get board into simple mode\n");
5205 return -ENODEV;
5206 }
5207 h->transMethod = CFGTBL_Trans_Simple;
5208 return 0;
5209}
5210
5211
5178static void __devexit cciss_remove_one(struct pci_dev *pdev) 5212static void __devexit cciss_remove_one(struct pci_dev *pdev)
5179{ 5213{
5180 ctlr_info_t *h; 5214 ctlr_info_t *h;
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index c049548e68b7..7fda30e4a241 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -92,6 +92,7 @@ struct ctlr_info
92 unsigned int intr[4]; 92 unsigned int intr[4];
93 unsigned int msix_vector; 93 unsigned int msix_vector;
94 unsigned int msi_vector; 94 unsigned int msi_vector;
95 int intr_mode;
95 int cciss_max_sectors; 96 int cciss_max_sectors;
96 BYTE cciss_read; 97 BYTE cciss_read;
97 BYTE cciss_write; 98 BYTE cciss_write;