patch-2.4.5 linux/drivers/block/cpqarray.c

Next file: linux/drivers/block/cpqarray.h
Previous file: linux/drivers/block/cciss_cmd.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.4/linux/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c
@@ -44,8 +44,8 @@
 
 #define SMART2_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
 
-#define DRIVER_NAME "Compaq SMART2 Driver (v 2.4.2)"
-#define DRIVER_VERSION SMART2_DRIVER_VERSION(2,4,2)
+#define DRIVER_NAME "Compaq SMART2 Driver (v 2.4.4)"
+#define DRIVER_VERSION SMART2_DRIVER_VERSION(2,4,4)
 
 /* Embedded module documentation macros - see modules.h */
 /* Original author Chris Frantz - Compaq Computer Corporation */
@@ -68,6 +68,8 @@
 #define MAX_CTLR	8
 #define CTLR_SHIFT	8
 
+#define CPQARRAY_DMA_MASK	0xFFFFFFFF	/* 32 bit DMA */
+
 static int nr_ctlr;
 static ctlr_info_t *hba[MAX_CTLR];
 
@@ -123,8 +125,8 @@
 static void getgeometry(int ctlr);
 static void start_fwbk(int ctlr);
 
-static cmdlist_t * cmd_alloc(ctlr_info_t *h);
-static void cmd_free(ctlr_info_t *h, cmdlist_t *c);
+static cmdlist_t * cmd_alloc(ctlr_info_t *h, int get_from_pool);
+static void cmd_free(ctlr_info_t *h, cmdlist_t *c, int got_from_pool);
 
 static int sendcmd(
 	__u8	cmd,
@@ -204,7 +206,7 @@
 static void __init ida_procinit(int i)
 {
 	if (proc_array == NULL) {
-		proc_array = proc_mkdir("driver/array", NULL);
+		proc_array = proc_mkdir("array", proc_root_driver);
 		if (!proc_array) return;
 	}
 
@@ -228,12 +230,12 @@
 
 	ctlr = h->ctlr;
 	size = sprintf(buffer, "%s:  Compaq %s Controller\n"
-		"       Board ID: %08lx\n"
+		"       Board ID: 0x%08lx\n"
 		"       Firmware Revision: %c%c%c%c\n"
-		"       Controller Sig: %08lx\n"
-		"       Memory Address: %08lx\n"
-		"       I/O Port: %04x\n"
-		"       IRQ: %x\n"
+		"       Controller Sig: 0x%08lx\n"
+		"       Memory Address: 0x%08lx\n"
+		"       I/O Port: 0x%04x\n"
+		"       IRQ: %d\n"
 		"       Logical drives: %d\n"
 		"       Physical drives: %d\n\n"
 		"       Current Q depth: %d\n"
@@ -314,7 +316,7 @@
 	int i;
 	struct gendisk *g;
 
-	remove_proc_entry("driver/array", NULL);
+	remove_proc_entry("array", proc_root_driver);
 
 	for(i=0; i<nr_ctlr; i++) {
 		hba[i]->access.set_intr_mask(hba[i], 0);
@@ -324,7 +326,9 @@
 		del_timer(&hba[i]->timer);
 		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + i));
 		remove_proc_entry(hba[i]->devname, proc_array);
-		kfree(hba[i]->cmd_pool);
+		pci_free_consistent(hba[i]->pci_dev, 
+			NR_CMDS * sizeof(cmdlist_t), (hba[i]->cmd_pool), 
+			hba[i]->cmd_pool_dhandle);
 		kfree(hba[i]->cmd_pool_bits);
 
 		if (gendisk_head == &ida_gendisk[i]) {
@@ -474,8 +478,9 @@
 			continue;
 		}
 		num_cntlrs_reg++;
-		hba[i]->cmd_pool = (cmdlist_t *)kmalloc(
-				NR_CMDS * sizeof(cmdlist_t), GFP_KERNEL);
+		hba[i]->cmd_pool = (cmdlist_t *)pci_alloc_consistent(
+				hba[i]->pci_dev, NR_CMDS * sizeof(cmdlist_t), 
+				&(hba[i]->cmd_pool_dhandle));
 		hba[i]->cmd_pool_bits = (__u32*)kmalloc(
 				((NR_CMDS+31)/32)*sizeof(__u32), GFP_KERNEL);
 		
@@ -485,7 +490,10 @@
 			if(hba[i]->cmd_pool_bits)
 				kfree(hba[i]->cmd_pool_bits);
 			if(hba[i]->cmd_pool)
-				kfree(hba[i]->cmd_pool);
+				pci_free_consistent(hba[i]->pci_dev, 
+					NR_CMDS * sizeof(cmdlist_t), 
+					hba[i]->cmd_pool, 
+					hba[i]->cmd_pool_dhandle);
 			free_irq(hba[i]->intr, hba[i]);
 			unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
 			num_cntlrs_reg--;
@@ -580,9 +588,11 @@
 		pdev = pci_find_device(ida_vendor_id[brdtype],
 				       ida_device_id[brdtype], NULL);
 		while (pdev) {
-			printk(KERN_DEBUG "cpqarray: Device %x has been found at %x %x\n",
+			printk(KERN_DEBUG "cpqarray: Device 0x%x has"
+				" been found at bus %d dev %d func %d\n",
 				ida_vendor_id[brdtype],
-				pdev->bus->number, pdev->devfn);
+				pdev->bus->number, PCI_SLOT(pdev->devfn),
+				PCI_FUNC(pdev->devfn));
 			if (nr_ctlr == 8) {
 				printk(KERN_WARNING "cpqarray: This driver"
 				" supports a maximum of 8 controllers.\n");
@@ -647,7 +657,15 @@
 		addr[i] = pci_resource_start(pdev, i);
 
 	if (pci_enable_device(pdev))
+	{
+		printk(KERN_ERR "cpqarray: Unable to Enable PCI device\n");
+		return -1;
+	}
+	if (pci_set_dma_mask(pdev, CPQARRAY_DMA_MASK) != 0)
+	{
+		printk(KERN_ERR "cpqarray: Unable to set DMA mask\n");
 		return -1;
+	}
 
 	pci_read_config_word(pdev, PCI_COMMAND, &command);
 	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
@@ -905,7 +923,12 @@
 	struct list_head * queue_head = &q->queue_head;
 	struct buffer_head *bh;
 	struct request *creq;
+	struct my_sg tmp_sg[SG_MAX];
+	int i;
 
+// Loop till the queue is empty if or it is plugged 
+   while (1)
+{
 	if (q->plugged || list_empty(queue_head)) {
 		start_io(h);
 		return;
@@ -925,7 +948,7 @@
                 return;
 	}
 
-	if ((c = cmd_alloc(h)) == NULL)
+	if ((c = cmd_alloc(h,1)) == NULL)
 	{
                 start_io(h);
                 return;
@@ -951,18 +974,28 @@
 	while(bh) {
 		sect += bh->b_size/512;
 		if (bh->b_data == lastdataend) {
-			c->req.sg[seg-1].size += bh->b_size;
+			tmp_sg[seg-1].size += bh->b_size;
 			lastdataend += bh->b_size;
 		} else {
 			if (seg == SG_MAX)
 				BUG();
-			c->req.sg[seg].size = bh->b_size;
-			c->req.sg[seg].addr = (__u32)virt_to_bus(bh->b_data);
+			tmp_sg[seg].size = bh->b_size;
+			tmp_sg[seg].start_addr = bh->b_data;
 			lastdataend = bh->b_data + bh->b_size;
 			seg++;
 		}
 		bh = bh->b_reqnext;
 	}
+	/* Now do all the DMA Mappings */
+	for( i=0; i < seg; i++)
+	{
+		c->req.sg[i].size = tmp_sg[i].size;
+		c->req.sg[i].addr = (__u32) pci_map_single(
+                		h->pci_dev, tmp_sg[i].start_addr, 
+				tmp_sg[i].size,
+                                (creq->cmd == READ) ? 
+					PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+	}
 DBGPX(	printk("Submitting %d sectors in %d segments\n", sect, seg); );
 	c->req.hdr.sg_cnt = seg;
 	c->req.hdr.blk_cnt = sect;
@@ -993,8 +1026,7 @@
 	h->Qdepth++;
 	if (h->Qdepth > h->maxQsinceinit) 
 		h->maxQsinceinit = h->Qdepth;
-
-	start_io(h);
+   } // while loop
 }
 
 /* 
@@ -1043,6 +1075,7 @@
 static inline void complete_command(cmdlist_t *cmd, int timeout)
 {
 	int ok=1;
+	int i;
 
 	if (cmd->req.hdr.rcode & RCODE_NONFATAL &&
 	   (hba[cmd->ctlr]->misc_tflags & MISC_NONFATAL_WARN) == 0) {
@@ -1063,6 +1096,13 @@
 		ok = 0;	
 	}
 	if (timeout) ok = 0;
+	/* unmap the DMA mapping for all the scatter gather elements */
+        for(i=0; i<cmd->req.hdr.sg_cnt; i++)
+        {
+                pci_unmap_single(hba[cmd->ctlr]->pci_dev,
+                        cmd->req.sg[i].addr, cmd->req.sg[i].size,
+                        (cmd->req.hdr.cmd == IDA_READ) ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+        }
 	complete_buffers(cmd->bh, ok);
 }
 
@@ -1110,7 +1150,7 @@
 				removeQ(&h->cmpQ, c);
 				if (c->type == CMD_RWREQ) {
 					complete_command(c, 0);
-					cmd_free(h, c);
+					cmd_free(h, c, 1);
 				} else if (c->type == CMD_IOCTL_PEND) {
 					c->type = CMD_IOCTL_DONE;
 				}
@@ -1243,7 +1283,7 @@
 	unsigned long flags;
 	int error;
 
-	if ((c = cmd_alloc(NULL)) == NULL)
+	if ((c = cmd_alloc(h, 0)) == NULL)
 		return -ENOMEM;
 	c->ctlr = ctlr;
 	c->hdr.unit = (io->unit & UNITVALID) ? (io->unit & ~UNITVALID) : dsk;
@@ -1262,13 +1302,16 @@
 		if (!p) 
 		{ 
 			error = -ENOMEM; 
-			cmd_free(NULL, c); 
+			cmd_free(h, c, 0); 
 			return(error);
 		}
 		copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size);
-		c->req.hdr.blk = virt_to_bus(&(io->c));
+		c->req.hdr.blk = pci_map_single(h->pci_dev, &(io->c), 
+				sizeof(ida_ioctl_t), 
+				PCI_DMA_BIDIRECTIONAL);
 		c->req.sg[0].size = io->sg[0].size;
-		c->req.sg[0].addr = virt_to_bus(p);
+		c->req.sg[0].addr = pci_map_single(h->pci_dev, p, 
+			c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
 		c->req.hdr.sg_cnt = 1;
 		break;
 	case IDA_READ:
@@ -1276,12 +1319,13 @@
 		if (!p) 
 		{ 
                         error = -ENOMEM; 
-                        cmd_free(NULL, c);
+                        cmd_free(h, c, 0);
                         return(error);
                 }
 
 		c->req.sg[0].size = io->sg[0].size;
-		c->req.sg[0].addr = virt_to_bus(p);
+		c->req.sg[0].addr = pci_map_single(h->pci_dev, p, 
+			c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL); 
 		c->req.hdr.sg_cnt = 1;
 		break;
 	case IDA_WRITE:
@@ -1291,20 +1335,22 @@
 		if (!p) 
  		{ 
                         error = -ENOMEM; 
-                        cmd_free(NULL, c);
+                        cmd_free(h, c, 0);
                         return(error);
                 }
 		copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size);
 		c->req.sg[0].size = io->sg[0].size;
-		c->req.sg[0].addr = virt_to_bus(p);
+		c->req.sg[0].addr = pci_map_single(h->pci_dev, p, 
+			c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL); 
 		c->req.hdr.sg_cnt = 1;
 		break;
 	default:
 		c->req.sg[0].size = sizeof(io->c);
-		c->req.sg[0].addr = virt_to_bus(&io->c);
+		c->req.sg[0].addr = pci_map_single(h->pci_dev,&io->c, 
+			c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
 		c->req.hdr.sg_cnt = 1;
 	}
-
+	
 	/* Put the request on the tail of the request queue */
 	spin_lock_irqsave(&io_request_lock, flags);
 	addQ(&h->reqQ, c);
@@ -1316,9 +1362,15 @@
 	while(c->type != CMD_IOCTL_DONE)
 		schedule();
 
+	/* Unmap the DMA  */
+	pci_unmap_single(h->pci_dev, c->req.sg[0].addr, c->req.sg[0].size, 
+		PCI_DMA_BIDIRECTIONAL);
 	/* Post submit processing */
 	switch(io->cmd) {
 	case PASSTHRU_A:
+		pci_unmap_single(h->pci_dev, c->req.hdr.blk,
+                                sizeof(ida_ioctl_t),
+                                PCI_DMA_BIDIRECTIONAL);
 	case IDA_READ:
 	case DIAG_PASS_THRU:
 		copy_to_user((void*)io->sg[0].addr, p, io->sg[0].size);
@@ -1332,7 +1384,7 @@
 	}
 
 	io->rcode = c->req.hdr.rcode;
-	cmd_free(NULL, c);
+	cmd_free(h, c, 0);
 	return(0);
 }
 
@@ -1342,13 +1394,15 @@
  * critical (and can wait for kmalloc and possibly sleep) can pass in NULL
  * as the first argument to get a new command.
  */
-static cmdlist_t * cmd_alloc(ctlr_info_t *h)
+static cmdlist_t * cmd_alloc(ctlr_info_t *h, int get_from_pool)
 {
 	cmdlist_t * c;
 	int i;
+	dma_addr_t cmd_dhandle;
 
-	if (h == NULL) {
-		c = (cmdlist_t*)kmalloc(sizeof(cmdlist_t), GFP_KERNEL);
+	if (!get_from_pool) {
+		c = (cmdlist_t*)pci_alloc_consistent(h->pci_dev, 
+			sizeof(cmdlist_t), &cmd_dhandle);
 		if(c==NULL)
 			return NULL;
 	} else {
@@ -1358,20 +1412,22 @@
 				return NULL;
 		} while(test_and_set_bit(i%32, h->cmd_pool_bits+(i/32)) != 0);
 		c = h->cmd_pool + i;
+		cmd_dhandle = h->cmd_pool_dhandle + i*sizeof(cmdlist_t);
 		h->nr_allocs++;
 	}
 
 	memset(c, 0, sizeof(cmdlist_t));
-	c->busaddr = virt_to_bus(c);
+	c->busaddr = cmd_dhandle; 
 	return c;
 }
 
-static void cmd_free(ctlr_info_t *h, cmdlist_t *c)
+static void cmd_free(ctlr_info_t *h, cmdlist_t *c, int got_from_pool)
 {
 	int i;
 
-	if (h == NULL) {
-		kfree(c);
+	if (!got_from_pool) {
+		pci_free_consistent(h->pci_dev, sizeof(cmdlist_t), c,
+			c->busaddr);
 	} else {
 		i = c - h->cmd_pool;
 		clear_bit(i%32, h->cmd_pool_bits+(i/32));
@@ -1400,7 +1456,7 @@
 	unsigned long i;
 	ctlr_info_t *info_p = hba[ctlr];
 
-	c = cmd_alloc(info_p);
+	c = cmd_alloc(info_p, 1);
 	if(!c)
 		return IO_ERROR;
 	c->ctlr = ctlr;
@@ -1424,7 +1480,8 @@
 	c->req.hdr.blk = blk;
 	c->req.hdr.blk_cnt = blkcnt;
 	c->req.hdr.cmd = (unsigned char) cmd;
-	c->req.sg[0].addr = (__u32) virt_to_bus(buff);
+	c->req.sg[0].addr = (__u32) pci_map_single(info_p->pci_dev, 
+		buff, c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
 	/*
 	 * Disable interrupt
 	 */
@@ -1447,13 +1504,16 @@
 	 */
 	info_p->access.submit_command(info_p, c);
 	complete = pollcomplete(ctlr);
+	
+	pci_unmap_single(info_p->pci_dev, (dma_addr_t) c->req.sg[0].addr, 
+		c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
 	if (complete != 1) {
 		if (complete != c->busaddr) {
 			printk( KERN_WARNING
 			"cpqarray ida%d: idaSendPciCmd "
 		      "Invalid command list address returned! (%08lx)\n",
 				ctlr, (unsigned long)complete);
-			cmd_free(info_p, c);
+			cmd_free(info_p, c, 1);
 			return (IO_ERROR);
 		}
 	} else {
@@ -1461,7 +1521,7 @@
 			"cpqarray ida%d: idaSendPciCmd Timeout out, "
 			"No command list address returned!\n",
 			ctlr);
-		cmd_free(info_p, c);
+		cmd_free(info_p, c, 1);
 		return (IO_ERROR);
 	}
 
@@ -1473,11 +1533,11 @@
 				"cmd: 0x%x, return code = 0x%x\n",
 				ctlr, c->req.hdr.cmd, c->req.hdr.rcode);
 
-			cmd_free(info_p, c);
+			cmd_free(info_p, c, 1);
 			return (IO_ERROR);
 		}
 	}
-	cmd_free(info_p, c);
+	cmd_free(info_p, c, 1);
 	return (IO_OK);
 }
 
@@ -1574,13 +1634,9 @@
 	max_p = gdev->max_p;
 	start = target << gdev->minor_shift;
 
-	for(i=max_p; i>=0; i--) {
+	for(i=max_p-1; i>=0; i--) {
 		int minor = start+i;
-		kdev_t devi = MKDEV(MAJOR_NR + ctlr, minor);
-		struct super_block *sb = get_super(devi);
-		sync_dev(devi);
-		if (sb) invalidate_inodes(sb);
-		invalidate_buffers(devi);
+		invalidate_device(MKDEV(MAJOR_NR + ctlr, minor), 1);
 		gdev->part[minor].start_sect = 0;	
 		gdev->part[minor].nr_sects = 0;	
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)