Commit 13049537007dee73a76f0a30fcbc24d02c6fa9e4
Committed by
Jens Axboe
1 parent
322a8b0340
Exists in
master
and in
6 other branches
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>
Showing 3 changed files with 56 additions and 11 deletions Side-by-side Diff
Documentation/blockdev/cciss.txt
... | ... | @@ -78,6 +78,16 @@ |
78 | 78 | /dev/cciss/c1d1p2 Controller 1, disk 1, partition 2 |
79 | 79 | /dev/cciss/c1d1p3 Controller 1, disk 1, partition 3 |
80 | 80 | |
81 | +CCISS simple mode support | |
82 | +------------------------- | |
83 | + | |
84 | +The "cciss_simple_mode=1" boot parameter may be used to prevent the driver | |
85 | +from putting the controller into "performant" mode. The difference is that | |
86 | +with simple mode, each command completion requires an interrupt, while with | |
87 | +"performant mode" (the default, and ordinarily better performing) it is | |
88 | +possible to have multiple command completions indicated by a single | |
89 | +interrupt. | |
90 | + | |
81 | 91 | SCSI tape drive and medium changer support |
82 | 92 | ------------------------------------------ |
83 | 93 |
drivers/block/cciss.c
... | ... | @@ -68,6 +68,10 @@ |
68 | 68 | module_param(cciss_tape_cmds, int, 0644); |
69 | 69 | MODULE_PARM_DESC(cciss_tape_cmds, |
70 | 70 | "number of commands to allocate for tape devices (default: 6)"); |
71 | +static int cciss_simple_mode; | |
72 | +module_param(cciss_simple_mode, int, S_IRUGO|S_IWUSR); | |
73 | +MODULE_PARM_DESC(cciss_simple_mode, | |
74 | + "Use 'simple mode' rather than 'performant mode'"); | |
71 | 75 | |
72 | 76 | static DEFINE_MUTEX(cciss_mutex); |
73 | 77 | static struct proc_dir_entry *proc_cciss; |
... | ... | @@ -176,6 +180,7 @@ |
176 | 180 | unsigned int block_size, InquiryData_struct *inq_buff, |
177 | 181 | drive_info_struct *drv); |
178 | 182 | static void __devinit cciss_interrupt_mode(ctlr_info_t *); |
183 | +static int __devinit cciss_enter_simple_mode(struct ctlr_info *h); | |
179 | 184 | static void start_io(ctlr_info_t *h); |
180 | 185 | static int sendcmd_withirq(ctlr_info_t *h, __u8 cmd, void *buff, size_t size, |
181 | 186 | __u8 page_code, unsigned char scsi3addr[], |
... | ... | @@ -388,7 +393,7 @@ |
388 | 393 | h->product_name, |
389 | 394 | (unsigned long)h->board_id, |
390 | 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 | 397 | h->num_luns, |
393 | 398 | h->Qdepth, h->commands_outstanding, |
394 | 399 | h->maxQsinceinit, h->max_outstanding, h->maxSG); |
... | ... | @@ -3984,6 +3989,9 @@ |
3984 | 3989 | { |
3985 | 3990 | __u32 trans_support; |
3986 | 3991 | |
3992 | + if (cciss_simple_mode) | |
3993 | + return; | |
3994 | + | |
3987 | 3995 | dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n"); |
3988 | 3996 | /* Attempt to put controller into performant mode if supported */ |
3989 | 3997 | /* Does board support performant mode? */ |
... | ... | @@ -4081,7 +4089,7 @@ |
4081 | 4089 | default_int_mode: |
4082 | 4090 | #endif /* CONFIG_PCI_MSI */ |
4083 | 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 | 4093 | return; |
4086 | 4094 | } |
4087 | 4095 | |
... | ... | @@ -4341,6 +4349,9 @@ |
4341 | 4349 | } |
4342 | 4350 | cciss_enable_scsi_prefetch(h); |
4343 | 4351 | cciss_p600_dma_prefetch_quirk(h); |
4352 | + err = cciss_enter_simple_mode(h); | |
4353 | + if (err) | |
4354 | + goto err_out_free_res; | |
4344 | 4355 | cciss_put_controller_into_performant_mode(h); |
4345 | 4356 | return 0; |
4346 | 4357 | |
4347 | 4358 | |
4348 | 4359 | |
4349 | 4360 | |
... | ... | @@ -4843,20 +4854,20 @@ |
4843 | 4854 | irqreturn_t (*intxhandler)(int, void *)) |
4844 | 4855 | { |
4845 | 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 | 4858 | IRQF_DISABLED, h->devname, h)) |
4848 | 4859 | return 0; |
4849 | 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 | 4862 | h->devname); |
4852 | 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 | 4867 | IRQF_DISABLED, h->devname, h)) |
4857 | 4868 | return 0; |
4858 | 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 | 4871 | return -1; |
4861 | 4872 | } |
4862 | 4873 | |
... | ... | @@ -4887,7 +4898,7 @@ |
4887 | 4898 | { |
4888 | 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 | 4902 | #ifdef CONFIG_PCI_MSI |
4892 | 4903 | if (h->msix_vector) |
4893 | 4904 | pci_disable_msix(h->pdev); |
... | ... | @@ -4953,6 +4964,7 @@ |
4953 | 4964 | h = hba[i]; |
4954 | 4965 | h->pdev = pdev; |
4955 | 4966 | h->busy_initializing = 1; |
4967 | + h->intr_mode = cciss_simple_mode ? SIMPLE_MODE_INT : PERF_MODE_INT; | |
4956 | 4968 | INIT_LIST_HEAD(&h->cmpQ); |
4957 | 4969 | INIT_LIST_HEAD(&h->reqQ); |
4958 | 4970 | mutex_init(&h->busy_shutting_down); |
... | ... | @@ -5009,7 +5021,7 @@ |
5009 | 5021 | |
5010 | 5022 | dev_info(&h->pdev->dev, "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n", |
5011 | 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 | 5026 | if (cciss_allocate_cmd_pool(h)) |
5015 | 5027 | goto clean4; |
... | ... | @@ -5056,7 +5068,7 @@ |
5056 | 5068 | spin_lock_irqsave(&h->lock, flags); |
5057 | 5069 | h->access.set_intr_mask(h, CCISS_INTR_OFF); |
5058 | 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 | 5072 | rc = cciss_request_irq(h, cciss_msix_discard_completions, |
5061 | 5073 | cciss_intx_discard_completions); |
5062 | 5074 | if (rc) { |
... | ... | @@ -5133,7 +5145,7 @@ |
5133 | 5145 | cciss_free_cmd_pool(h); |
5134 | 5146 | cciss_free_scatterlists(h); |
5135 | 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); | |
5137 | 5149 | clean2: |
5138 | 5150 | unregister_blkdev(h->major, h->devname); |
5139 | 5151 | clean1: |
5140 | 5152 | |
... | ... | @@ -5172,8 +5184,30 @@ |
5172 | 5184 | if (return_code != IO_OK) |
5173 | 5185 | dev_warn(&h->pdev->dev, "Error flushing cache\n"); |
5174 | 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 | } |
5189 | + | |
5190 | +static 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 | + | |
5177 | 5211 | |
5178 | 5212 | static void __devexit cciss_remove_one(struct pci_dev *pdev) |
5179 | 5213 | { |