Commit 13049537 authored by Joseph Handzik's avatar Joseph Handzik Committed by Jens Axboe

cciss: Adds simple mode functionality

Signed-off-by: default avatarJoseph Handzik <joseph.t.handzik@beardog.cce.hp.com>
Acked-by: default avatarStephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: default avatarJens Axboe <jaxboe@fusionio.com>
parent 322a8b03
...@@ -78,6 +78,16 @@ The device naming scheme is: ...@@ -78,6 +78,16 @@ The device naming scheme is:
/dev/cciss/c1d1p2 Controller 1, disk 1, partition 2 /dev/cciss/c1d1p2 Controller 1, disk 1, partition 2
/dev/cciss/c1d1p3 Controller 1, disk 1, partition 3 /dev/cciss/c1d1p3 Controller 1, disk 1, partition 3
CCISS simple mode support
-------------------------
The "cciss_simple_mode=1" boot parameter may be used to prevent the driver
from putting the controller into "performant" mode. The difference is that
with simple mode, each command completion requires an interrupt, while with
"performant mode" (the default, and ordinarily better performing) it is
possible to have multiple command completions indicated by a single
interrupt.
SCSI tape drive and medium changer support SCSI tape drive and medium changer support
------------------------------------------ ------------------------------------------
......
...@@ -68,6 +68,10 @@ static int cciss_tape_cmds = 6; ...@@ -68,6 +68,10 @@ static int cciss_tape_cmds = 6;
module_param(cciss_tape_cmds, int, 0644); module_param(cciss_tape_cmds, int, 0644);
MODULE_PARM_DESC(cciss_tape_cmds, MODULE_PARM_DESC(cciss_tape_cmds,
"number of commands to allocate for tape devices (default: 6)"); "number of commands to allocate for tape devices (default: 6)");
static int cciss_simple_mode;
module_param(cciss_simple_mode, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(cciss_simple_mode,
"Use 'simple mode' rather than 'performant mode'");
static DEFINE_MUTEX(cciss_mutex); static DEFINE_MUTEX(cciss_mutex);
static struct proc_dir_entry *proc_cciss; static struct proc_dir_entry *proc_cciss;
...@@ -176,6 +180,7 @@ static void cciss_geometry_inquiry(ctlr_info_t *h, int logvol, ...@@ -176,6 +180,7 @@ static void cciss_geometry_inquiry(ctlr_info_t *h, int logvol,
unsigned int block_size, InquiryData_struct *inq_buff, unsigned int block_size, InquiryData_struct *inq_buff,
drive_info_struct *drv); drive_info_struct *drv);
static void __devinit cciss_interrupt_mode(ctlr_info_t *); static void __devinit cciss_interrupt_mode(ctlr_info_t *);
static int __devinit cciss_enter_simple_mode(struct ctlr_info *h);
static void start_io(ctlr_info_t *h); static void start_io(ctlr_info_t *h);
static int sendcmd_withirq(ctlr_info_t *h, __u8 cmd, void *buff, size_t size, static int sendcmd_withirq(ctlr_info_t *h, __u8 cmd, void *buff, size_t size,
__u8 page_code, unsigned char scsi3addr[], __u8 page_code, unsigned char scsi3addr[],
...@@ -388,7 +393,7 @@ static void cciss_seq_show_header(struct seq_file *seq) ...@@ -388,7 +393,7 @@ static void cciss_seq_show_header(struct seq_file *seq)
h->product_name, h->product_name,
(unsigned long)h->board_id, (unsigned long)h->board_id,
h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], h->firm_ver[0], h->firm_ver[1], h->firm_ver[2],
h->firm_ver[3], (unsigned int)h->intr[PERF_MODE_INT], h->firm_ver[3], (unsigned int)h->intr[h->intr_mode],
h->num_luns, h->num_luns,
h->Qdepth, h->commands_outstanding, h->Qdepth, h->commands_outstanding,
h->maxQsinceinit, h->max_outstanding, h->maxSG); 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,6 +3989,9 @@ static void __devinit cciss_put_controller_into_performant_mode(ctlr_info_t *h)
{ {
__u32 trans_support; __u32 trans_support;
if (cciss_simple_mode)
return;
dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n"); dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n");
/* Attempt to put controller into performant mode if supported */ /* Attempt to put controller into performant mode if supported */
/* Does board support performant mode? */ /* Does board support performant mode? */
...@@ -4081,7 +4089,7 @@ static void __devinit cciss_interrupt_mode(ctlr_info_t *h) ...@@ -4081,7 +4089,7 @@ static void __devinit cciss_interrupt_mode(ctlr_info_t *h)
default_int_mode: default_int_mode:
#endif /* CONFIG_PCI_MSI */ #endif /* CONFIG_PCI_MSI */
/* if we get here we're going to use the default interrupt mode */ /* if we get here we're going to use the default interrupt mode */
h->intr[PERF_MODE_INT] = h->pdev->irq; h->intr[h->intr_mode] = h->pdev->irq;
return; return;
} }
...@@ -4341,6 +4349,9 @@ static int __devinit cciss_pci_init(ctlr_info_t *h) ...@@ -4341,6 +4349,9 @@ static int __devinit cciss_pci_init(ctlr_info_t *h)
} }
cciss_enable_scsi_prefetch(h); cciss_enable_scsi_prefetch(h);
cciss_p600_dma_prefetch_quirk(h); cciss_p600_dma_prefetch_quirk(h);
err = cciss_enter_simple_mode(h);
if (err)
goto err_out_free_res;
cciss_put_controller_into_performant_mode(h); cciss_put_controller_into_performant_mode(h);
return 0; return 0;
...@@ -4843,20 +4854,20 @@ static int cciss_request_irq(ctlr_info_t *h, ...@@ -4843,20 +4854,20 @@ static int cciss_request_irq(ctlr_info_t *h,
irqreturn_t (*intxhandler)(int, void *)) irqreturn_t (*intxhandler)(int, void *))
{ {
if (h->msix_vector || h->msi_vector) { if (h->msix_vector || h->msi_vector) {
if (!request_irq(h->intr[PERF_MODE_INT], msixhandler, if (!request_irq(h->intr[h->intr_mode], msixhandler,
IRQF_DISABLED, h->devname, h)) IRQF_DISABLED, h->devname, h))
return 0; return 0;
dev_err(&h->pdev->dev, "Unable to get msi irq %d" dev_err(&h->pdev->dev, "Unable to get msi irq %d"
" for %s\n", h->intr[PERF_MODE_INT], " for %s\n", h->intr[h->intr_mode],
h->devname); h->devname);
return -1; return -1;
} }
if (!request_irq(h->intr[PERF_MODE_INT], intxhandler, if (!request_irq(h->intr[h->intr_mode], intxhandler,
IRQF_DISABLED, h->devname, h)) IRQF_DISABLED, h->devname, h))
return 0; return 0;
dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n", dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n",
h->intr[PERF_MODE_INT], h->devname); h->intr[h->intr_mode], h->devname);
return -1; return -1;
} }
...@@ -4887,7 +4898,7 @@ static void cciss_undo_allocations_after_kdump_soft_reset(ctlr_info_t *h) ...@@ -4887,7 +4898,7 @@ static void cciss_undo_allocations_after_kdump_soft_reset(ctlr_info_t *h)
{ {
int ctlr = h->ctlr; int ctlr = h->ctlr;
free_irq(h->intr[PERF_MODE_INT], h); free_irq(h->intr[h->intr_mode], h);
#ifdef CONFIG_PCI_MSI #ifdef CONFIG_PCI_MSI
if (h->msix_vector) if (h->msix_vector)
pci_disable_msix(h->pdev); pci_disable_msix(h->pdev);
...@@ -4953,6 +4964,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, ...@@ -4953,6 +4964,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
h = hba[i]; h = hba[i];
h->pdev = pdev; h->pdev = pdev;
h->busy_initializing = 1; h->busy_initializing = 1;
h->intr_mode = cciss_simple_mode ? SIMPLE_MODE_INT : PERF_MODE_INT;
INIT_LIST_HEAD(&h->cmpQ); INIT_LIST_HEAD(&h->cmpQ);
INIT_LIST_HEAD(&h->reqQ); INIT_LIST_HEAD(&h->reqQ);
mutex_init(&h->busy_shutting_down); mutex_init(&h->busy_shutting_down);
...@@ -5009,7 +5021,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, ...@@ -5009,7 +5021,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
dev_info(&h->pdev->dev, "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n", dev_info(&h->pdev->dev, "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n",
h->devname, pdev->device, pci_name(pdev), h->devname, pdev->device, pci_name(pdev),
h->intr[PERF_MODE_INT], dac ? "" : " not"); h->intr[h->intr_mode], dac ? "" : " not");
if (cciss_allocate_cmd_pool(h)) if (cciss_allocate_cmd_pool(h))
goto clean4; goto clean4;
...@@ -5056,7 +5068,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, ...@@ -5056,7 +5068,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
spin_lock_irqsave(&h->lock, flags); spin_lock_irqsave(&h->lock, flags);
h->access.set_intr_mask(h, CCISS_INTR_OFF); h->access.set_intr_mask(h, CCISS_INTR_OFF);
spin_unlock_irqrestore(&h->lock, flags); spin_unlock_irqrestore(&h->lock, flags);
free_irq(h->intr[PERF_MODE_INT], h); free_irq(h->intr[h->intr_mode], h);
rc = cciss_request_irq(h, cciss_msix_discard_completions, rc = cciss_request_irq(h, cciss_msix_discard_completions,
cciss_intx_discard_completions); cciss_intx_discard_completions);
if (rc) { if (rc) {
...@@ -5133,7 +5145,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, ...@@ -5133,7 +5145,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
cciss_free_cmd_pool(h); cciss_free_cmd_pool(h);
cciss_free_scatterlists(h); cciss_free_scatterlists(h);
cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds); cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds);
free_irq(h->intr[PERF_MODE_INT], h); free_irq(h->intr[h->intr_mode], h);
clean2: clean2:
unregister_blkdev(h->major, h->devname); unregister_blkdev(h->major, h->devname);
clean1: clean1:
...@@ -5172,9 +5184,31 @@ static void cciss_shutdown(struct pci_dev *pdev) ...@@ -5172,9 +5184,31 @@ static void cciss_shutdown(struct pci_dev *pdev)
if (return_code != IO_OK) if (return_code != IO_OK)
dev_warn(&h->pdev->dev, "Error flushing cache\n"); dev_warn(&h->pdev->dev, "Error flushing cache\n");
h->access.set_intr_mask(h, CCISS_INTR_OFF); h->access.set_intr_mask(h, CCISS_INTR_OFF);
free_irq(h->intr[PERF_MODE_INT], h); free_irq(h->intr[h->intr_mode], h);
} }
static int __devinit cciss_enter_simple_mode(struct ctlr_info *h)
{
u32 trans_support;
trans_support = readl(&(h->cfgtable->TransportSupport));
if (!(trans_support & SIMPLE_MODE))
return -ENOTSUPP;
h->max_commands = readl(&(h->cfgtable->CmdsOutMax));
writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest));
writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
cciss_wait_for_mode_change_ack(h);
print_cfg_table(h);
if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) {
dev_warn(&h->pdev->dev, "unable to get board into simple mode\n");
return -ENODEV;
}
h->transMethod = CFGTBL_Trans_Simple;
return 0;
}
static void __devexit cciss_remove_one(struct pci_dev *pdev) static void __devexit cciss_remove_one(struct pci_dev *pdev)
{ {
ctlr_info_t *h; ctlr_info_t *h;
......
...@@ -92,6 +92,7 @@ struct ctlr_info ...@@ -92,6 +92,7 @@ struct ctlr_info
unsigned int intr[4]; unsigned int intr[4];
unsigned int msix_vector; unsigned int msix_vector;
unsigned int msi_vector; unsigned int msi_vector;
int intr_mode;
int cciss_max_sectors; int cciss_max_sectors;
BYTE cciss_read; BYTE cciss_read;
BYTE cciss_write; BYTE cciss_write;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment