http://drm.bkbits.net/drm-2.6
airlied@starflyer.(none)|ChangeSet|20040706112025|54519 airlied

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/07/13 12:37:40-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-drm
# 
# drivers/char/drm/drm_drv.h
#   2004/07/13 12:37:37-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/07/06 21:20:25+10:00 airlied@starflyer.(none) 
#   changes for better hotplug and proper PCI device support from Jon Smirl and
#   Dave Airlie, along with a big fix from Paul Mackerras.
#   
#   Note: these are complex due to the need for the DRM to fallback if the 
#   framebuffer driver has already taken the device.
#   
#   These changes have been in the DRM CVS tree for about 3 months, style
#   comments are appreciated...
# 
# drivers/char/drm/drm_stub.h
#   2004/07/06 21:20:12+10:00 airlied@starflyer.(none) +19 -27
#   changes for better hotplug and proper PCI device support from Jon Smirl and
#   Dave Airlie, along with a big fix from Paul Mackerras.
#   
#   Note: these are complex due to the need for the DRM to fallback if the 
#   framebuffer driver has already taken the device.
#   
#   These changes have been in the DRM CVS tree for about 3 months, style
#   comments are appreciated...
# 
# drivers/char/drm/drm_drv.h
#   2004/07/06 21:20:12+10:00 airlied@starflyer.(none) +128 -56
#   changes for better hotplug and proper PCI device support from Jon Smirl and
#   Dave Airlie, along with a big fix from Paul Mackerras.
#   
#   Note: these are complex due to the need for the DRM to fallback if the 
#   framebuffer driver has already taken the device.
#   
#   These changes have been in the DRM CVS tree for about 3 months, style
#   comments are appreciated...
# 
# ChangeSet
#   2004/07/01 01:35:05-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-drm
# 
# drivers/char/drm/i830_dma.c
#   2004/07/01 01:35:01-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/05 16:54:02-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-drm
# 
# ChangeSet
#   2004/06/05 12:36:01-07:00 akpm@bix.(none) 
#   Merge http://drm.bkbits.net/drm-2.6 into bix.(none):/usr/src/bk-drm
# 
# drivers/char/drm/drm_agpsupport.h
#   2004/06/05 16:53:58-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/char/drm/drm_agpsupport.h
#   2004/06/05 12:35:58-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/26 18:15:47-07:00 akpm@bix.(none) 
#   Merge http://drm.bkbits.net/drm-2.6 into bix.(none):/usr/src/bk-drm
# 
# drivers/char/drm/i830_irq.c
#   2004/04/26 18:15:44-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/char/drm/i830_dma.c
#   2004/04/26 18:15:44-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/char/drm/i810_dma.c
#   2004/04/26 18:15:44-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/21 21:56:23-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-drm
# 
# drivers/char/drm/i810_dma.c
#   2004/04/21 21:56:20-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/12 20:53:29-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-drm
# 
# drivers/char/drm/i830_irq.c
#   2004/04/12 20:53:26-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/char/drm/i830_dma.c
#   2004/04/12 20:53:26-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/char/drm/i810_dma.c
#   2004/04/12 20:53:26-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
diff -Nru a/drivers/char/drm/drm_drv.h b/drivers/char/drm/drm_drv.h
--- a/drivers/char/drm/drm_drv.h	2004-07-13 12:38:43 -07:00
+++ b/drivers/char/drm/drm_drv.h	2004-07-13 12:38:43 -07:00
@@ -103,10 +103,10 @@
 #endif
 
 #ifndef DRIVER_PREINIT
-#define DRIVER_PREINIT()
+#define DRIVER_PREINIT() 0
 #endif
 #ifndef DRIVER_POSTINIT
-#define DRIVER_POSTINIT()
+#define DRIVER_POSTINIT() 0
 #endif
 #ifndef DRIVER_PRERELEASE
 #define DRIVER_PRERELEASE()
@@ -144,6 +144,17 @@
 }
 #endif
 
+static void __exit drm_cleanup( drm_device_t *dev );
+
+/** Stub information */
+struct drm_stub_info {
+	int (*info_register)(const char *name, struct file_operations *fops,
+			     drm_device_t *dev);
+	int (*info_unregister)(int minor);
+	struct class_simple *drm_class;
+};
+extern struct drm_stub_info DRM(stub_info);
+
 #ifndef MODULE
 /** Use an additional macro to avoid preprocessor troubles */
 #define DRM_OPTIONS_FUNC DRM(options)
@@ -163,8 +174,9 @@
 #endif
 
 #define MAX_DEVICES 4
-static drm_device_t	DRM(device)[MAX_DEVICES];
-static int		DRM(numdevs) = 0;
+drm_device_t            DRM(device)[MAX_DEVICES];
+int DRM(numdevs) = 0;
+int DRM(fb_loaded) = 0;
 
 DRIVER_FOPS;
 
@@ -546,30 +558,19 @@
 	DRM(PCI_IDS)
 };
 
-static int DRM(probe)(struct pci_dev *pdev)
+static int drm_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	drm_device_t *dev;
-#if __HAVE_CTX_BITMAP
 	int retcode;
-#endif
-	int i;
-	int is_compat = 0;
 
 	DRM_DEBUG( "\n" );
 
-	for (i = 0; DRM(pciidlist)[i].vendor != 0; i++) {
-		if ((DRM(pciidlist)[i].vendor == pdev->vendor) &&
-		    (DRM(pciidlist)[i].device == pdev->device)) {
-			is_compat = 1;
-		}
-	}
-	if (is_compat == 0)
-		return -ENODEV;
-
 	if (DRM(numdevs) >= MAX_DEVICES)
 		return -ENODEV;
 
 	dev = &(DRM(device)[DRM(numdevs)]);
+	if (DRM(fb_loaded)==0)
+		pci_set_drvdata(pdev, dev);
 
 	memset( (void *)dev, 0, sizeof(*dev) );
 	dev->count_lock = SPIN_LOCK_UNLOCKED;
@@ -578,11 +579,16 @@
 	sema_init( &dev->ctxlist_sem, 1 );
 
 	if ((dev->minor = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
-		return -EPERM;
+	{
+		retcode = -EPERM;
+		goto error_out;
+	}
+			
 	dev->device = MKDEV(DRM_MAJOR, dev->minor );
 	dev->name   = DRIVER_NAME;
 
 	dev->pdev   = pdev;
+	pci_enable_device(pdev);
 #ifdef __alpha__
 	dev->hose   = pdev->sysdata;
 	dev->pci_domain = dev->hose->bus->number;
@@ -594,16 +600,16 @@
 	dev->pci_func = PCI_FUNC(pdev->devfn);
 	dev->irq = pdev->irq;
 
-	DRIVER_PREINIT();
+	if ((retcode = DRIVER_PREINIT()))
+	  goto error_out_unreg;
 
 #if __REALLY_HAVE_AGP
 	dev->agp = DRM(agp_init)();
 #if __MUST_HAVE_AGP
 	if ( dev->agp == NULL ) {
 		DRM_ERROR( "Cannot initialize the agpgart module.\n" );
-		DRM(stub_unregister)(dev->minor);
-		DRM(takedown)( dev );
-		return -EINVAL;
+		retcode = -EINVAL;
+		goto error_out_unreg;
 	}
 #endif
 #if __REALLY_HAVE_MTRR
@@ -619,13 +625,11 @@
 	retcode = DRM(ctxbitmap_init)( dev );
 	if( retcode ) {
 		DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
-		DRM(stub_unregister)(dev->minor);
-		DRM(takedown)( dev );
-		return retcode;
+		goto error_out_unreg;
  	}
 #endif
 	DRM(numdevs)++; /* no errors, mark it reserved */
-	
+
 	DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
 		DRIVER_NAME,
 		DRIVER_MAJOR,
@@ -633,13 +637,43 @@
 		DRIVER_PATCHLEVEL,
 		DRIVER_DATE,
 		dev->minor,
-		pci_pretty_name(pdev));
+		pci_pretty_name(pdev)
+		);
 
-	DRIVER_POSTINIT();
+	if ((retcode = DRIVER_POSTINIT()))
+		goto error_out_unreg;
+
+
+	/*
+	 * don't move this earlier, for upcoming hotplugging support
+	 */
+	class_simple_device_add(DRM(stub_info).drm_class, 
+					MKDEV(DRM_MAJOR, dev->minor), &pdev->dev, "card%d", dev->minor);
 
 	return 0;
+
+ error_out_unreg:
+	DRM(stub_unregister)(dev->minor);
+	DRM(takedown)(dev);
+ error_out:
+	return retcode;
+}
+
+static void __exit drm_cleanup_pci(struct pci_dev *pdev)
+{
+	drm_device_t *dev = pci_get_drvdata(pdev);
+
+	pci_set_drvdata(pdev, NULL);
+	drm_cleanup(dev);
 }
 
+static struct pci_driver drm_driver = {
+	.name          = DRIVER_NAME,
+	.id_table      = DRM(pciidlist),
+	.probe         = drm_probe,
+	.remove        = __devexit_p(drm_cleanup_pci),
+};
+
 /**
  * Module initialization. Called via init_module at module load time, or via
  * linux/init/main.c (this is not currently supported).
@@ -656,7 +690,9 @@
 static int __init drm_init( void )
 {
 	struct pci_dev *pdev = NULL;
-
+	struct pci_driver *pdriver = NULL;
+	int i;
+	
 	DRM_DEBUG( "\n" );
 
 #ifdef MODULE
@@ -664,10 +700,26 @@
 #endif
 
 	DRM(mem_init)();
-
-	while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
-		DRM(probe)(pdev);
+	
+	for (i=0; DRM(pciidlist)[i].vendor != 0; i++) {
+		pdev = pci_get_subsys(DRM(pciidlist[i]).vendor, DRM(pciidlist[i]).device, DRM(pciidlist[i]).subvendor, DRM(pciidlist[i]).subdevice, NULL);
+		if (pdev)
+		{
+			pdriver = pci_dev_driver(pdev);
+			if (pdriver)
+			{
+				DRM(fb_loaded)=1;
+				drm_probe(pdev, &DRM(pciidlist[i]));
+			}
+			else
+				pci_dev_put(pdev);
+		}
 	}
+	
+	if (DRM(fb_loaded)==0)
+		pci_register_driver(&drm_driver);
+	else
+		DRM_INFO("Used old pci detect: framebuffer loaded\n");
 	return 0;
 }
 
@@ -678,23 +730,25 @@
  * 
  * \sa drm_init().
  */
-static void __exit drm_cleanup( void )
+static void __exit drm_cleanup( drm_device_t *dev )
 {
-	drm_device_t *dev;
-	int i;
-
 	DRM_DEBUG( "\n" );
+	if (!dev) {
+		DRM_ERROR("cleanup called no dev\n");
+		return;
+	}
 
-	for (i = DRM(numdevs) - 1; i >= 0; i--) {
-		dev = &(DRM(device)[i]);
-		if ( DRM(stub_unregister)(dev->minor) ) {
-			DRM_ERROR( "Cannot unload module\n" );
-		} else {
-			DRM_DEBUG("minor %d unregistered\n", dev->minor);
-			if (i == 0) {
-				DRM_INFO( "Module unloaded\n" );
-			}
-		}
+	DRM(takedown)(dev);
+
+	if (DRM(fb_loaded)==0)
+		pci_disable_device(dev->pdev);
+
+	if ( DRM(stub_unregister)(dev->minor) ) {
+		DRM_ERROR( "Cannot unload module\n" );
+	} else {
+		DRM_DEBUG( "minor %d unregistered\n", dev->minor);
+	}
+	
 #if __HAVE_CTX_BITMAP
 		DRM(ctxbitmap_cleanup)( dev );
 #endif
@@ -709,22 +763,40 @@
 		}
 #endif
 
-		DRM(takedown)( dev );
 
 #if __REALLY_HAVE_AGP
-		if ( dev->agp ) {
-			DRM(agp_uninit)();
-			DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
-			dev->agp = NULL;
-		}
+	if ( dev->agp ) {
+		DRM(agp_uninit)();
+		DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
+		dev->agp = NULL;
+	}
 #endif
+
+	class_simple_device_remove(MKDEV(DRM_MAJOR, 0));
+}
+
+static void __exit drm_exit (void)
+{
+	if (DRM(fb_loaded)==1)
+	{
+		int i;
+		drm_device_t *dev;
+
+		for (i = DRM(numdevs) - 1; i >= 0; i--) {
+			dev = &(DRM(device)[i]);
+			/* release the pci driver */
+			if (dev->pdev)
+				pci_dev_put(dev->pdev);
+			drm_cleanup(dev);
+		}
 	}
-	DRIVER_POSTCLEANUP();
-	DRM(numdevs) = 0;
+	else
+		pci_unregister_driver(&drm_driver);
+	DRM_INFO( "Module unloaded\n" );
 }
 
 module_init( drm_init );
-module_exit( drm_cleanup );
+module_exit( drm_exit );
 
 
 /**
diff -Nru a/drivers/char/drm/drm_stub.h b/drivers/char/drm/drm_stub.h
--- a/drivers/char/drm/drm_stub.h	2004-07-13 12:38:43 -07:00
+++ b/drivers/char/drm/drm_stub.h	2004-07-13 12:38:43 -07:00
@@ -35,8 +35,6 @@
 
 #define DRM_STUB_MAXCARDS 16	/* Enough for one machine */
 
-static struct class_simple *drm_class;
-
 /** Stub list. One for each minor. */
 static struct drm_stub_list {
 	const char             *name;
@@ -46,13 +44,6 @@
 
 static struct proc_dir_entry *DRM(stub_root);
 
-/** Stub information */
-static struct drm_stub_info {
-	int (*info_register)(const char *name, struct file_operations *fops,
-			     drm_device_t *dev);
-	int (*info_unregister)(int minor);
-} DRM(stub_info);
-
 /**
  * File \c open operation.
  *
@@ -119,7 +110,6 @@
 			DRM(stub_root) = DRM(proc_init)(dev, i, DRM(stub_root),
 							&DRM(stub_list)[i]
 							.dev_root);
-			class_simple_device_add(drm_class, MKDEV(DRM_MAJOR, i), NULL, name);
 			return i;
 		}
 	}
@@ -144,16 +134,14 @@
 	DRM(proc_cleanup)(minor, DRM(stub_root),
 			  DRM(stub_list)[minor].dev_root);
 	if (minor) {
-		class_simple_device_remove(MKDEV(DRM_MAJOR, minor));
 		inter_module_put("drm");
 	} else {
 		inter_module_unregister("drm");
 		DRM(free)(DRM(stub_list),
 			  sizeof(*DRM(stub_list)) * DRM_STUB_MAXCARDS,
 			  DRM_MEM_STUB);
+		class_simple_destroy(DRM(stub_info).drm_class);
 		unregister_chrdev(DRM_MAJOR, "drm");
-		class_simple_device_remove(MKDEV(DRM_MAJOR, minor));
-		class_simple_destroy(drm_class);
 	}
 	return 0;
 }
@@ -181,27 +169,24 @@
 
 	DRM_DEBUG("\n");
 	ret1 = register_chrdev(DRM_MAJOR, "drm", &DRM(stub_fops));
-	if (!ret1) {
-		drm_class = class_simple_create(THIS_MODULE, "drm");
-		if (IS_ERR(drm_class)) {
-			printk (KERN_ERR "Error creating drm class.\n");
-			unregister_chrdev(DRM_MAJOR, "drm");
-			return PTR_ERR(drm_class);
-		}
-	}
-	else if (ret1 == -EBUSY)
+	if (ret1 == -EBUSY) 
 		i = (struct drm_stub_info *)inter_module_get("drm");
-	else
+	if (ret1 < 0)
 		return -1;
 
 	if (i) {
 				/* Already registered */
 		DRM(stub_info).info_register   = i->info_register;
 		DRM(stub_info).info_unregister = i->info_unregister;
+		DRM(stub_info).drm_class = i->drm_class;
 		DRM_DEBUG("already registered\n");
-	} else if (DRM(stub_info).info_register != DRM(stub_getminor)) {
-		DRM(stub_info).info_register   = DRM(stub_getminor);
-		DRM(stub_info).info_unregister = DRM(stub_putminor);
+	} else if (DRM(stub_info).drm_class == NULL) {
+		DRM(stub_info).drm_class = class_simple_create(THIS_MODULE, "drm");
+		if (IS_ERR(DRM(stub_info).drm_class)) {
+                        printk (KERN_ERR "Error creating drm class.\n");
+                        unregister_chrdev(DRM_MAJOR, "drm");
+                        return PTR_ERR(DRM(stub_info).drm_class);
+		}
 		DRM_DEBUG("calling inter_module_register\n");
 		inter_module_register("drm", THIS_MODULE, &DRM(stub_info));
 	}
@@ -210,7 +195,7 @@
 		if (ret2) {
 			if (!ret1) {
 				unregister_chrdev(DRM_MAJOR, "drm");
-				class_simple_destroy(drm_class);
+				class_simple_destroy(DRM(stub_info).drm_class);
 			}
 			if (!i)
 				inter_module_unregister("drm");
@@ -234,3 +219,10 @@
 		return DRM(stub_info).info_unregister(minor);
 	return -1;
 }
+
+/** Stub information */
+struct drm_stub_info DRM(stub_info) = {
+	.info_register   = DRM(stub_getminor),
+	.info_unregister = DRM(stub_putminor),
+	.drm_class = NULL,
+};