Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Joseph Handzik and committed by
Jens Axboe
13049537 322a8b03

+56 -11
+10
Documentation/blockdev/cciss.txt
··· 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
+45 -11
drivers/block/cciss.c
··· 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; ··· 180 176 unsigned int block_size, InquiryData_struct *inq_buff, 181 177 drive_info_struct *drv); 182 178 static void __devinit cciss_interrupt_mode(ctlr_info_t *); 179 + static int __devinit cciss_enter_simple_mode(struct ctlr_info *h); 183 180 static void start_io(ctlr_info_t *h); 184 181 static int sendcmd_withirq(ctlr_info_t *h, __u8 cmd, void *buff, size_t size, 185 182 __u8 page_code, unsigned char scsi3addr[], ··· 393 388 h->product_name, 394 389 (unsigned long)h->board_id, 395 390 h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], 396 - h->firm_ver[3], (unsigned int)h->intr[PERF_MODE_INT], 391 + h->firm_ver[3], (unsigned int)h->intr[h->intr_mode], 397 392 h->num_luns, 398 393 h->Qdepth, h->commands_outstanding, 399 394 h->maxQsinceinit, h->max_outstanding, h->maxSG); ··· 3989 3984 { 3990 3985 __u32 trans_support; 3991 3986 3987 + if (cciss_simple_mode) 3988 + return; 3989 + 3992 3990 dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n"); 3993 3991 /* Attempt to put controller into performant mode if supported */ 3994 3992 /* Does board support performant mode? */ ··· 4089 4081 default_int_mode: 4090 4082 #endif /* CONFIG_PCI_MSI */ 4091 4083 /* if we get here we're going to use the default interrupt mode */ 4092 - h->intr[PERF_MODE_INT] = h->pdev->irq; 4084 + h->intr[h->intr_mode] = h->pdev->irq; 4093 4085 return; 4094 4086 } 4095 4087 ··· 4349 4341 } 4350 4342 cciss_enable_scsi_prefetch(h); 4351 4343 cciss_p600_dma_prefetch_quirk(h); 4344 + err = cciss_enter_simple_mode(h); 4345 + if (err) 4346 + goto err_out_free_res; 4352 4347 cciss_put_controller_into_performant_mode(h); 4353 4348 return 0; 4354 4349 ··· 4854 4843 irqreturn_t (*intxhandler)(int, void *)) 4855 4844 { 4856 4845 if (h->msix_vector || h->msi_vector) { 4857 - if (!request_irq(h->intr[PERF_MODE_INT], msixhandler, 4846 + if (!request_irq(h->intr[h->intr_mode], msixhandler, 4858 4847 IRQF_DISABLED, h->devname, h)) 4859 4848 return 0; 4860 4849 dev_err(&h->pdev->dev, "Unable to get msi irq %d" 4861 - " for %s\n", h->intr[PERF_MODE_INT], 4850 + " for %s\n", h->intr[h->intr_mode], 4862 4851 h->devname); 4863 4852 return -1; 4864 4853 } 4865 4854 4866 - if (!request_irq(h->intr[PERF_MODE_INT], intxhandler, 4855 + if (!request_irq(h->intr[h->intr_mode], intxhandler, 4867 4856 IRQF_DISABLED, h->devname, h)) 4868 4857 return 0; 4869 4858 dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n", 4870 - h->intr[PERF_MODE_INT], h->devname); 4859 + h->intr[h->intr_mode], h->devname); 4871 4860 return -1; 4872 4861 } 4873 4862 ··· 4898 4887 { 4899 4888 int ctlr = h->ctlr; 4900 4889 4901 - free_irq(h->intr[PERF_MODE_INT], h); 4890 + free_irq(h->intr[h->intr_mode], h); 4902 4891 #ifdef CONFIG_PCI_MSI 4903 4892 if (h->msix_vector) 4904 4893 pci_disable_msix(h->pdev); ··· 4964 4953 h = hba[i]; 4965 4954 h->pdev = pdev; 4966 4955 h->busy_initializing = 1; 4956 + h->intr_mode = cciss_simple_mode ? SIMPLE_MODE_INT : PERF_MODE_INT; 4967 4957 INIT_LIST_HEAD(&h->cmpQ); 4968 4958 INIT_LIST_HEAD(&h->reqQ); 4969 4959 mutex_init(&h->busy_shutting_down); ··· 5021 5009 5022 5010 dev_info(&h->pdev->dev, "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n", 5023 5011 h->devname, pdev->device, pci_name(pdev), 5024 - h->intr[PERF_MODE_INT], dac ? "" : " not"); 5012 + h->intr[h->intr_mode], dac ? "" : " not"); 5025 5013 5026 5014 if (cciss_allocate_cmd_pool(h)) 5027 5015 goto clean4; ··· 5068 5056 spin_lock_irqsave(&h->lock, flags); 5069 5057 h->access.set_intr_mask(h, CCISS_INTR_OFF); 5070 5058 spin_unlock_irqrestore(&h->lock, flags); 5071 - free_irq(h->intr[PERF_MODE_INT], h); 5059 + free_irq(h->intr[h->intr_mode], h); 5072 5060 rc = cciss_request_irq(h, cciss_msix_discard_completions, 5073 5061 cciss_intx_discard_completions); 5074 5062 if (rc) { ··· 5145 5133 cciss_free_cmd_pool(h); 5146 5134 cciss_free_scatterlists(h); 5147 5135 cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds); 5148 - free_irq(h->intr[PERF_MODE_INT], h); 5136 + free_irq(h->intr[h->intr_mode], h); 5149 5137 clean2: 5150 5138 unregister_blkdev(h->major, h->devname); 5151 5139 clean1: ··· 5184 5172 if (return_code != IO_OK) 5185 5173 dev_warn(&h->pdev->dev, "Error flushing cache\n"); 5186 5174 h->access.set_intr_mask(h, CCISS_INTR_OFF); 5187 - free_irq(h->intr[PERF_MODE_INT], h); 5175 + free_irq(h->intr[h->intr_mode], h); 5188 5176 } 5177 + 5178 + static int __devinit cciss_enter_simple_mode(struct ctlr_info *h) 5179 + { 5180 + u32 trans_support; 5181 + 5182 + trans_support = readl(&(h->cfgtable->TransportSupport)); 5183 + if (!(trans_support & SIMPLE_MODE)) 5184 + return -ENOTSUPP; 5185 + 5186 + h->max_commands = readl(&(h->cfgtable->CmdsOutMax)); 5187 + writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest)); 5188 + writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); 5189 + cciss_wait_for_mode_change_ack(h); 5190 + print_cfg_table(h); 5191 + if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) { 5192 + dev_warn(&h->pdev->dev, "unable to get board into simple mode\n"); 5193 + return -ENODEV; 5194 + } 5195 + h->transMethod = CFGTBL_Trans_Simple; 5196 + return 0; 5197 + } 5198 + 5189 5199 5190 5200 static void __devexit cciss_remove_one(struct pci_dev *pdev) 5191 5201 {
+1
drivers/block/cciss.h
··· 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;