diff options
| -rw-r--r-- | Documentation/blockdev/cciss.txt | 10 | ||||
| -rw-r--r-- | drivers/block/cciss.c | 56 | ||||
| -rw-r--r-- | drivers/block/cciss.h | 1 |
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 | ||
| 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 | SCSI tape drive and medium changer support | 91 | SCSI 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; | |||
| 68 | module_param(cciss_tape_cmds, int, 0644); | 68 | module_param(cciss_tape_cmds, int, 0644); |
| 69 | MODULE_PARM_DESC(cciss_tape_cmds, | 69 | MODULE_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)"); |
| 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 | static DEFINE_MUTEX(cciss_mutex); | 76 | static DEFINE_MUTEX(cciss_mutex); |
| 73 | static struct proc_dir_entry *proc_cciss; | 77 | static 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); |
| 178 | static void __devinit cciss_interrupt_mode(ctlr_info_t *); | 182 | static void __devinit cciss_interrupt_mode(ctlr_info_t *); |
| 183 | static int __devinit cciss_enter_simple_mode(struct ctlr_info *h); | ||
| 179 | static void start_io(ctlr_info_t *h); | 184 | static void start_io(ctlr_info_t *h); |
| 180 | static int sendcmd_withirq(ctlr_info_t *h, __u8 cmd, void *buff, size_t size, | 185 | static 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) | |||
| 4081 | default_int_mode: | 4089 | default_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); |
| 5137 | clean2: | 5149 | clean2: |
| 5138 | unregister_blkdev(h->major, h->devname); | 5150 | unregister_blkdev(h->major, h->devname); |
| 5139 | clean1: | 5151 | clean1: |
| @@ -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); |
