diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index b73116e..066577f 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -480,7 +480,7 @@ static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool) do { i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds); - if (i == h->nr_cmds) + if (i >= h->qdepth_max) return NULL; } while (test_and_set_bit (i & (BITS_PER_LONG - 1), @@ -1259,7 +1259,7 @@ static void cciss_check_queues(ctlr_info_t *h) * in case the interrupt we serviced was from an ioctl and did not * free any new commands. */ - if ((find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds)) == h->nr_cmds) + if ((find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds)) >= h->qdepth_max) return; /* We have room on the queue for more commands. Now we need to queue @@ -1278,7 +1278,7 @@ static void cciss_check_queues(ctlr_info_t *h) /* check to see if we have maxed out the number of commands * that can be placed on the queue. */ - if ((find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds)) == h->nr_cmds) { + if ((find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds)) >= h->qdepth_max) { if (curr_queue == start_queue) { h->next_to_run = (start_queue + 1) % (h->highest_lun + 1); @@ -3253,6 +3253,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) c->product_name = products[i].product_name; c->access = *(products[i].access); c->nr_cmds = c->max_commands - 4; + c->qdepth_max = c->nr_cmds; break; } } @@ -3273,6 +3274,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) c->product_name = products[i-1].product_name; c->access = *(products[i-1].access); c->nr_cmds = c->max_commands - 4; + c->qdepth_max = c->nr_cmds; printk(KERN_WARNING "cciss: This is an unknown " "Smart Array controller.\n" "cciss: Please update to the latest driver " @@ -3392,6 +3394,44 @@ static void free_hba(int i) kfree(p); } +static inline ctlr_info_t *cciss_get_ctlr_info(struct device *dev) +{ + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); + return pci_get_drvdata(pdev); +} + +static ssize_t cciss_show_queue_depth(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ctlr_info_t *ctlr = cciss_get_ctlr_info(dev); + BUG_ON(!ctlr); + + return sprintf(buf, "%u\n", ctlr->qdepth_max); +} + +static ssize_t cciss_store_queue_depth(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + ctlr_info_t *ctlr = cciss_get_ctlr_info(dev); + unsigned long qdepth_max; + + BUG_ON(!ctlr); + qdepth_max = simple_strtoul(buf, NULL, 10); + + if (qdepth_max < 1) + qdepth_max = 1; + else if (qdepth_max > ctlr->nr_cmds) + qdepth_max = ctlr->nr_cmds; + + ctlr->qdepth_max = (unsigned)qdepth_max; + return count; +} + +static struct device_attribute cciss_queue_depth = + __ATTR(queue_depth, S_IRUGO | S_IWUSR, + &cciss_show_queue_depth, + &cciss_store_queue_depth); + /* * This is it. Find all the controllers and register them. I really hate * stealing all these major device numbers. @@ -3496,6 +3536,11 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, ((hba[i]->nr_cmds + BITS_PER_LONG - 1) / BITS_PER_LONG) * sizeof(unsigned long)); + /* Setup queue_depth sysfs entry */ + rc = device_create_file(&pdev->dev, &cciss_queue_depth); + if (rc) + goto clean4; + hba[i]->num_luns = 0; hba[i]->highest_lun = -1; for (j = 0; j < CISS_MAX_LUN; j++) { diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index 24a7efa..91dcac6 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h @@ -62,6 +62,7 @@ struct ctlr_info void __iomem *vaddr; unsigned long paddr; int nr_cmds; /* Number of commands allowed on this controller */ + unsigned qdepth_max; /* userspace queue depth limit */ CfgTable_struct __iomem *cfgtable; int interrupts_enabled; int major;