From d3da253adbf471c9af9c68b2ff67cbf516856352 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 4 Jan 2008 17:49:40 +1100 Subject: drm: add initial support for a drm control device node --- linux-core/drmP.h | 8 ++++---- linux-core/drm_drv.c | 3 ++- linux-core/drm_stub.c | 44 ++++++++++++++++++++++++++--------------- linux-core/drm_sysfs.c | 53 +++++++++++++++++++++++++++++--------------------- 4 files changed, 65 insertions(+), 43 deletions(-) (limited to 'linux-core') diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 962ad4eb..5bc4887a 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -699,6 +699,7 @@ struct drm_minor { int minor; /**< Minor device number */ int type; /**< Control or render */ dev_t device; /**< Device number for mknod */ + struct device kdev; /**< Linux device */ struct drm_device *dev; /* for render nodes */ struct proc_dir_entry *dev_root; /**< proc directory entry */ @@ -711,7 +712,6 @@ struct drm_minor { * may contain multiple heads. */ struct drm_device { - struct device dev; /**< Linux device */ char *unique; /**< Unique identifier: e.g., busid */ int unique_len; /**< Length of unique field */ char *devname; /**< For /proc/interrupts */ @@ -1158,7 +1158,7 @@ extern void drm_agp_chipset_flush(struct drm_device *dev); extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver); extern int drm_put_dev(struct drm_device *dev); -extern int drm_put_head(struct drm_minor *minor); +extern int drm_put_minor(struct drm_minor *minor); extern unsigned int drm_debug; /* 1 to enable debug output */ extern unsigned int drm_minors_limit; extern struct drm_minor **drm_minors; @@ -1198,8 +1198,8 @@ extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t *dmah); struct drm_sysfs_class; extern struct class *drm_sysfs_create(struct module *owner, char *name); extern void drm_sysfs_destroy(void); -extern int drm_sysfs_device_add(struct drm_device *dev, struct drm_minor *minor); -extern void drm_sysfs_device_remove(struct drm_device *dev); +extern int drm_sysfs_device_add(struct drm_minor *minor); +extern void drm_sysfs_device_remove(struct drm_minor *minor); /* * Basic memory manager support (drm_mm.c) diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 29fa18d8..58beec66 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -423,7 +423,8 @@ static void drm_cleanup(struct drm_device * dev) drm_mm_takedown(&dev->offset_manager); drm_ht_remove(&dev->object_hash); - drm_put_head(&dev->primary); + drm_put_minor(&dev->primary); + drm_put_minor(&dev->control); if (drm_put_dev(dev)) DRM_ERROR("Cannot unload module\n"); } diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c index 433869e6..cee00c5e 100644 --- a/linux-core/drm_stub.c +++ b/linux-core/drm_stub.c @@ -160,7 +160,7 @@ error_out_unreg: * create the proc init entry via proc_init(). This routines assigns * minor numbers to secondary heads of multi-headed cards */ -static int drm_get_head(struct drm_device * dev, struct drm_minor *minor) +static int drm_get_minor(struct drm_device *dev, struct drm_minor *minor, int type) { struct drm_minor **minors = drm_minors; int ret; @@ -172,19 +172,23 @@ static int drm_get_head(struct drm_device * dev, struct drm_minor *minor) if (!*minors) { *minor = (struct drm_minor) { + .type = type, .dev = dev, .device = MKDEV(DRM_MAJOR, index), .minor = index, }; - if ((ret = - drm_proc_init(dev, index, drm_proc_root, - &minor->dev_root))) { - printk(KERN_ERR - "DRM: Failed to initialize /proc/dri.\n"); - goto err_g1; - } - ret = drm_sysfs_device_add(dev, minor); + if (type == DRM_MINOR_RENDER) { + ret = drm_proc_init(dev, index, drm_proc_root, + &minor->dev_root); + if (ret) { + DRM_ERROR("DRM: Failed to initialize /proc/dri.\n"); + goto err_g1; + } + } else + minor->dev_root = NULL; + + ret = drm_sysfs_device_add(minor); if (ret) { printk(KERN_ERR "DRM: Error sysfs_device_add.\n"); @@ -199,7 +203,8 @@ static int drm_get_head(struct drm_device * dev, struct drm_minor *minor) DRM_ERROR("out of minors\n"); return -ENOMEM; err_g2: - drm_proc_cleanup(index, drm_proc_root, minor->dev_root); + if (minor->type == DRM_MINOR_RENDER) + drm_proc_cleanup(index, drm_proc_root, minor->dev_root); err_g1: *minor = (struct drm_minor) { .dev = NULL}; @@ -245,22 +250,28 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, printk(KERN_ERR "DRM: fill_in_dev failed\n"); goto err_g3; } - if ((ret = drm_get_head(dev, &dev->primary))) + + if ((ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL))) goto err_g3; + if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_RENDER))) + goto err_g4; + DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, dev->primary.minor); return 0; - err_g3: +err_g4: + drm_put_minor(&dev->control); +err_g3: if (!drm_fb_loaded) pci_disable_device(pdev); - err_g2: +err_g2: if (!drm_fb_loaded) pci_release_regions(pdev); - err_g1: +err_g1: if (!drm_fb_loaded) pci_set_drvdata(pdev, NULL); @@ -315,8 +326,9 @@ int drm_put_minor(struct drm_minor *minor) DRM_DEBUG("release secondary minor %d\n", index); - drm_proc_cleanup(index, drm_proc_root, minor->dev_root); - drm_sysfs_device_remove(minor->dev); + if (minor->type == DRM_MINOR_RENDER) + drm_proc_cleanup(index, drm_proc_root, minor->dev_root); + drm_sysfs_device_remove(minor); *minor = (struct drm_minor) {.type = DRM_MINOR_UNASSIGNED, .dev = NULL}; diff --git a/linux-core/drm_sysfs.c b/linux-core/drm_sysfs.c index 1f2d763b..a56e9959 100644 --- a/linux-core/drm_sysfs.c +++ b/linux-core/drm_sysfs.c @@ -19,7 +19,7 @@ #include "drm_core.h" #include "drmP.h" -#define to_drm_device(d) container_of(d, struct drm_device, dev) +#define to_drm_minor(d) container_of(d, struct drm_minor, kdev) /** * drm_sysfs_suspend - DRM class suspend hook @@ -31,7 +31,8 @@ */ static int drm_sysfs_suspend(struct device *dev, pm_message_t state) { - struct drm_device *drm_dev = to_drm_device(dev); + struct drm_minor *drm_minor = to_drm_minor(dev); + struct drm_device *drm_dev = drm_minor->dev; printk(KERN_ERR "%s\n", __FUNCTION__); @@ -50,7 +51,8 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state) */ static int drm_sysfs_resume(struct device *dev) { - struct drm_device *drm_dev = to_drm_device(dev); + struct drm_minor *drm_minor = to_drm_minor(dev); + struct drm_device *drm_dev = drm_minor->dev; if (drm_dev->driver->resume) return drm_dev->driver->resume(drm_dev); @@ -122,10 +124,11 @@ void drm_sysfs_destroy(void) static ssize_t show_dri(struct device *device, struct device_attribute *attr, char *buf) { - struct drm_device *dev = to_drm_device(device); - if (dev->driver->dri_library_name) - return dev->driver->dri_library_name(dev, buf); - return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name); + struct drm_minor *drm_minor = to_drm_minor(device); + struct drm_device *drm_dev = drm_minor->dev; + if (drm_dev->driver->dri_library_name) + return drm_dev->driver->dri_library_name(drm_dev, buf); + return snprintf(buf, PAGE_SIZE, "%s\n", drm_dev->driver->pci_driver.name); } static struct device_attribute device_attrs[] = { @@ -154,25 +157,31 @@ static void drm_sysfs_device_release(struct device *dev) * as the parent for the Linux device, and make sure it has a file containing * the driver we're using (for userspace compatibility). */ -int drm_sysfs_device_add(struct drm_device *dev, struct drm_minor *minor) +int drm_sysfs_device_add(struct drm_minor *minor) { int err; int i, j; - - dev->dev.parent = &dev->pdev->dev; - dev->dev.class = drm_class; - dev->dev.release = drm_sysfs_device_release; - dev->dev.devt = minor->device; - snprintf(dev->dev.bus_id, BUS_ID_SIZE, "card%d", minor->minor); - - err = device_register(&dev->dev); + char *minor_str; + + minor->kdev.parent = &minor->dev->pdev->dev; + minor->kdev.class = drm_class; + minor->kdev.release = drm_sysfs_device_release; + minor->kdev.devt = minor->device; + if (minor->type == DRM_MINOR_CONTROL) + minor_str = "controlD%d"; + else + minor_str = "card%d"; + + snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->minor); + + err = device_register(&minor->kdev); if (err) { DRM_ERROR("device add failed: %d\n", err); goto err_out; } for (i = 0; i < ARRAY_SIZE(device_attrs); i++) { - err = device_create_file(&dev->dev, &device_attrs[i]); + err = device_create_file(&minor->kdev, &device_attrs[i]); if (err) goto err_out_files; } @@ -182,8 +191,8 @@ int drm_sysfs_device_add(struct drm_device *dev, struct drm_minor *minor) err_out_files: if (i > 0) for (j = 0; j < i; j++) - device_remove_file(&dev->dev, &device_attrs[i]); - device_unregister(&dev->dev); + device_remove_file(&minor->kdev, &device_attrs[i]); + device_unregister(&minor->kdev); err_out: return err; @@ -196,11 +205,11 @@ err_out: * This call unregisters and cleans up a class device that was created with a * call to drm_sysfs_device_add() */ -void drm_sysfs_device_remove(struct drm_device *dev) +void drm_sysfs_device_remove(struct drm_minor *minor) { int i; for (i = 0; i < ARRAY_SIZE(device_attrs); i++) - device_remove_file(&dev->dev, &device_attrs[i]); - device_unregister(&dev->dev); + device_remove_file(&minor->kdev, &device_attrs[i]); + device_unregister(&minor->kdev); } -- cgit v1.2.3