Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 293

kernel-2.6.18-238.el5.src.rpm

From: Tomas Henzl <thenzl@redhat.com>
Date: Sun, 29 Aug 2010 15:49:49 -0400
Subject: [block] cciss: add more commands for tapes
Message-id: <1283097002-3341-51-git-send-email-thenzl@redhat.com>
Patchwork-id: 27892
O-Subject: [RHEL6 PATCH 50/63] cciss: add more commands for tapes
Bugzilla: 568830
RH-Acked-by: Neil Horman <nhorman@redhat.com>

Allow number of commands reserved for use by SCSI tape drives
and medium changes to be adjusted at driver load time via the
kernel parameter cciss_tape_cmds, with a default value of 6, and
a range of 2 - 16 inclusive.
Previously, the driver limited the number of commands which could be queued to the
SCSI half of the the driver to only 2.

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index fbc3c74..00d3158 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -63,6 +63,9 @@ MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
 			" and HP Smart Array G2 SAS/SATA Controllers");
 MODULE_VERSION("3.6.20-RH4");
 MODULE_LICENSE("GPL");
+static int cciss_tape_cmds = 6;
+module_param(cciss_tape_cmds, int, 0644);
+MODULE_PARM_DESC(cciss_tape_cmds, "number of commands to allocate for tape devices (default: 6)");
 
 #include "cciss_cmd.h"
 #include "cciss.h"
@@ -3746,7 +3749,8 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
 		if (board_id == products[i].board_id) {
 			c->product_name = products[i].product_name;
 			c->access = *(products[i].access);
-			c->nr_cmds = c->max_commands - 4;
+			c->nr_cmds = 
+				c->max_commands - 4 - cciss_tape_cmds;
 			break;
 		}
 	}
@@ -3766,7 +3770,8 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
 		if (subsystem_vendor_id == PCI_VENDOR_ID_HP) {
 			c->product_name = products[i-1].product_name;
 			c->access = *(products[i-1].access);
-			c->nr_cmds = c->max_commands - 4;
+			c->nr_cmds =
+				c->max_commands - 4 - cciss_tape_cmds;
 			printk(KERN_WARNING "cciss: This is an unknown "
 				"Smart Array controller.\n");
 		} else {
@@ -4121,6 +4126,11 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
 	INIT_HLIST_HEAD(&hba[i]->cmpQ);
 	INIT_HLIST_HEAD(&hba[i]->reqQ);
 
+	if (cciss_tape_cmds < 2)
+		cciss_tape_cmds = 2;
+	if (cciss_tape_cmds > 16)
+		cciss_tape_cmds = 16;
+
 	if (cciss_pci_init(hba[i], pdev) != 0)
 		goto clean_no_release_regions;
 
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index e40341e..08e938f 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -85,7 +85,6 @@ static struct scsi_host_template cciss_driver_template = {
 	.proc_name		= "cciss",
 	.proc_info		= cciss_scsi_proc_info,
 	.queuecommand		= cciss_scsi_queue_command,
-	.can_queue		= SCSI_CCISS_CAN_QUEUE,
 	.this_id		= 7,
 	.sg_tablesize		= MAXSGENTRIES,
 	.cmd_per_lun		= 1,
@@ -103,18 +102,12 @@ struct cciss_scsi_cmd_stack_elem_t {
 	__u32 pad;
 };
 
-#pragma pack()
-
-#define CMD_STACK_SIZE (SCSI_CCISS_CAN_QUEUE * \
-		CCISS_MAX_SCSI_DEVS_PER_HBA + 2)
-			// plus two for init time usage
-
-#pragma pack(1)
 struct cciss_scsi_cmd_stack_t {
 	struct cciss_scsi_cmd_stack_elem_t *pool;
-	struct cciss_scsi_cmd_stack_elem_t *elem[CMD_STACK_SIZE];
+	struct cciss_scsi_cmd_stack_elem_t **elem;
 	dma_addr_t cmd_pool_handle;
 	int top;
+	int nelems;
 };
 #pragma pack()
 
@@ -185,7 +178,7 @@ scsi_cmd_free(ctlr_info_t *h, CommandList_struct *cmd)
 
 	sa = h->scsi_ctlr;
 	stk = &sa->cmd_stack; 
-	if (stk->top >= CMD_STACK_SIZE) {
+	if (stk->top >= stk->nelems) {
 		printk("cciss: scsi_cmd_free called too many times.\n");
 		BUG();
 	}
@@ -201,7 +194,8 @@ scsi_cmd_stack_setup(int ctlr, struct cciss_scsi_adapter_data_t *sa)
 	size_t size;
 
 	stk = &sa->cmd_stack; 
-	size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE;
+	stk->nelems = cciss_tape_cmds + 2;
+	size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * stk->nelems;
 
 	/* Check alignment, see cciss_cmd.h near CommandList_struct def. */
 	BUILD_BUG_ON((sizeof(struct cciss_scsi_cmd_stack_elem_t) % 8) != 0);
@@ -216,12 +210,18 @@ scsi_cmd_stack_setup(int ctlr, struct cciss_scsi_adapter_data_t *sa)
 		return -1;
 	}
 
-	for (i=0; i<CMD_STACK_SIZE; i++) {
+	stk->elem = kmalloc(sizeof(stk->elem[0]) * stk->nelems, GFP_KERNEL);
+	if (!stk->elem) {
+		pci_free_consistent(hba[ctlr]->pdev, size, stk->pool, stk->cmd_pool_handle);
+		return -1;
+	}
+
+	for (i=0; i<stk->nelems; i++) {
 		stk->elem[i] = &stk->pool[i];
 		stk->elem[i]->busaddr = (__u32) (stk->cmd_pool_handle + 
 			(sizeof(struct cciss_scsi_cmd_stack_elem_t) * i));
 	}
-	stk->top = CMD_STACK_SIZE-1;
+	stk->top = stk->nelems-1;
 	return 0;
 }
 
@@ -234,13 +234,13 @@ scsi_cmd_stack_free(int ctlr)
 
 	sa = hba[ctlr]->scsi_ctlr;
 	stk = &sa->cmd_stack; 
-	if (stk->top != CMD_STACK_SIZE-1) {
+	if (stk->top != stk->nelems-1) {
 		printk( "cciss: %d scsi commands are still outstanding.\n",
-			CMD_STACK_SIZE - stk->top);
+			stk->nelems - stk->top);
 		// BUG();
 		printk("WE HAVE A BUG HERE!!! stk=0x%p\n", stk);
 	}
-	size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE;
+	size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * stk->nelems;
 
 	pci_free_consistent(hba[ctlr]->pdev, size, stk->pool, stk->cmd_pool_handle);
 	stk->pool = NULL;
@@ -691,6 +691,7 @@ cciss_scsi_detect(int ctlr)
 	sh->io_port = 0;	// good enough?  FIXME, 
 	sh->n_io_port = 0;	// I don't think we use these two...
 	sh->this_id = SELF_SCSI_ID;  
+	sh->can_queue = cciss_tape_cmds;
 
 	((struct cciss_scsi_adapter_data_t *) 
 		hba[ctlr]->scsi_ctlr)->scsi_host = sh;
diff --git a/drivers/block/cciss_scsi.h b/drivers/block/cciss_scsi.h
index 00b581e..a0a5c42 100644
--- a/drivers/block/cciss_scsi.h
+++ b/drivers/block/cciss_scsi.h
@@ -38,13 +38,8 @@
 		// addressible natively, and may in fact turn
 		// out to be not scsi at all.
 
-#define SCSI_CCISS_CAN_QUEUE 2
-
 /* 
 
-Note, cmd_per_lun could give us some trouble, so I'm setting it very low.
-Likewise, SCSI_CCISS_CAN_QUEUE is set very conservatively.
-
 If the upper scsi layer tries to track how many commands we have 
 outstanding, it will be operating under the misapprehension that it is
 the only one sending us requests.  We also have the block interface,