Commit 13049537007dee73a76f0a30fcbc24d02c6fa9e4

Authored by Joseph Handzik
Committed by Jens Axboe
1 parent 322a8b0340

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 {
drivers/block/cciss.h
... ... @@ -92,6 +92,7 @@
92 92 unsigned int intr[4];
93 93 unsigned int msix_vector;
94 94 unsigned int msi_vector;
  95 + int intr_mode;
95 96 int cciss_max_sectors;
96 97 BYTE cciss_read;
97 98 BYTE cciss_write;