aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Barnes <jesse.barnes@intel.com>2007-11-21 23:02:38 -0500
committerDave Airlie <airlied@redhat.com>2008-02-07 00:09:38 -0500
commite8b962b6df50b74afed14af7f7a7d569b3ba70ac (patch)
tree4b40becefb49018a4b02a217673e44637040f4f6
parent8b40958032fd236194de57d29be9cf2c1f2643ee (diff)
drm: update DRM sysfs support
Make DRM devices use real Linux devices instead of class devices, which are going away. While we're at it, clean up some of the interfaces to take struct drm_device * or struct device * and use the global drm_class where needed instead of passing it around. Signed-off-by: Dave Airlie <airlied@linux.ie>
-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 36caf93db309..19d3be5c4b2d 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 44a46268b02b..fc6e7646cd61 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 cdde3c3320fa..2ed7a5c67906 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 cf4349b00b07..6f8623ce045e 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}