aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_stub.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2008-11-27 23:22:24 -0500
committerDave Airlie <airlied@linux.ie>2008-12-29 02:47:22 -0500
commit7c1c2871a6a3a114853ec6836e9035ac1c0c7f7a (patch)
tree1b5debcc86ff20bd5e11b42ea5c52da42214e376 /drivers/gpu/drm/drm_stub.c
parente7f7ab45ebcb54fd5f814ea15ea079e079662f67 (diff)
drm: move to kref per-master structures.
This is step one towards having multiple masters sharing a drm device in order to get fast-user-switching to work. It splits out the information associated with the drm master into a separate kref counted structure, and allocates this when a master opens the device node. It also allows the current master to abdicate (say while VT switched), and a new master to take over the hardware. It moves the Intel and radeon drivers to using the sarea from within the new master structures. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_stub.c')
-rw-r--r--drivers/gpu/drm/drm_stub.c105
1 files changed, 99 insertions, 6 deletions
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 849c0a9fe7fd..0f24c2dcd517 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -79,6 +79,104 @@ again:
79 return new_id; 79 return new_id;
80} 80}
81 81
82struct drm_master *drm_master_create(struct drm_minor *minor)
83{
84 struct drm_master *master;
85
86 master = drm_calloc(1, sizeof(*master), DRM_MEM_DRIVER);
87 if (!master)
88 return NULL;
89
90 kref_init(&master->refcount);
91 spin_lock_init(&master->lock.spinlock);
92 init_waitqueue_head(&master->lock.lock_queue);
93 drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER);
94 INIT_LIST_HEAD(&master->magicfree);
95 master->minor = minor;
96
97 list_add_tail(&master->head, &minor->master_list);
98
99 return master;
100}
101
102struct drm_master *drm_master_get(struct drm_master *master)
103{
104 kref_get(&master->refcount);
105 return master;
106}
107
108static void drm_master_destroy(struct kref *kref)
109{
110 struct drm_master *master = container_of(kref, struct drm_master, refcount);
111 struct drm_magic_entry *pt, *next;
112 struct drm_device *dev = master->minor->dev;
113
114 list_del(&master->head);
115
116 if (dev->driver->master_destroy)
117 dev->driver->master_destroy(dev, master);
118
119 if (master->unique) {
120 drm_free(master->unique, strlen(master->unique) + 1, DRM_MEM_DRIVER);
121 master->unique = NULL;
122 master->unique_len = 0;
123 }
124
125 list_for_each_entry_safe(pt, next, &master->magicfree, head) {
126 list_del(&pt->head);
127 drm_ht_remove_item(&master->magiclist, &pt->hash_item);
128 drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
129 }
130
131 drm_ht_remove(&master->magiclist);
132
133 if (master->lock.hw_lock) {
134 if (dev->sigdata.lock == master->lock.hw_lock)
135 dev->sigdata.lock = NULL;
136 master->lock.hw_lock = NULL;
137 master->lock.file_priv = NULL;
138 wake_up_interruptible(&master->lock.lock_queue);
139 }
140
141 drm_free(master, sizeof(*master), DRM_MEM_DRIVER);
142}
143
144void drm_master_put(struct drm_master **master)
145{
146 kref_put(&(*master)->refcount, drm_master_destroy);
147 *master = NULL;
148}
149
150int drm_setmaster_ioctl(struct drm_device *dev, void *data,
151 struct drm_file *file_priv)
152{
153 if (file_priv->minor->master && file_priv->minor->master != file_priv->master)
154 return -EINVAL;
155
156 if (!file_priv->master)
157 return -EINVAL;
158
159 if (!file_priv->minor->master &&
160 file_priv->minor->master != file_priv->master) {
161 mutex_lock(&dev->struct_mutex);
162 file_priv->minor->master = drm_master_get(file_priv->master);
163 mutex_lock(&dev->struct_mutex);
164 }
165
166 return 0;
167}
168
169int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
170 struct drm_file *file_priv)
171{
172 if (!file_priv->master)
173 return -EINVAL;
174 mutex_lock(&dev->struct_mutex);
175 drm_master_put(&file_priv->minor->master);
176 mutex_unlock(&dev->struct_mutex);
177 return 0;
178}
179
82static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, 180static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
83 const struct pci_device_id *ent, 181 const struct pci_device_id *ent,
84 struct drm_driver *driver) 182 struct drm_driver *driver)
@@ -92,7 +190,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
92 190
93 spin_lock_init(&dev->count_lock); 191 spin_lock_init(&dev->count_lock);
94 spin_lock_init(&dev->drw_lock); 192 spin_lock_init(&dev->drw_lock);
95 spin_lock_init(&dev->lock.spinlock);
96 init_timer(&dev->timer); 193 init_timer(&dev->timer);
97 mutex_init(&dev->struct_mutex); 194 mutex_init(&dev->struct_mutex);
98 mutex_init(&dev->ctxlist_mutex); 195 mutex_init(&dev->ctxlist_mutex);
@@ -200,6 +297,7 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int t
200 new_minor->device = MKDEV(DRM_MAJOR, minor_id); 297 new_minor->device = MKDEV(DRM_MAJOR, minor_id);
201 new_minor->dev = dev; 298 new_minor->dev = dev;
202 new_minor->index = minor_id; 299 new_minor->index = minor_id;
300 INIT_LIST_HEAD(&new_minor->master_list);
203 301
204 idr_replace(&drm_minors_idr, new_minor, minor_id); 302 idr_replace(&drm_minors_idr, new_minor, minor_id);
205 303
@@ -299,11 +397,6 @@ int drm_put_dev(struct drm_device * dev)
299{ 397{
300 DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name); 398 DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name);
301 399
302 if (dev->unique) {
303 drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
304 dev->unique = NULL;
305 dev->unique_len = 0;
306 }
307 if (dev->devname) { 400 if (dev->devname) {
308 drm_free(dev->devname, strlen(dev->devname) + 1, 401 drm_free(dev->devname, strlen(dev->devname) + 1,
309 DRM_MEM_DRIVER); 402 DRM_MEM_DRIVER);