diff options
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r-- | drivers/block/cciss.c | 88 |
1 files changed, 75 insertions, 13 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 8f4ef656a1af..587cce57adae 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/types.h> | 25 | #include <linux/types.h> |
26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
27 | #include <linux/pci-aspm.h> | ||
27 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
28 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
29 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
@@ -68,6 +69,10 @@ static int cciss_tape_cmds = 6; | |||
68 | module_param(cciss_tape_cmds, int, 0644); | 69 | module_param(cciss_tape_cmds, int, 0644); |
69 | MODULE_PARM_DESC(cciss_tape_cmds, | 70 | MODULE_PARM_DESC(cciss_tape_cmds, |
70 | "number of commands to allocate for tape devices (default: 6)"); | 71 | "number of commands to allocate for tape devices (default: 6)"); |
72 | static int cciss_simple_mode; | ||
73 | module_param(cciss_simple_mode, int, S_IRUGO|S_IWUSR); | ||
74 | MODULE_PARM_DESC(cciss_simple_mode, | ||
75 | "Use 'simple mode' rather than 'performant mode'"); | ||
71 | 76 | ||
72 | static DEFINE_MUTEX(cciss_mutex); | 77 | static DEFINE_MUTEX(cciss_mutex); |
73 | static struct proc_dir_entry *proc_cciss; | 78 | static struct proc_dir_entry *proc_cciss; |
@@ -176,6 +181,7 @@ static void cciss_geometry_inquiry(ctlr_info_t *h, int logvol, | |||
176 | unsigned int block_size, InquiryData_struct *inq_buff, | 181 | unsigned int block_size, InquiryData_struct *inq_buff, |
177 | drive_info_struct *drv); | 182 | drive_info_struct *drv); |
178 | static void __devinit cciss_interrupt_mode(ctlr_info_t *); | 183 | static void __devinit cciss_interrupt_mode(ctlr_info_t *); |
184 | static int __devinit cciss_enter_simple_mode(struct ctlr_info *h); | ||
179 | static void start_io(ctlr_info_t *h); | 185 | static void start_io(ctlr_info_t *h); |
180 | static int sendcmd_withirq(ctlr_info_t *h, __u8 cmd, void *buff, size_t size, | 186 | static int sendcmd_withirq(ctlr_info_t *h, __u8 cmd, void *buff, size_t size, |
181 | __u8 page_code, unsigned char scsi3addr[], | 187 | __u8 page_code, unsigned char scsi3addr[], |
@@ -388,7 +394,7 @@ static void cciss_seq_show_header(struct seq_file *seq) | |||
388 | h->product_name, | 394 | h->product_name, |
389 | (unsigned long)h->board_id, | 395 | (unsigned long)h->board_id, |
390 | h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], | 396 | h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], |
391 | h->firm_ver[3], (unsigned int)h->intr[PERF_MODE_INT], | 397 | h->firm_ver[3], (unsigned int)h->intr[h->intr_mode], |
392 | h->num_luns, | 398 | h->num_luns, |
393 | h->Qdepth, h->commands_outstanding, | 399 | h->Qdepth, h->commands_outstanding, |
394 | h->maxQsinceinit, h->max_outstanding, h->maxSG); | 400 | h->maxQsinceinit, h->max_outstanding, h->maxSG); |
@@ -636,6 +642,18 @@ static ssize_t host_store_rescan(struct device *dev, | |||
636 | } | 642 | } |
637 | static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan); | 643 | static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan); |
638 | 644 | ||
645 | static ssize_t host_show_transport_mode(struct device *dev, | ||
646 | struct device_attribute *attr, | ||
647 | char *buf) | ||
648 | { | ||
649 | struct ctlr_info *h = to_hba(dev); | ||
650 | |||
651 | return snprintf(buf, 20, "%s\n", | ||
652 | h->transMethod & CFGTBL_Trans_Performant ? | ||
653 | "performant" : "simple"); | ||
654 | } | ||
655 | static DEVICE_ATTR(transport_mode, S_IRUGO, host_show_transport_mode, NULL); | ||
656 | |||
639 | static ssize_t dev_show_unique_id(struct device *dev, | 657 | static ssize_t dev_show_unique_id(struct device *dev, |
640 | struct device_attribute *attr, | 658 | struct device_attribute *attr, |
641 | char *buf) | 659 | char *buf) |
@@ -808,6 +826,7 @@ static DEVICE_ATTR(usage_count, S_IRUGO, cciss_show_usage_count, NULL); | |||
808 | static struct attribute *cciss_host_attrs[] = { | 826 | static struct attribute *cciss_host_attrs[] = { |
809 | &dev_attr_rescan.attr, | 827 | &dev_attr_rescan.attr, |
810 | &dev_attr_resettable.attr, | 828 | &dev_attr_resettable.attr, |
829 | &dev_attr_transport_mode.attr, | ||
811 | NULL | 830 | NULL |
812 | }; | 831 | }; |
813 | 832 | ||
@@ -2582,6 +2601,8 @@ static int fill_cmd(ctlr_info_t *h, CommandList_struct *c, __u8 cmd, void *buff, | |||
2582 | c->Request.Timeout = 0; | 2601 | c->Request.Timeout = 0; |
2583 | c->Request.CDB[0] = BMIC_WRITE; | 2602 | c->Request.CDB[0] = BMIC_WRITE; |
2584 | c->Request.CDB[6] = BMIC_CACHE_FLUSH; | 2603 | c->Request.CDB[6] = BMIC_CACHE_FLUSH; |
2604 | c->Request.CDB[7] = (size >> 8) & 0xFF; | ||
2605 | c->Request.CDB[8] = size & 0xFF; | ||
2585 | break; | 2606 | break; |
2586 | case TEST_UNIT_READY: | 2607 | case TEST_UNIT_READY: |
2587 | c->Request.CDBLen = 6; | 2608 | c->Request.CDBLen = 6; |
@@ -3984,6 +4005,9 @@ static void __devinit cciss_put_controller_into_performant_mode(ctlr_info_t *h) | |||
3984 | { | 4005 | { |
3985 | __u32 trans_support; | 4006 | __u32 trans_support; |
3986 | 4007 | ||
4008 | if (cciss_simple_mode) | ||
4009 | return; | ||
4010 | |||
3987 | dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n"); | 4011 | dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n"); |
3988 | /* Attempt to put controller into performant mode if supported */ | 4012 | /* Attempt to put controller into performant mode if supported */ |
3989 | /* Does board support performant mode? */ | 4013 | /* Does board support performant mode? */ |
@@ -4081,7 +4105,7 @@ static void __devinit cciss_interrupt_mode(ctlr_info_t *h) | |||
4081 | default_int_mode: | 4105 | default_int_mode: |
4082 | #endif /* CONFIG_PCI_MSI */ | 4106 | #endif /* CONFIG_PCI_MSI */ |
4083 | /* if we get here we're going to use the default interrupt mode */ | 4107 | /* if we get here we're going to use the default interrupt mode */ |
4084 | h->intr[PERF_MODE_INT] = h->pdev->irq; | 4108 | h->intr[h->intr_mode] = h->pdev->irq; |
4085 | return; | 4109 | return; |
4086 | } | 4110 | } |
4087 | 4111 | ||
@@ -4298,6 +4322,10 @@ static int __devinit cciss_pci_init(ctlr_info_t *h) | |||
4298 | dev_warn(&h->pdev->dev, "controller appears to be disabled\n"); | 4322 | dev_warn(&h->pdev->dev, "controller appears to be disabled\n"); |
4299 | return -ENODEV; | 4323 | return -ENODEV; |
4300 | } | 4324 | } |
4325 | |||
4326 | pci_disable_link_state(h->pdev, PCIE_LINK_STATE_L0S | | ||
4327 | PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM); | ||
4328 | |||
4301 | err = pci_enable_device(h->pdev); | 4329 | err = pci_enable_device(h->pdev); |
4302 | if (err) { | 4330 | if (err) { |
4303 | dev_warn(&h->pdev->dev, "Unable to Enable PCI device\n"); | 4331 | dev_warn(&h->pdev->dev, "Unable to Enable PCI device\n"); |
@@ -4341,6 +4369,9 @@ static int __devinit cciss_pci_init(ctlr_info_t *h) | |||
4341 | } | 4369 | } |
4342 | cciss_enable_scsi_prefetch(h); | 4370 | cciss_enable_scsi_prefetch(h); |
4343 | cciss_p600_dma_prefetch_quirk(h); | 4371 | cciss_p600_dma_prefetch_quirk(h); |
4372 | err = cciss_enter_simple_mode(h); | ||
4373 | if (err) | ||
4374 | goto err_out_free_res; | ||
4344 | cciss_put_controller_into_performant_mode(h); | 4375 | cciss_put_controller_into_performant_mode(h); |
4345 | return 0; | 4376 | return 0; |
4346 | 4377 | ||
@@ -4533,6 +4564,13 @@ static int cciss_controller_hard_reset(struct pci_dev *pdev, | |||
4533 | pmcsr &= ~PCI_PM_CTRL_STATE_MASK; | 4564 | pmcsr &= ~PCI_PM_CTRL_STATE_MASK; |
4534 | pmcsr |= PCI_D0; | 4565 | pmcsr |= PCI_D0; |
4535 | pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr); | 4566 | pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr); |
4567 | |||
4568 | /* | ||
4569 | * The P600 requires a small delay when changing states. | ||
4570 | * Otherwise we may think the board did not reset and we bail. | ||
4571 | * This for kdump only and is particular to the P600. | ||
4572 | */ | ||
4573 | msleep(500); | ||
4536 | } | 4574 | } |
4537 | return 0; | 4575 | return 0; |
4538 | } | 4576 | } |
@@ -4843,20 +4881,20 @@ static int cciss_request_irq(ctlr_info_t *h, | |||
4843 | irqreturn_t (*intxhandler)(int, void *)) | 4881 | irqreturn_t (*intxhandler)(int, void *)) |
4844 | { | 4882 | { |
4845 | if (h->msix_vector || h->msi_vector) { | 4883 | if (h->msix_vector || h->msi_vector) { |
4846 | if (!request_irq(h->intr[PERF_MODE_INT], msixhandler, | 4884 | if (!request_irq(h->intr[h->intr_mode], msixhandler, |
4847 | IRQF_DISABLED, h->devname, h)) | 4885 | 0, h->devname, h)) |
4848 | return 0; | 4886 | return 0; |
4849 | dev_err(&h->pdev->dev, "Unable to get msi irq %d" | 4887 | dev_err(&h->pdev->dev, "Unable to get msi irq %d" |
4850 | " for %s\n", h->intr[PERF_MODE_INT], | 4888 | " for %s\n", h->intr[h->intr_mode], |
4851 | h->devname); | 4889 | h->devname); |
4852 | return -1; | 4890 | return -1; |
4853 | } | 4891 | } |
4854 | 4892 | ||
4855 | if (!request_irq(h->intr[PERF_MODE_INT], intxhandler, | 4893 | if (!request_irq(h->intr[h->intr_mode], intxhandler, |
4856 | IRQF_DISABLED, h->devname, h)) | 4894 | IRQF_SHARED, h->devname, h)) |
4857 | return 0; | 4895 | return 0; |
4858 | dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n", | 4896 | dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n", |
4859 | h->intr[PERF_MODE_INT], h->devname); | 4897 | h->intr[h->intr_mode], h->devname); |
4860 | return -1; | 4898 | return -1; |
4861 | } | 4899 | } |
4862 | 4900 | ||
@@ -4887,7 +4925,7 @@ static void cciss_undo_allocations_after_kdump_soft_reset(ctlr_info_t *h) | |||
4887 | { | 4925 | { |
4888 | int ctlr = h->ctlr; | 4926 | int ctlr = h->ctlr; |
4889 | 4927 | ||
4890 | free_irq(h->intr[PERF_MODE_INT], h); | 4928 | free_irq(h->intr[h->intr_mode], h); |
4891 | #ifdef CONFIG_PCI_MSI | 4929 | #ifdef CONFIG_PCI_MSI |
4892 | if (h->msix_vector) | 4930 | if (h->msix_vector) |
4893 | pci_disable_msix(h->pdev); | 4931 | pci_disable_msix(h->pdev); |
@@ -4953,6 +4991,7 @@ reinit_after_soft_reset: | |||
4953 | h = hba[i]; | 4991 | h = hba[i]; |
4954 | h->pdev = pdev; | 4992 | h->pdev = pdev; |
4955 | h->busy_initializing = 1; | 4993 | h->busy_initializing = 1; |
4994 | h->intr_mode = cciss_simple_mode ? SIMPLE_MODE_INT : PERF_MODE_INT; | ||
4956 | INIT_LIST_HEAD(&h->cmpQ); | 4995 | INIT_LIST_HEAD(&h->cmpQ); |
4957 | INIT_LIST_HEAD(&h->reqQ); | 4996 | INIT_LIST_HEAD(&h->reqQ); |
4958 | mutex_init(&h->busy_shutting_down); | 4997 | mutex_init(&h->busy_shutting_down); |
@@ -5009,7 +5048,7 @@ reinit_after_soft_reset: | |||
5009 | 5048 | ||
5010 | dev_info(&h->pdev->dev, "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n", | 5049 | 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), | 5050 | h->devname, pdev->device, pci_name(pdev), |
5012 | h->intr[PERF_MODE_INT], dac ? "" : " not"); | 5051 | h->intr[h->intr_mode], dac ? "" : " not"); |
5013 | 5052 | ||
5014 | if (cciss_allocate_cmd_pool(h)) | 5053 | if (cciss_allocate_cmd_pool(h)) |
5015 | goto clean4; | 5054 | goto clean4; |
@@ -5056,7 +5095,7 @@ reinit_after_soft_reset: | |||
5056 | spin_lock_irqsave(&h->lock, flags); | 5095 | spin_lock_irqsave(&h->lock, flags); |
5057 | h->access.set_intr_mask(h, CCISS_INTR_OFF); | 5096 | h->access.set_intr_mask(h, CCISS_INTR_OFF); |
5058 | spin_unlock_irqrestore(&h->lock, flags); | 5097 | spin_unlock_irqrestore(&h->lock, flags); |
5059 | free_irq(h->intr[PERF_MODE_INT], h); | 5098 | free_irq(h->intr[h->intr_mode], h); |
5060 | rc = cciss_request_irq(h, cciss_msix_discard_completions, | 5099 | rc = cciss_request_irq(h, cciss_msix_discard_completions, |
5061 | cciss_intx_discard_completions); | 5100 | cciss_intx_discard_completions); |
5062 | if (rc) { | 5101 | if (rc) { |
@@ -5126,6 +5165,7 @@ reinit_after_soft_reset: | |||
5126 | h->cciss_max_sectors = 8192; | 5165 | h->cciss_max_sectors = 8192; |
5127 | 5166 | ||
5128 | rebuild_lun_table(h, 1, 0); | 5167 | rebuild_lun_table(h, 1, 0); |
5168 | cciss_engage_scsi(h); | ||
5129 | h->busy_initializing = 0; | 5169 | h->busy_initializing = 0; |
5130 | return 1; | 5170 | return 1; |
5131 | 5171 | ||
@@ -5133,7 +5173,7 @@ clean4: | |||
5133 | cciss_free_cmd_pool(h); | 5173 | cciss_free_cmd_pool(h); |
5134 | cciss_free_scatterlists(h); | 5174 | cciss_free_scatterlists(h); |
5135 | cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds); | 5175 | cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds); |
5136 | free_irq(h->intr[PERF_MODE_INT], h); | 5176 | free_irq(h->intr[h->intr_mode], h); |
5137 | clean2: | 5177 | clean2: |
5138 | unregister_blkdev(h->major, h->devname); | 5178 | unregister_blkdev(h->major, h->devname); |
5139 | clean1: | 5179 | clean1: |
@@ -5172,9 +5212,31 @@ static void cciss_shutdown(struct pci_dev *pdev) | |||
5172 | if (return_code != IO_OK) | 5212 | if (return_code != IO_OK) |
5173 | dev_warn(&h->pdev->dev, "Error flushing cache\n"); | 5213 | dev_warn(&h->pdev->dev, "Error flushing cache\n"); |
5174 | h->access.set_intr_mask(h, CCISS_INTR_OFF); | 5214 | h->access.set_intr_mask(h, CCISS_INTR_OFF); |
5175 | free_irq(h->intr[PERF_MODE_INT], h); | 5215 | free_irq(h->intr[h->intr_mode], h); |
5176 | } | 5216 | } |
5177 | 5217 | ||
5218 | static int __devinit cciss_enter_simple_mode(struct ctlr_info *h) | ||
5219 | { | ||
5220 | u32 trans_support; | ||
5221 | |||
5222 | trans_support = readl(&(h->cfgtable->TransportSupport)); | ||
5223 | if (!(trans_support & SIMPLE_MODE)) | ||
5224 | return -ENOTSUPP; | ||
5225 | |||
5226 | h->max_commands = readl(&(h->cfgtable->CmdsOutMax)); | ||
5227 | writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest)); | ||
5228 | writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); | ||
5229 | cciss_wait_for_mode_change_ack(h); | ||
5230 | print_cfg_table(h); | ||
5231 | if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) { | ||
5232 | dev_warn(&h->pdev->dev, "unable to get board into simple mode\n"); | ||
5233 | return -ENODEV; | ||
5234 | } | ||
5235 | h->transMethod = CFGTBL_Trans_Simple; | ||
5236 | return 0; | ||
5237 | } | ||
5238 | |||
5239 | |||
5178 | static void __devexit cciss_remove_one(struct pci_dev *pdev) | 5240 | static void __devexit cciss_remove_one(struct pci_dev *pdev) |
5179 | { | 5241 | { |
5180 | ctlr_info_t *h; | 5242 | ctlr_info_t *h; |