aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/drm/drmP.h11
-rw-r--r--drivers/char/drm/drm_drv.c10
-rw-r--r--drivers/char/drm/drm_stub.c7
-rw-r--r--drivers/char/drm/drm_sysfs.c151
4 files changed, 117 insertions, 62 deletions
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 36caf93db30..19d3be5c4b2 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -568,6 +568,8 @@ struct drm_driver {
568 void (*postclose) (struct drm_device *, struct drm_file *); 568 void (*postclose) (struct drm_device *, struct drm_file *);
569 void (*lastclose) (struct drm_device *); 569 void (*lastclose) (struct drm_device *);
570 int (*unload) (struct drm_device *); 570 int (*unload) (struct drm_device *);
571 int (*suspend) (struct drm_device *);
572 int (*resume) (struct drm_device *);
571 int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv); 573 int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv);
572 void (*dma_ready) (struct drm_device *); 574 void (*dma_ready) (struct drm_device *);
573 int (*dma_quiescent) (struct drm_device *); 575 int (*dma_quiescent) (struct drm_device *);
@@ -643,6 +645,7 @@ struct drm_head {
643 * may contain multiple heads. 645 * may contain multiple heads.
644 */ 646 */
645struct drm_device { 647struct drm_device {
648 struct device dev; /**< Linux device */
646 char *unique; /**< Unique identifier: e.g., busid */ 649 char *unique; /**< Unique identifier: e.g., busid */
647 int unique_len; /**< Length of unique field */ 650 int unique_len; /**< Length of unique field */
648 char *devname; /**< For /proc/interrupts */ 651 char *devname; /**< For /proc/interrupts */
@@ -1063,11 +1066,11 @@ extern void __drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
1063extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah); 1066extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
1064 1067
1065 /* sysfs support (drm_sysfs.c) */ 1068 /* sysfs support (drm_sysfs.c) */
1069struct drm_sysfs_class;
1066extern struct class *drm_sysfs_create(struct module *owner, char *name); 1070extern struct class *drm_sysfs_create(struct module *owner, char *name);
1067extern void drm_sysfs_destroy(struct class *cs); 1071extern void drm_sysfs_destroy(void);
1068extern struct class_device *drm_sysfs_device_add(struct class *cs, 1072extern int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head);
1069 struct drm_head *head); 1073extern void drm_sysfs_device_remove(struct drm_device *dev);
1070extern void drm_sysfs_device_remove(struct class_device *class_dev);
1071 1074
1072/* 1075/*
1073 * Basic memory manager support (drm_mm.c) 1076 * Basic memory manager support (drm_mm.c)
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index 44a46268b02..fc6e7646cd6 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -386,19 +386,19 @@ static int __init drm_core_init(void)
386 DRM_INFO("Initialized %s %d.%d.%d %s\n", 386 DRM_INFO("Initialized %s %d.%d.%d %s\n",
387 CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE); 387 CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
388 return 0; 388 return 0;
389 err_p3: 389err_p3:
390 drm_sysfs_destroy(drm_class); 390 drm_sysfs_destroy();
391 err_p2: 391err_p2:
392 unregister_chrdev(DRM_MAJOR, "drm"); 392 unregister_chrdev(DRM_MAJOR, "drm");
393 drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB); 393 drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
394 err_p1: 394err_p1:
395 return ret; 395 return ret;
396} 396}
397 397
398static void __exit drm_core_exit(void) 398static void __exit drm_core_exit(void)
399{ 399{
400 remove_proc_entry("dri", NULL); 400 remove_proc_entry("dri", NULL);
401 drm_sysfs_destroy(drm_class); 401 drm_sysfs_destroy();
402 402
403 unregister_chrdev(DRM_MAJOR, "drm"); 403 unregister_chrdev(DRM_MAJOR, "drm");
404 404
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index cdde3c3320f..2ed7a5c6790 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -168,11 +168,10 @@ static int drm_get_head(struct drm_device * dev, struct drm_head * head)
168 goto err_g1; 168 goto err_g1;
169 } 169 }
170 170
171 head->dev_class = drm_sysfs_device_add(drm_class, head); 171 ret = drm_sysfs_device_add(dev, head);
172 if (IS_ERR(head->dev_class)) { 172 if (ret) {
173 printk(KERN_ERR 173 printk(KERN_ERR
174 "DRM: Error sysfs_device_add.\n"); 174 "DRM: Error sysfs_device_add.\n");
175 ret = PTR_ERR(head->dev_class);
176 goto err_g2; 175 goto err_g2;
177 } 176 }
178 *heads = head; 177 *heads = head;
@@ -283,7 +282,7 @@ int drm_put_head(struct drm_head * head)
283 DRM_DEBUG("release secondary minor %d\n", minor); 282 DRM_DEBUG("release secondary minor %d\n", minor);
284 283
285 drm_proc_cleanup(minor, drm_proc_root, head->dev_root); 284 drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
286 drm_sysfs_device_remove(head->dev_class); 285 drm_sysfs_device_remove(head->dev);
287 286
288 *head = (struct drm_head) {.dev = NULL}; 287 *head = (struct drm_head) {.dev = NULL};
289 288
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index cf4349b00b0..6f8623ce045 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -19,6 +19,45 @@
19#include "drm_core.h" 19#include "drm_core.h"
20#include "drmP.h" 20#include "drmP.h"
21 21
22#define to_drm_device(d) container_of(d, struct drm_device, dev)
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_device *drm_dev = to_drm_device(dev);
35
36 printk(KERN_ERR "%s\n", __FUNCTION__);
37
38 if (drm_dev->driver->suspend)
39 return drm_dev->driver->suspend(drm_dev);
40
41 return 0;
42}
43
44/**
45 * drm_sysfs_resume - DRM class resume hook
46 * @dev: Linux device to resume
47 *
48 * Just figures out what the actual struct drm_device associated with
49 * @dev is and calls its resume hook, if present.
50 */
51static int drm_sysfs_resume(struct device *dev)
52{
53 struct drm_device *drm_dev = to_drm_device(dev);
54
55 if (drm_dev->driver->resume)
56 return drm_dev->driver->resume(drm_dev);
57
58 return 0;
59}
60
22/* Display the version of drm_core. This doesn't work right in current design */ 61/* Display the version of drm_core. This doesn't work right in current design */
23static ssize_t version_show(struct class *dev, char *buf) 62static ssize_t version_show(struct class *dev, char *buf)
24{ 63{
@@ -33,7 +72,7 @@ static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
33 * @owner: pointer to the module that is to "own" this struct drm_sysfs_class 72 * @owner: pointer to the module that is to "own" this struct drm_sysfs_class
34 * @name: pointer to a string for the name of this class. 73 * @name: pointer to a string for the name of this class.
35 * 74 *
36 * This is used to create a struct drm_sysfs_class pointer that can then be used 75 * This is used to create DRM class pointer that can then be used
37 * in calls to drm_sysfs_device_add(). 76 * in calls to drm_sysfs_device_add().
38 * 77 *
39 * Note, the pointer created here is to be destroyed when finished by making a 78 * Note, the pointer created here is to be destroyed when finished by making a
@@ -50,6 +89,9 @@ struct class *drm_sysfs_create(struct module *owner, char *name)
50 goto err_out; 89 goto err_out;
51 } 90 }
52 91
92 class->suspend = drm_sysfs_suspend;
93 class->resume = drm_sysfs_resume;
94
53 err = class_create_file(class, &class_attr_version); 95 err = class_create_file(class, &class_attr_version);
54 if (err) 96 if (err)
55 goto err_out_class; 97 goto err_out_class;
@@ -63,94 +105,105 @@ err_out:
63} 105}
64 106
65/** 107/**
66 * drm_sysfs_destroy - destroys a struct drm_sysfs_class structure 108 * drm_sysfs_destroy - destroys DRM class
67 * @cs: pointer to the struct drm_sysfs_class that is to be destroyed
68 * 109 *
69 * Note, the pointer to be destroyed must have been created with a call to 110 * Destroy the DRM device class.
70 * drm_sysfs_create().
71 */ 111 */
72void drm_sysfs_destroy(struct class *class) 112void drm_sysfs_destroy(void)
73{ 113{
74 if ((class == NULL) || (IS_ERR(class))) 114 if ((drm_class == NULL) || (IS_ERR(drm_class)))
75 return; 115 return;
76 116 class_remove_file(drm_class, &class_attr_version);
77 class_remove_file(class, &class_attr_version); 117 class_destroy(drm_class);
78 class_destroy(class);
79} 118}
80 119
81static ssize_t show_dri(struct class_device *class_device, char *buf) 120static ssize_t show_dri(struct device *device, struct device_attribute *attr,
121 char *buf)
82{ 122{
83 struct drm_device * dev = ((struct drm_head *)class_get_devdata(class_device))->dev; 123 struct drm_device *dev = to_drm_device(device);
84 if (dev->driver->dri_library_name) 124 if (dev->driver->dri_library_name)
85 return dev->driver->dri_library_name(dev, buf); 125 return dev->driver->dri_library_name(dev, buf);
86 return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name); 126 return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name);
87} 127}
88 128
89static struct class_device_attribute class_device_attrs[] = { 129static struct device_attribute device_attrs[] = {
90 __ATTR(dri_library_name, S_IRUGO, show_dri, NULL), 130 __ATTR(dri_library_name, S_IRUGO, show_dri, NULL),
91}; 131};
92 132
93/** 133/**
134 * drm_sysfs_device_release - do nothing
135 * @dev: Linux device
136 *
137 * Normally, this would free the DRM device associated with @dev, along
138 * with cleaning up any other stuff. But we do that in the DRM core, so
139 * this function can just return and hope that the core does its job.
140 */
141static void drm_sysfs_device_release(struct device *dev)
142{
143 return;
144}
145
146/**
94 * drm_sysfs_device_add - adds a class device to sysfs for a character driver 147 * drm_sysfs_device_add - adds a class device to sysfs for a character driver
95 * @cs: pointer to the struct class that this device should be registered to. 148 * @dev: DRM device to be added
96 * @dev: the dev_t for the device to be added. 149 * @head: DRM head in question
97 * @device: a pointer to a struct device that is assiociated with this class device.
98 * @fmt: string for the class device's name
99 * 150 *
100 * A struct class_device will be created in sysfs, registered to the specified 151 * Add a DRM device to the DRM's device model class. We use @dev's PCI device
101 * class. A "dev" file will be created, showing the dev_t for the device. The 152 * as the parent for the Linux device, and make sure it has a file containing
102 * pointer to the struct class_device will be returned from the call. Any further 153 * the driver we're using (for userspace compatibility).
103 * sysfs files that might be required can be created using this pointer.
104 * Note: the struct class passed to this function must have previously been
105 * created with a call to drm_sysfs_create().
106 */ 154 */
107struct class_device *drm_sysfs_device_add(struct class *cs, struct drm_head *head) 155int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head)
108{ 156{
109 struct class_device *class_dev; 157 int err;
110 int i, j, err; 158 int i, j;
111 159
112 class_dev = class_device_create(cs, NULL, 160 dev->dev.parent = &dev->pdev->dev;
113 MKDEV(DRM_MAJOR, head->minor), 161 dev->dev.class = drm_class;
114 &(head->dev->pdev)->dev, 162 dev->dev.release = drm_sysfs_device_release;
115 "card%d", head->minor); 163 /*
116 if (IS_ERR(class_dev)) { 164 * This will actually add the major:minor file so that udev
117 err = PTR_ERR(class_dev); 165 * will create the device node. We don't want to do that just
166 * yet...
167 */
168 /* dev->dev.devt = head->device; */
169 snprintf(dev->dev.bus_id, BUS_ID_SIZE, "card%d", head->minor);
170
171 err = device_register(&dev->dev);
172 if (err) {
173 DRM_ERROR("device add failed: %d\n", err);
118 goto err_out; 174 goto err_out;
119 } 175 }
120 176
121 class_set_devdata(class_dev, head); 177 for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
122 178 err = device_create_file(&dev->dev, &device_attrs[i]);
123 for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) {
124 err = class_device_create_file(class_dev,
125 &class_device_attrs[i]);
126 if (err) 179 if (err)
127 goto err_out_files; 180 goto err_out_files;
128 } 181 }
129 182
130 return class_dev; 183 return 0;
131 184
132err_out_files: 185err_out_files:
133 if (i > 0) 186 if (i > 0)
134 for (j = 0; j < i; j++) 187 for (j = 0; j < i; j++)
135 class_device_remove_file(class_dev, 188 device_remove_file(&dev->dev, &device_attrs[i]);
136 &class_device_attrs[i]); 189 device_unregister(&dev->dev);
137 class_device_unregister(class_dev);
138err_out: 190err_out:
139 return ERR_PTR(err); 191
192 return err;
140} 193}
141 194
142/** 195/**
143 * drm_sysfs_device_remove - removes a class device that was created with drm_sysfs_device_add() 196 * drm_sysfs_device_remove - remove DRM device
144 * @dev: the dev_t of the device that was previously registered. 197 * @dev: DRM device to remove
145 * 198 *
146 * This call unregisters and cleans up a class device that was created with a 199 * This call unregisters and cleans up a class device that was created with a
147 * call to drm_sysfs_device_add() 200 * call to drm_sysfs_device_add()
148 */ 201 */
149void drm_sysfs_device_remove(struct class_device *class_dev) 202void drm_sysfs_device_remove(struct drm_device *dev)
150{ 203{
151 int i; 204 int i;
152 205
153 for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) 206 for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
154 class_device_remove_file(class_dev, &class_device_attrs[i]); 207 device_remove_file(&dev->dev, &device_attrs[i]);
155 class_device_unregister(class_dev); 208 device_unregister(&dev->dev);
156} 209}