Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.26-rc2 210 lines 5.4 kB view raw
1 2/* 3 * drm_sysfs.c - Modifications to drm_sysfs_class.c to support 4 * extra sysfs attribute from DRM. Normal drm_sysfs_class 5 * does not allow adding attributes. 6 * 7 * Copyright (c) 2004 Jon Smirl <jonsmirl@gmail.com> 8 * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com> 9 * Copyright (c) 2003-2004 IBM Corp. 10 * 11 * This file is released under the GPLv2 12 * 13 */ 14 15#include <linux/device.h> 16#include <linux/kdev_t.h> 17#include <linux/err.h> 18 19#include "drm_core.h" 20#include "drmP.h" 21 22#define to_drm_minor(d) container_of(d, struct drm_minor, kdev) 23 24/** 25 * drm_sysfs_suspend - DRM class suspend hook 26 * @dev: Linux device to suspend 27 * @state: power state to enter 28 * 29 * Just figures out what the actual struct drm_device associated with 30 * @dev is and calls its suspend hook, if present. 31 */ 32static int drm_sysfs_suspend(struct device *dev, pm_message_t state) 33{ 34 struct drm_minor *drm_minor = to_drm_minor(dev); 35 struct drm_device *drm_dev = drm_minor->dev; 36 37 printk(KERN_ERR "%s\n", __func__); 38 39 if (drm_dev->driver->suspend) 40 return drm_dev->driver->suspend(drm_dev, state); 41 42 return 0; 43} 44 45/** 46 * drm_sysfs_resume - DRM class resume hook 47 * @dev: Linux device to resume 48 * 49 * Just figures out what the actual struct drm_device associated with 50 * @dev is and calls its resume hook, if present. 51 */ 52static int drm_sysfs_resume(struct device *dev) 53{ 54 struct drm_minor *drm_minor = to_drm_minor(dev); 55 struct drm_device *drm_dev = drm_minor->dev; 56 57 if (drm_dev->driver->resume) 58 return drm_dev->driver->resume(drm_dev); 59 60 return 0; 61} 62 63/* Display the version of drm_core. This doesn't work right in current design */ 64static ssize_t version_show(struct class *dev, char *buf) 65{ 66 return sprintf(buf, "%s %d.%d.%d %s\n", CORE_NAME, CORE_MAJOR, 67 CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE); 68} 69 70static CLASS_ATTR(version, S_IRUGO, version_show, NULL); 71 72/** 73 * drm_sysfs_create - create a struct drm_sysfs_class structure 74 * @owner: pointer to the module that is to "own" this struct drm_sysfs_class 75 * @name: pointer to a string for the name of this class. 76 * 77 * This is used to create DRM class pointer that can then be used 78 * in calls to drm_sysfs_device_add(). 79 * 80 * Note, the pointer created here is to be destroyed when finished by making a 81 * call to drm_sysfs_destroy(). 82 */ 83struct class *drm_sysfs_create(struct module *owner, char *name) 84{ 85 struct class *class; 86 int err; 87 88 class = class_create(owner, name); 89 if (IS_ERR(class)) { 90 err = PTR_ERR(class); 91 goto err_out; 92 } 93 94 class->suspend = drm_sysfs_suspend; 95 class->resume = drm_sysfs_resume; 96 97 err = class_create_file(class, &class_attr_version); 98 if (err) 99 goto err_out_class; 100 101 return class; 102 103err_out_class: 104 class_destroy(class); 105err_out: 106 return ERR_PTR(err); 107} 108 109/** 110 * drm_sysfs_destroy - destroys DRM class 111 * 112 * Destroy the DRM device class. 113 */ 114void drm_sysfs_destroy(void) 115{ 116 if ((drm_class == NULL) || (IS_ERR(drm_class))) 117 return; 118 class_remove_file(drm_class, &class_attr_version); 119 class_destroy(drm_class); 120} 121 122static ssize_t show_dri(struct device *device, struct device_attribute *attr, 123 char *buf) 124{ 125 struct drm_minor *drm_minor = to_drm_minor(device); 126 struct drm_device *drm_dev = drm_minor->dev; 127 if (drm_dev->driver->dri_library_name) 128 return drm_dev->driver->dri_library_name(drm_dev, buf); 129 return snprintf(buf, PAGE_SIZE, "%s\n", drm_dev->driver->pci_driver.name); 130} 131 132static struct device_attribute device_attrs[] = { 133 __ATTR(dri_library_name, S_IRUGO, show_dri, NULL), 134}; 135 136/** 137 * drm_sysfs_device_release - do nothing 138 * @dev: Linux device 139 * 140 * Normally, this would free the DRM device associated with @dev, along 141 * with cleaning up any other stuff. But we do that in the DRM core, so 142 * this function can just return and hope that the core does its job. 143 */ 144static void drm_sysfs_device_release(struct device *dev) 145{ 146 return; 147} 148 149/** 150 * drm_sysfs_device_add - adds a class device to sysfs for a character driver 151 * @dev: DRM device to be added 152 * @head: DRM head in question 153 * 154 * Add a DRM device to the DRM's device model class. We use @dev's PCI device 155 * as the parent for the Linux device, and make sure it has a file containing 156 * the driver we're using (for userspace compatibility). 157 */ 158int drm_sysfs_device_add(struct drm_minor *minor) 159{ 160 int err; 161 int i, j; 162 char *minor_str; 163 164 minor->kdev.parent = &minor->dev->pdev->dev; 165 minor->kdev.class = drm_class; 166 minor->kdev.release = drm_sysfs_device_release; 167 minor->kdev.devt = minor->device; 168 minor_str = "card%d"; 169 170 snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index); 171 172 err = device_register(&minor->kdev); 173 if (err) { 174 DRM_ERROR("device add failed: %d\n", err); 175 goto err_out; 176 } 177 178 for (i = 0; i < ARRAY_SIZE(device_attrs); i++) { 179 err = device_create_file(&minor->kdev, &device_attrs[i]); 180 if (err) 181 goto err_out_files; 182 } 183 184 return 0; 185 186err_out_files: 187 if (i > 0) 188 for (j = 0; j < i; j++) 189 device_remove_file(&minor->kdev, &device_attrs[i]); 190 device_unregister(&minor->kdev); 191err_out: 192 193 return err; 194} 195 196/** 197 * drm_sysfs_device_remove - remove DRM device 198 * @dev: DRM device to remove 199 * 200 * This call unregisters and cleans up a class device that was created with a 201 * call to drm_sysfs_device_add() 202 */ 203void drm_sysfs_device_remove(struct drm_minor *minor) 204{ 205 int i; 206 207 for (i = 0; i < ARRAY_SIZE(device_attrs); i++) 208 device_remove_file(&minor->kdev, &device_attrs[i]); 209 device_unregister(&minor->kdev); 210}