public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* cpqarray patches for 2.6 [4 of 5]
@ 2004-03-16 16:46 mikem
  2004-03-16 17:17 ` Christoph Hellwig
  2004-03-16 17:37 ` Jeff Garzik
  0 siblings, 2 replies; 4+ messages in thread
From: mikem @ 2004-03-16 16:46 UTC (permalink / raw)
  To: axboe, akpm; +Cc: linux-kernel

This is patch 4 of 5 for cpqarray. Please apply in order.

Thanks,
mikem
-------------------------------------------------------------------------------
   - Change to use pci APIs (change from 2.4.18 to 2.4.19)
     PS: This also includes eisa detection fix during initialization
     which was missing from 2.4.19 but fixed in 2.4.25



 drivers/block/cpqarray.c |  542 +++++++++++++++++++++++++++++------------------
 1 files changed, 344 insertions(+), 198 deletions(-)

--- linux-2.6.1/drivers/block/cpqarray.c~cpqarray_pci_register	2004-02-11 18:01:15.521444648 -0600
+++ linux-2.6.1-root/drivers/block/cpqarray.c	2004-02-11 18:01:15.527443736 -0600
@@ -97,6 +97,34 @@ static struct board_type products[] = {
 	{ 0x40580E11, "Smart Array 431",	&smart4_access },
 };
 
+/* define the PCI info for the PCI cards this driver can control */
+const struct pci_device_id cpqarray_pci_device_id[] =
+{
+	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_COMPAQ_42XX,
+		0x0E11, 0x4058, 0, 0, 0},       /* SA431 */
+	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_COMPAQ_42XX,
+		0x0E11, 0x4051, 0, 0, 0},      /* SA4250ES */
+	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_COMPAQ_42XX,
+		0x0E11, 0x4050, 0, 0, 0},      /* SA4200 */
+	{ PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C1510,
+		0x0E11, 0x4048, 0, 0, 0},       /* LC2 */
+	{ PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C1510,
+		0x0E11, 0x4040, 0, 0, 0},      /* Integrated Array */
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_SMART2P,
+		0x0E11, 0x4034, 0, 0, 0},       /* SA 221 */
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_SMART2P,
+		0x0E11, 0x4033, 0, 0, 0},       /* SA 3100ES*/
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_SMART2P,
+		0x0E11, 0x4032, 0, 0, 0},       /* SA 3200*/
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_SMART2P,
+		0x0E11, 0x4031, 0, 0, 0},       /* SA 2SL*/
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_SMART2P,
+		0x0E11, 0x4030, 0, 0, 0},       /* SA 2P */
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, cpqarray_pci_device_id);
+
 static struct gendisk *ida_gendisk[MAX_CTLR][NWD];
 
 /* Debug... */
@@ -108,7 +136,7 @@ static struct gendisk *ida_gendisk[MAX_C
 /* Debug Extra Paranoid... */
 #define DBGPX(s) do { } while(0)
 
-static int cpqarray_pci_detect(void);
+int cpqarray_init_step2(void);
 static int cpqarray_pci_init(ctlr_info_t *c, struct pci_dev *pdev);
 static void *remap_pci_mem(ulong base, ulong size);
 static int cpqarray_eisa_detect(void);
@@ -119,6 +147,9 @@ static void start_fwbk(int ctlr);
 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 void free_hba(int i);
+static int alloc_cpqarray_hba(void);
+
 static int sendcmd(
 	__u8	cmd,
 	int	ctlr,
@@ -145,6 +176,7 @@ static irqreturn_t do_ida_intr(int irq, 
 static void ida_timer(unsigned long tdata);
 static int ida_revalidate(struct gendisk *disk);
 static int revalidate_allvol(ctlr_info_t *host);
+static int cpqarray_register_ctlr(int ctlr, struct pci_dev *pdev);
 
 #ifdef CONFIG_PROC_FS
 static void ida_procinit(int i);
@@ -281,150 +313,190 @@ static int ida_proc_get_info(char *buffe
 
 MODULE_PARM(eisa, "1-8i");
 
-static void __exit cpqarray_exit(void)
+/* This is a bit of a hack, 
+ * necessary to support both eisa and pci
+ */
+int __init cpqarray_init(void)
 {
-	int i, j;
-	char buff[4]; 
+	if(cpqarray_init_step2() == 0) 	/* all the block dev num already used */
+		return -ENODEV;		/* or no controllers were found */
+	return 0;
+}
 
-	for(i=0; i<nr_ctlr; i++) {
+static void release_io_mem(ctlr_info_t *c)
+{
+	/* if IO mem was not protected do nothing */
+	if( c->io_mem_addr == 0)
+		return;
+	release_region(c->io_mem_addr, c->io_mem_length);
+	c->io_mem_addr = 0;
+	c->io_mem_length = 0;
+}
 
-		/* sendcmd will turn off interrupt, and send the flush... 
-		 * To write all data in the battery backed cache to disks    
-		 * no data returned, but don't want to send NULL to sendcmd */	
-		if( sendcmd(FLUSH_CACHE, i, buff, 4, 0, 0, 0))
-		{
-			printk(KERN_WARNING "Unable to flush cache on "
-				"controller %d\n", i);	
-		}
-		free_irq(hba[i]->intr, hba[i]);
-		iounmap(hba[i]->vaddr);
-		unregister_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname);
-		del_timer(&hba[i]->timer);
-		remove_proc_entry(hba[i]->devname, proc_array);
-		pci_free_consistent(hba[i]->pci_dev, 
-			NR_CMDS * sizeof(cmdlist_t), (hba[i]->cmd_pool), 
+static void __devexit cpqarray_remove_one(int i)
+{
+	int j;
+	char buff[4];
+
+	/* sendcmd will turn off interrupt, and send the flush...
+	 * To write all data in the battery backed cache to disks
+	 * no data returned, but don't want to send NULL to sendcmd */
+	if( sendcmd(FLUSH_CACHE, i, buff, 4, 0, 0, 0))
+	{
+		printk(KERN_WARNING "Unable to flush cache on controller %d\n",
+				i);
+	}
+	free_irq(hba[i]->intr, hba[i]);
+	iounmap(hba[i]->vaddr);
+	unregister_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname);
+	del_timer(&hba[i]->timer);
+	remove_proc_entry(hba[i]->devname, proc_array);
+	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);
+	kfree(hba[i]->cmd_pool_bits);
+	for(j = 0; j < NWD; j++) {
+		if (ida_gendisk[i][j]->flags & GENHD_FL_UP)
+			del_gendisk(ida_gendisk[i][j]);
+		devfs_remove("ida/c%dd%d",i,j);
+		put_disk(ida_gendisk[i][j]);
+	}
+	blk_cleanup_queue(hba[i]->queue);
+	release_io_mem(hba[i]);
+	free_hba(i);
+}
 
-		for (j = 0; j < NWD; j++) {
-			if (ida_gendisk[i][j]->flags & GENHD_FL_UP)
-				del_gendisk(ida_gendisk[i][j]);
-			devfs_remove("ida/c%dd%d",i,j);
-			put_disk(ida_gendisk[i][j]);
-		}
-		blk_cleanup_queue(hba[i]->queue);
+static void __devexit cpqarray_remove_one_pci (struct pci_dev *pdev)
+{
+	int i;
+	ctlr_info_t *tmp_ptr;
+
+	if (pci_get_drvdata(pdev) == NULL) {
+		printk( KERN_ERR "cpqarray: Unable to remove device \n");
+		return;
 	}
-	devfs_remove("ida");
-	remove_proc_entry("cpqarray", proc_root_driver);
+
+	tmp_ptr = pci_get_drvdata(pdev);
+	i = tmp_ptr->ctlr;
+	if (hba[i] == NULL) {
+		printk(KERN_ERR "cpqarray: controller %d appears to have"
+			"already been removed \n", i);
+		return;
+        }
+	pci_set_drvdata(pdev, NULL);
+
+	cpqarray_remove_one(i);
 }
 
-/*
- *  This is it.  Find all the controllers and register them.  I really hate
- *  stealing all these major device numbers.
- *  returns the number of block devices registered.
+/* removing an instance that was not removed automatically..
+ * must be an eisa card.
  */
-static int __init cpqarray_init(void)
+static void __devexit cpqarray_remove_one_eisa (int i)
 {
-	request_queue_t *q;
-	int i,j;
-	int num_cntlrs_reg = 0;
-	/* detect controllers */
-	cpqarray_pci_detect();
-	cpqarray_eisa_detect();
-	
-	if (nr_ctlr == 0)
-		return -ENODEV;
+	if (hba[i] == NULL) {
+		printk(KERN_ERR "cpqarray: controller %d appears to have"
+			"already been removed \n", i);
+		return;
+        }
+	cpqarray_remove_one(i);
+}
 
-	printk(DRIVER_NAME "\n");
-	printk("Found %d controller(s)\n", nr_ctlr);
+/* pdev is NULL for eisa */
+static int cpqarray_register_ctlr( int i, struct pci_dev *pdev)
+{
+	request_queue_t *q;
+	int j;
 
-	/* allocate space for disk structs */
 	/* 
 	 * register block devices
 	 * Find disks and fill in structs
 	 * Get an interrupt, set the Q depth and get into /proc
 	 */
-	for(i=0; i < nr_ctlr; i++) {
-	  	/* If this successful it should insure that we are the only */
-		/* instance of the driver */	
-		if (register_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname))
-                        continue;
-
-		hba[i]->access.set_intr_mask(hba[i], 0);
-		if (request_irq(hba[i]->intr, do_ida_intr,
-			SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i])) {
-
-			printk(KERN_ERR "cpqarray: Unable to get irq %d for %s\n", 
+  	
+	/* If this successful it should insure that we are the only */
+	/* instance of the driver */	
+	if (register_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname)) {
+		goto Enomem4;
+	}
+	hba[i]->access.set_intr_mask(hba[i], 0);
+	if (request_irq(hba[i]->intr, do_ida_intr,
+		SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i]))
+	{
+		printk(KERN_ERR "cpqarray: Unable to get irq %d for %s\n", 
 				hba[i]->intr, hba[i]->devname);
-			unregister_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname);
-			continue;
-		}
-		num_cntlrs_reg++;
-		for (j=0; j<NWD; j++) {
-			ida_gendisk[i][j] = alloc_disk(1 << NWD_SHIFT);
-			if (!ida_gendisk[i][j])
-				goto Enomem2;
-		}
-		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 = kmalloc(((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long), GFP_KERNEL);
+		goto Enomem3;
+	}
 		
-		if (!hba[i]->cmd_pool_bits || !hba[i]->cmd_pool)
-			goto Enomem1;
-		memset(hba[i]->cmd_pool, 0, NR_CMDS * sizeof(cmdlist_t));
-		memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long));
-		printk(KERN_INFO "cpqarray: Finding drives on %s", 
-			hba[i]->devname);
-
-		spin_lock_init(&hba[i]->lock);
-		q = blk_init_queue(do_ida_request, &hba[i]->lock);
-		if (!q)
+	for (j=0; j<NWD; j++) {
+		ida_gendisk[i][j] = alloc_disk(1 << NWD_SHIFT);
+		if (!ida_gendisk[i][j])
+			goto Enomem2;
+	}
+
+	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 = kmalloc(
+		((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long),
+		GFP_KERNEL);
+		
+	if (!hba[i]->cmd_pool_bits || !hba[i]->cmd_pool)
 			goto Enomem1;
 
-		hba[i]->queue = q;
-		q->queuedata = hba[i];
+	memset(hba[i]->cmd_pool, 0, NR_CMDS * sizeof(cmdlist_t));
+	memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long));
+	printk(KERN_INFO "cpqarray: Finding drives on %s", 
+		hba[i]->devname);
+
+	spin_lock_init(&hba[i]->lock);
+	q = blk_init_queue(do_ida_request, &hba[i]->lock);
+	if (!q)
+		goto Enomem1;
 
-		getgeometry(i);
-		start_fwbk(i); 
+	hba[i]->queue = q;
+	q->queuedata = hba[i];
 
-		ida_procinit(i);
+	getgeometry(i);
+	start_fwbk(i); 
 
+	ida_procinit(i);
+
+	if (pdev)
 		blk_queue_bounce_limit(q, hba[i]->pci_dev->dma_mask);
 
-		/* This is a hardware imposed limit. */
-		blk_queue_max_hw_segments(q, SG_MAX);
+	/* This is a hardware imposed limit. */
+	blk_queue_max_hw_segments(q, SG_MAX);
 
-		/* This is a driver limit and could be eliminated. */
-		blk_queue_max_phys_segments(q, SG_MAX);
+	/* This is a driver limit and could be eliminated. */
+	blk_queue_max_phys_segments(q, SG_MAX);
 	
-		init_timer(&hba[i]->timer);
-		hba[i]->timer.expires = jiffies + IDA_TIMER;
-		hba[i]->timer.data = (unsigned long)hba[i];
-		hba[i]->timer.function = ida_timer;
-		add_timer(&hba[i]->timer);
-
-		/* Enable IRQ now that spinlock and rate limit timer are set up */
-		hba[i]->access.set_intr_mask(hba[i], FIFO_NOT_EMPTY);
-
-		for(j=0; j<NWD; j++) {
-			struct gendisk *disk = ida_gendisk[i][j];
-			drv_info_t *drv = &hba[i]->drv[j];
-			sprintf(disk->disk_name, "ida/c%dd%d", i, j);
-			disk->major = COMPAQ_SMART2_MAJOR + i;
-			disk->first_minor = j<<NWD_SHIFT;
-			disk->fops = &ida_fops; 
-			if (j && !drv->nr_blks)
-				continue;
-			blk_queue_hardsect_size(hba[i]->queue, drv->blk_size);
-			set_capacity(disk, drv->nr_blks);
-			disk->queue = hba[i]->queue;
-			disk->private_data = drv;
-			add_disk(disk);
-		}
+	init_timer(&hba[i]->timer);
+	hba[i]->timer.expires = jiffies + IDA_TIMER;
+	hba[i]->timer.data = (unsigned long)hba[i];
+	hba[i]->timer.function = ida_timer;
+	add_timer(&hba[i]->timer);
+
+	/* Enable IRQ now that spinlock and rate limit timer are set up */
+	hba[i]->access.set_intr_mask(hba[i], FIFO_NOT_EMPTY);
+
+	for(j=0; j<NWD; j++) {
+		struct gendisk *disk = ida_gendisk[i][j];
+		drv_info_t *drv = &hba[i]->drv[j];
+		sprintf(disk->disk_name, "ida/c%dd%d", i, j);
+		disk->major = COMPAQ_SMART2_MAJOR + i;
+		disk->first_minor = j<<NWD_SHIFT;
+		disk->fops = &ida_fops; 
+		if (j && !drv->nr_blks)
+			continue;
+		blk_queue_hardsect_size(hba[i]->queue, drv->blk_size);
+		set_capacity(disk, drv->nr_blks);
+		disk->queue = hba[i]->queue;
+		disk->private_data = drv;
+		add_disk(disk);
 	}
+	
 	/* done ! */
-	return num_cntlrs_reg ? 0 : -ENODEV;
+	return(i);
 
 Enomem1:
 	nr_ctlr = i; 
@@ -438,83 +510,102 @@ Enomem2:
 		ida_gendisk[i][j] = NULL;
 	}
 	free_irq(hba[i]->intr, hba[i]);
+Enomem3:
 	unregister_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname);
-	num_cntlrs_reg--;
+Enomem4:
+	if (pdev)	
+		pci_set_drvdata(pdev, NULL);
+	release_io_mem(hba[i]);
+	free_hba(i);
+
 	printk( KERN_ERR "cpqarray: out of memory");
 
-	if (!num_cntlrs_reg) {
-		remove_proc_entry("cpqarray", proc_root_driver);
-		return -ENODEV;
+	return -1;
+}
+
+static int __init cpqarray_init_one( struct pci_dev *pdev,
+	const struct pci_device_id *ent)
+{
+	int i;
+
+	printk(KERN_DEBUG "cpqarray: Device 0x%x has been found at"
+			" bus %d dev %d func %d\n",
+			pdev->device, pdev->bus->number, PCI_SLOT(pdev->devfn),
+			PCI_FUNC(pdev->devfn));
+	i = alloc_cpqarray_hba();
+	if( i < 0 )
+		return (-1);
+	memset(hba[i], 0, sizeof(ctlr_info_t));
+	sprintf(hba[i]->devname, "ida%d", i);
+	hba[i]->ctlr = i;
+	/* Initialize the pdev driver private data */
+	pci_set_drvdata(pdev, hba[i]);
+
+	if (cpqarray_pci_init(hba[i], pdev) != 0) {
+		pci_set_drvdata(pdev, NULL);
+		release_io_mem(hba[i]);
+		free_hba(i);
+		return -1;
 	}
-	return 0;
+
+	return (cpqarray_register_ctlr(i, pdev));
 }
 
+static struct pci_driver cpqarray_pci_driver = {
+	name:   "cpqarray",
+	probe:  cpqarray_init_one,
+	remove:  __devexit_p(cpqarray_remove_one_pci),
+	id_table:  cpqarray_pci_device_id,
+};
+
 /*
- * Find the controller and initialize it
- *  Cannot use the class code to search, because older array controllers use
- *    0x018000 and new ones use 0x010400.  So I might as well search for each
- *    each device IDs, being there are only going to be three of them. 
- */
-static int cpqarray_pci_detect(void)
-{
-	struct pci_dev *pdev;
-
-#define IDA_BOARD_TYPES 3
-	static int ida_vendor_id[IDA_BOARD_TYPES] = { PCI_VENDOR_ID_DEC, 
-		PCI_VENDOR_ID_NCR, PCI_VENDOR_ID_COMPAQ };
-	static int ida_device_id[IDA_BOARD_TYPES] = { PCI_DEVICE_ID_COMPAQ_42XX,		PCI_DEVICE_ID_NCR_53C1510, PCI_DEVICE_ID_COMPAQ_SMART2P };
-	int brdtype;
+ *  This is it.  Find all the controllers and register them.  I really hate
+ *  stealing all these major device numbers.
+ *  returns the number of block devices registered.
+ */
+int __init cpqarray_init_step2(void)
+{
+	int num_cntlrs_reg = 0;
+	int i;
+
+	/* detect controllers */
+	printk(DRIVER_NAME "\n");
+	pci_register_driver(&cpqarray_pci_driver);
+	cpqarray_eisa_detect();
 	
-	/* search for all PCI board types that could be for this driver */
-	for(brdtype=0; brdtype<IDA_BOARD_TYPES; brdtype++)
-	{
-		pdev = pci_find_device(ida_vendor_id[brdtype],
-				       ida_device_id[brdtype], NULL);
-		while (pdev) {
-			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, 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");
-				break;
-			}
-			
-/* if it is a PCI_DEVICE_ID_NCR_53C1510, make sure it's 				the Compaq version of the chip */ 
+	for (i=0; i < MAX_CTLR; i++) {
+		if (hba[i] != NULL)
+			num_cntlrs_reg++;
+	}
 
-			if (ida_device_id[brdtype] == PCI_DEVICE_ID_NCR_53C1510)			{	
-				unsigned short subvendor=pdev->subsystem_vendor;
-				if(subvendor !=  PCI_VENDOR_ID_COMPAQ)
-				{
-					printk(KERN_DEBUG 
-						"cpqarray: not a Compaq integrated array controller\n");
-					continue;
-				}
-			}
+	return(num_cntlrs_reg);
+}
 
-			hba[nr_ctlr] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);			if(hba[nr_ctlr]==NULL)
-			{
+/* Function to find the first free pointer into our hba[] array */
+/* Returns -1 if no free entries are left.  */
+static int alloc_cpqarray_hba(void)
+{
+	int i;
+
+	for(i=0; i< MAX_CTLR; i++) {
+		if (hba[i] == NULL) {
+			hba[i] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
+			if(hba[i]==NULL) {
 				printk(KERN_ERR "cpqarray: out of memory.\n");
-				continue;
-			}
-			memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));
-			if (cpqarray_pci_init(hba[nr_ctlr], pdev) != 0)
-			{
-				kfree(hba[nr_ctlr]);
-				continue;
+				return (-1);
 			}
-			sprintf(hba[nr_ctlr]->devname, "ida%d", nr_ctlr);
-			hba[nr_ctlr]->ctlr = nr_ctlr;
-			nr_ctlr++;
-
-			pdev = pci_find_device(ida_vendor_id[brdtype],
-					       ida_device_id[brdtype], pdev);
+			return (i);
 		}
 	}
+	printk(KERN_WARNING "cpqarray: This driver supports a maximum"
+		" of 8 controllers.\n");
+	return(-1);
+}
 
-	return nr_ctlr;
+static void free_hba(int i)
+{
+	kfree(hba[i]);
+	hba[i]=NULL;
 }
 
 /*
@@ -555,6 +646,13 @@ static int cpqarray_pci_init(ctlr_info_t
 	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_timer);
 
 	pci_read_config_dword(pdev, 0x2c, &board_id);
+	
+	/* check to see if controller has been disabled */
+	if(!(command & 0x02)) {
+		printk(KERN_WARNING 
+			"cpqarray: controller appears to be disabled\n");
+		return(-1);
+	}
 
 DBGINFO(
 	printk("vendor_id = %x\n", vendor_id);
@@ -570,11 +668,28 @@ DBGINFO(
 );
 
 	c->intr = irq;
-	c->io_mem_addr = addr[0];
+
+	for(i=0; i<6; i++) {
+		if (pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE_IO)
+		{ /* IO space */
+			c->io_mem_addr = addr[i];
+			c->io_mem_length = pci_resource_end(pdev, i)
+				- pci_resource_start(pdev, i) + 1;
+			if(!request_region( c->io_mem_addr, c->io_mem_length,
+				"cpqarray"))
+			{
+				printk( KERN_WARNING "cpqarray I/O memory range already in use addr %lx length = %ld\n", c->io_mem_addr, c->io_mem_length);
+				c->io_mem_addr = 0;
+				c->io_mem_length = 0;
+			}
+			break;
+		}
+	}
 
 	c->paddr = 0;
 	for(i=0; i<6; i++)
-		if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) {
+		if (!(pci_resource_flags(pdev, i) &
+				PCI_BASE_ADDRESS_SPACE_IO)) {
 			c->paddr = pci_resource_start (pdev, i);
 			break;
 		}
@@ -654,13 +769,13 @@ static int cpqarray_eisa_detect(void)
 	int i=0, j;
 	__u32 board_id;
 	int intr;
+	int ctlr;
+	int num_ctlr = 0;
 
 	while(i<8 && eisa[i]) {
-		if (nr_ctlr == 8) {
-			printk(KERN_WARNING "cpqarray: This driver supports"
-				" a maximum of 8 controllers.\n");
+		ctlr = alloc_cpqarray_hba();
+		if(ctlr == -1)
 			break;
-		}
 		board_id = inl(eisa[i]+0xC80);
 		for(j=0; j < NR_PRODUCTS; j++)
 			if (board_id == products[j].board_id) 
@@ -671,14 +786,21 @@ static int cpqarray_eisa_detect(void)
 				" to access the SMART Array controller %08lx\n",				 (unsigned long)board_id);
 			continue;
 		}
-		hba[nr_ctlr] = (ctlr_info_t *) kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
-		if(hba[nr_ctlr]==NULL)
+		
+		memset(hba[ctlr], 0, sizeof(ctlr_info_t));
+		hba[ctlr]->io_mem_addr = eisa[i];
+		hba[ctlr]->io_mem_length = 0x7FF;
+		if(!request_region(hba[ctlr]->io_mem_addr,
+				hba[ctlr]->io_mem_length,
+				"cpqarray"))
 		{
-			printk(KERN_ERR "cpqarray: out of memory.\n");
+			printk(KERN_WARNING "cpqarray: I/O range already in "
+					"use addr = %lx length = %ld\n",
+					hba[ctlr]->io_mem_addr,
+					hba[ctlr]->io_mem_length);
+			free_hba(ctlr);
 			continue;
 		}
-		memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));
-		hba[nr_ctlr]->io_mem_addr = eisa[i];
 
 		/*
 		 * Read the config register to find our interrupt
@@ -689,13 +811,13 @@ static int cpqarray_eisa_detect(void)
 		else if (intr & 4) intr = 14;
 		else if (intr & 8) intr = 15;
 		
-		hba[nr_ctlr]->intr = intr;
-		sprintf(hba[nr_ctlr]->devname, "ida%d", nr_ctlr);
-		hba[nr_ctlr]->product_name = products[j].product_name;
-		hba[nr_ctlr]->access = *(products[j].access);
-		hba[nr_ctlr]->ctlr = nr_ctlr;
-		hba[nr_ctlr]->board_id = board_id;
-		hba[nr_ctlr]->pci_dev = NULL; /* not PCI */
+		hba[ctlr]->intr = intr;
+		sprintf(hba[ctlr]->devname, "ida%d", nr_ctlr);
+		hba[ctlr]->product_name = products[j].product_name;
+		hba[ctlr]->access = *(products[j].access);
+		hba[ctlr]->ctlr = ctlr;
+		hba[ctlr]->board_id = board_id;
+		hba[ctlr]->pci_dev = NULL; /* not PCI */
 
 DBGINFO(
 	printk("i = %d, j = %d\n", i, j);
@@ -704,14 +826,19 @@ DBGINFO(
 	printk("board_id = %x\n", board_id);
 );
 
-		nr_ctlr++;
+		num_ctlr++;
 		i++;
+
+		if (cpqarray_register_ctlr(ctlr, NULL) == -1)
+			printk(KERN_WARNING
+				"cpqarray: Can't register EISA controller %d\n",
+				ctlr);
+		
 	}
 
-	return nr_ctlr;
+	return num_ctlr;
 }
 
-
 /*
  * Open.  Make sure the device is really there.
  */
@@ -1721,5 +1848,24 @@ static void getgeometry(int ctlr)
 
 }
 
+static void __exit cpqarray_exit(void)
+{
+	int i;
+
+	pci_unregister_driver(&cpqarray_pci_driver);
+
+	/* Double check that all controller entries have been removed */
+	for(i=0; i<MAX_CTLR; i++) {
+		if (hba[i] != NULL) {
+			printk(KERN_WARNING "cpqarray: Removing EISA "
+					"controller %d\n", i);
+			cpqarray_remove_one_eisa(i);
+		}
+	}
+
+	devfs_remove("ida");
+	remove_proc_entry("cpqarray", proc_root_driver);
+}
+
 module_init(cpqarray_init)
 module_exit(cpqarray_exit)

_

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: cpqarray patches for 2.6 [4 of 5]
  2004-03-16 16:46 cpqarray patches for 2.6 [4 of 5] mikem
@ 2004-03-16 17:17 ` Christoph Hellwig
  2004-03-16 17:37 ` Jeff Garzik
  1 sibling, 0 replies; 4+ messages in thread
From: Christoph Hellwig @ 2004-03-16 17:17 UTC (permalink / raw)
  To: mike.miller; +Cc: axboe, akpm, linux-kernel

On Tue, Mar 16, 2004 at 10:46:42AM -0600, mikem@beardog.cca.cpqcorp.net wrote:
> +int cpqarray_init_step2(void);

Why is this non-static?

>  static int cpqarray_pci_init(ctlr_info_t *c, struct pci_dev *pdev);
>  static void *remap_pci_mem(ulong base, ulong size);
>  static int cpqarray_eisa_detect(void);
> @@ -119,6 +147,9 @@ static void start_fwbk(int ctlr);
>  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 void free_hba(int i);

Argg.  Not holding back this patch, but could you please fix cpqarray
to pass around objects instead of indices?  That's how 90% of the drivers
work, it makes the code more redable and removes global arrays that limit
the max number of devices supported.

> +/* This is a bit of a hack, 
> + * necessary to support both eisa and pci
> + */
> +int __init cpqarray_init(void)
>  {
> -	int i, j;
> -	char buff[4]; 
> +	if(cpqarray_init_step2() == 0) 	/* all the block dev num already used */
> +		return -ENODEV;		/* or no controllers were found */
> +	return 0;
> +}

Why can't cpqarray_init_step2 be inlined in cpqarray_init directly?
Why is cpqarray_init non-static?
And what's the issue with EISA and PCI?  If you converted the driver
to the proper device-model based EISA probing API supporting both should
be really easy.

> +	del_timer(&hba[i]->timer);

You probably want a del_timer_sync here.

> +		if (ida_gendisk[i][j]->flags & GENHD_FL_UP)
> +			del_gendisk(ida_gendisk[i][j]);

How can the gendisk be non up?

> +	if (pci_get_drvdata(pdev) == NULL) {
> +		printk( KERN_ERR "cpqarray: Unable to remove device \n");
> +		return;
>  	}

Rather silly check.  if pci_get_drvdata(pdev) returns NULL the pci code
would be really badly hosed in which case a panic because of a NULL pointer
dereference is probably the best thing to keep the box from corrupting even
more data.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: cpqarray patches for 2.6 [4 of 5]
  2004-03-16 16:46 cpqarray patches for 2.6 [4 of 5] mikem
  2004-03-16 17:17 ` Christoph Hellwig
@ 2004-03-16 17:37 ` Jeff Garzik
  2004-03-16 19:23   ` Jeff Garzik
  1 sibling, 1 reply; 4+ messages in thread
From: Jeff Garzik @ 2004-03-16 17:37 UTC (permalink / raw)
  To: mike.miller; +Cc: axboe, akpm, linux-kernel

mikem@beardog.cca.cpqcorp.net wrote:
> This is patch 4 of 5 for cpqarray. Please apply in order.
> 
> Thanks,
> mikem
> -------------------------------------------------------------------------------
>    - Change to use pci APIs (change from 2.4.18 to 2.4.19)
>      PS: This also includes eisa detection fix during initialization
>      which was missing from 2.4.19 but fixed in 2.4.25


While I like this patch a lot, there is one tiny bug I spotted, and one 
question:


> +	/* sendcmd will turn off interrupt, and send the flush...
> +	 * To write all data in the battery backed cache to disks
> +	 * no data returned, but don't want to send NULL to sendcmd */
> +	if( sendcmd(FLUSH_CACHE, i, buff, 4, 0, 0, 0))
> +	{
> +		printk(KERN_WARNING "Unable to flush cache on controller %d\n",
> +				i);
> +	}
> +	free_irq(hba[i]->intr, hba[i]);
> +	iounmap(hba[i]->vaddr);
> +	unregister_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname);
> +	del_timer(&hba[i]->timer);

should this be del_timer_sync()?


> +	remove_proc_entry(hba[i]->devname, proc_array);
> +	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);
> +	kfree(hba[i]->cmd_pool_bits);
> +	for(j = 0; j < NWD; j++) {
> +		if (ida_gendisk[i][j]->flags & GENHD_FL_UP)
> +			del_gendisk(ida_gendisk[i][j]);
> +		devfs_remove("ida/c%dd%d",i,j);
> +		put_disk(ida_gendisk[i][j]);
> +	}
> +	blk_cleanup_queue(hba[i]->queue);
> +	release_io_mem(hba[i]);
> +	free_hba(i);
> +}
>  

> +	hba[i]->access.set_intr_mask(hba[i], 0);
> +	if (request_irq(hba[i]->intr, do_ida_intr,
> +		SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i]))
> +	{
> +		printk(KERN_ERR "cpqarray: Unable to get irq %d for %s\n", 
>  				hba[i]->intr, hba[i]->devname);

Even though this line of code existed in the driver prior to your patch, 
  this highlights a bug:  SA_SHIRQ should really only be passed to 
request_irq() when the device is a PCI device.  If it's an EISA device, 
that really shouldn't be present.

I am also curious why SA_INTERRUPT is needed.  EISA requirement?

This patch gets my ACK otherwise...  I'm glad somebody did this.

	Jeff




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: cpqarray patches for 2.6 [4 of 5]
  2004-03-16 17:37 ` Jeff Garzik
@ 2004-03-16 19:23   ` Jeff Garzik
  0 siblings, 0 replies; 4+ messages in thread
From: Jeff Garzik @ 2004-03-16 19:23 UTC (permalink / raw)
  To: mike.miller; +Cc: axboe, akpm, linux-kernel

Thanks to Andrew for forwarding, patches #1 and #2 look OK, too.



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2004-03-16 19:32 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-03-16 16:46 cpqarray patches for 2.6 [4 of 5] mikem
2004-03-16 17:17 ` Christoph Hellwig
2004-03-16 17:37 ` Jeff Garzik
2004-03-16 19:23   ` Jeff Garzik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox