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, +};