aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/drm_fops.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/drm/drm_fops.c')
-rw-r--r--drivers/char/drm/drm_fops.c289
1 files changed, 166 insertions, 123 deletions
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index b73543c694a9..403f44a1bf01 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -35,6 +35,7 @@
35 */ 35 */
36 36
37#include "drmP.h" 37#include "drmP.h"
38#include "drm_sarea.h"
38#include <linux/poll.h> 39#include <linux/poll.h>
39 40
40static int drm_open_helper(struct inode *inode, struct file *filp, 41static int drm_open_helper(struct inode *inode, struct file *filp,
@@ -42,6 +43,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
42 43
43static int drm_setup(drm_device_t * dev) 44static int drm_setup(drm_device_t * dev)
44{ 45{
46 drm_local_map_t *map;
45 int i; 47 int i;
46 int ret; 48 int ret;
47 49
@@ -51,6 +53,11 @@ static int drm_setup(drm_device_t * dev)
51 return ret; 53 return ret;
52 } 54 }
53 55
56 /* prebuild the SAREA */
57 i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, _DRM_CONTAINS_LOCK, &map);
58 if (i != 0)
59 return i;
60
54 atomic_set(&dev->ioctl_count, 0); 61 atomic_set(&dev->ioctl_count, 0);
55 atomic_set(&dev->vma_count, 0); 62 atomic_set(&dev->vma_count, 0);
56 dev->buf_use = 0; 63 dev->buf_use = 0;
@@ -152,10 +159,168 @@ int drm_open(struct inode *inode, struct file *filp)
152 159
153 return retcode; 160 return retcode;
154} 161}
155
156EXPORT_SYMBOL(drm_open); 162EXPORT_SYMBOL(drm_open);
157 163
158/** 164/**
165 * File \c open operation.
166 *
167 * \param inode device inode.
168 * \param filp file pointer.
169 *
170 * Puts the dev->fops corresponding to the device minor number into
171 * \p filp, call the \c open method, and restore the file operations.
172 */
173int drm_stub_open(struct inode *inode, struct file *filp)
174{
175 drm_device_t *dev = NULL;
176 int minor = iminor(inode);
177 int err = -ENODEV;
178 struct file_operations *old_fops;
179
180 DRM_DEBUG("\n");
181
182 if (!((minor >= 0) && (minor < drm_cards_limit)))
183 return -ENODEV;
184
185 if (!drm_heads[minor])
186 return -ENODEV;
187
188 if (!(dev = drm_heads[minor]->dev))
189 return -ENODEV;
190
191 old_fops = filp->f_op;
192 filp->f_op = fops_get(&dev->driver->fops);
193 if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
194 fops_put(filp->f_op);
195 filp->f_op = fops_get(old_fops);
196 }
197 fops_put(old_fops);
198
199 return err;
200}
201
202/**
203 * Check whether DRI will run on this CPU.
204 *
205 * \return non-zero if the DRI will run on this CPU, or zero otherwise.
206 */
207static int drm_cpu_valid(void)
208{
209#if defined(__i386__)
210 if (boot_cpu_data.x86 == 3)
211 return 0; /* No cmpxchg on a 386 */
212#endif
213#if defined(__sparc__) && !defined(__sparc_v9__)
214 return 0; /* No cmpxchg before v9 sparc. */
215#endif
216 return 1;
217}
218
219/**
220 * Called whenever a process opens /dev/drm.
221 *
222 * \param inode device inode.
223 * \param filp file pointer.
224 * \param dev device.
225 * \return zero on success or a negative number on failure.
226 *
227 * Creates and initializes a drm_file structure for the file private data in \p
228 * filp and add it into the double linked list in \p dev.
229 */
230static int drm_open_helper(struct inode *inode, struct file *filp,
231 drm_device_t * dev)
232{
233 int minor = iminor(inode);
234 drm_file_t *priv;
235 int ret;
236
237 if (filp->f_flags & O_EXCL)
238 return -EBUSY; /* No exclusive opens */
239 if (!drm_cpu_valid())
240 return -EINVAL;
241
242 DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
243
244 priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
245 if (!priv)
246 return -ENOMEM;
247
248 memset(priv, 0, sizeof(*priv));
249 filp->private_data = priv;
250 priv->uid = current->euid;
251 priv->pid = current->pid;
252 priv->minor = minor;
253 priv->head = drm_heads[minor];
254 priv->ioctl_count = 0;
255 /* for compatibility root is always authenticated */
256 priv->authenticated = capable(CAP_SYS_ADMIN);
257 priv->lock_count = 0;
258
259 if (dev->driver->open) {
260 ret = dev->driver->open(dev, priv);
261 if (ret < 0)
262 goto out_free;
263 }
264
265 down(&dev->struct_sem);
266 if (!dev->file_last) {
267 priv->next = NULL;
268 priv->prev = NULL;
269 dev->file_first = priv;
270 dev->file_last = priv;
271 /* first opener automatically becomes master */
272 priv->master = 1;
273 } else {
274 priv->next = NULL;
275 priv->prev = dev->file_last;
276 dev->file_last->next = priv;
277 dev->file_last = priv;
278 }
279 up(&dev->struct_sem);
280
281#ifdef __alpha__
282 /*
283 * Default the hose
284 */
285 if (!dev->hose) {
286 struct pci_dev *pci_dev;
287 pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
288 if (pci_dev) {
289 dev->hose = pci_dev->sysdata;
290 pci_dev_put(pci_dev);
291 }
292 if (!dev->hose) {
293 struct pci_bus *b = pci_bus_b(pci_root_buses.next);
294 if (b)
295 dev->hose = b->sysdata;
296 }
297 }
298#endif
299
300 return 0;
301 out_free:
302 drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
303 filp->private_data = NULL;
304 return ret;
305}
306
307/** No-op. */
308int drm_fasync(int fd, struct file *filp, int on)
309{
310 drm_file_t *priv = filp->private_data;
311 drm_device_t *dev = priv->head->dev;
312 int retcode;
313
314 DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
315 (long)old_encode_dev(priv->head->device));
316 retcode = fasync_helper(fd, filp, on, &dev->buf_async);
317 if (retcode < 0)
318 return retcode;
319 return 0;
320}
321EXPORT_SYMBOL(drm_fasync);
322
323/**
159 * Release file. 324 * Release file.
160 * 325 *
161 * \param inode device inode 326 * \param inode device inode
@@ -291,7 +456,6 @@ int drm_release(struct inode *inode, struct file *filp)
291 456
292 if (dev->driver->postclose) 457 if (dev->driver->postclose)
293 dev->driver->postclose(dev, priv); 458 dev->driver->postclose(dev, priv);
294
295 drm_free(priv, sizeof(*priv), DRM_MEM_FILES); 459 drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
296 460
297 /* ======================================================== 461 /* ========================================================
@@ -318,132 +482,11 @@ int drm_release(struct inode *inode, struct file *filp)
318 482
319 return retcode; 483 return retcode;
320} 484}
321
322EXPORT_SYMBOL(drm_release); 485EXPORT_SYMBOL(drm_release);
323 486
324/**
325 * Check whether DRI will run on this CPU.
326 *
327 * \return non-zero if the DRI will run on this CPU, or zero otherwise.
328 */
329static int drm_cpu_valid(void)
330{
331#if defined(__i386__)
332 if (boot_cpu_data.x86 == 3)
333 return 0; /* No cmpxchg on a 386 */
334#endif
335#if defined(__sparc__) && !defined(__sparc_v9__)
336 return 0; /* No cmpxchg before v9 sparc. */
337#endif
338 return 1;
339}
340
341/**
342 * Called whenever a process opens /dev/drm.
343 *
344 * \param inode device inode.
345 * \param filp file pointer.
346 * \param dev device.
347 * \return zero on success or a negative number on failure.
348 *
349 * Creates and initializes a drm_file structure for the file private data in \p
350 * filp and add it into the double linked list in \p dev.
351 */
352static int drm_open_helper(struct inode *inode, struct file *filp,
353 drm_device_t * dev)
354{
355 int minor = iminor(inode);
356 drm_file_t *priv;
357 int ret;
358
359 if (filp->f_flags & O_EXCL)
360 return -EBUSY; /* No exclusive opens */
361 if (!drm_cpu_valid())
362 return -EINVAL;
363
364 DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
365
366 priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
367 if (!priv)
368 return -ENOMEM;
369
370 memset(priv, 0, sizeof(*priv));
371 filp->private_data = priv;
372 priv->uid = current->euid;
373 priv->pid = current->pid;
374 priv->minor = minor;
375 priv->head = drm_heads[minor];
376 priv->ioctl_count = 0;
377 priv->authenticated = capable(CAP_SYS_ADMIN);
378 priv->lock_count = 0;
379
380 if (dev->driver->open) {
381 ret = dev->driver->open(dev, priv);
382 if (ret < 0)
383 goto out_free;
384 }
385
386 down(&dev->struct_sem);
387 if (!dev->file_last) {
388 priv->next = NULL;
389 priv->prev = NULL;
390 dev->file_first = priv;
391 dev->file_last = priv;
392 } else {
393 priv->next = NULL;
394 priv->prev = dev->file_last;
395 dev->file_last->next = priv;
396 dev->file_last = priv;
397 }
398 up(&dev->struct_sem);
399
400#ifdef __alpha__
401 /*
402 * Default the hose
403 */
404 if (!dev->hose) {
405 struct pci_dev *pci_dev;
406 pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
407 if (pci_dev) {
408 dev->hose = pci_dev->sysdata;
409 pci_dev_put(pci_dev);
410 }
411 if (!dev->hose) {
412 struct pci_bus *b = pci_bus_b(pci_root_buses.next);
413 if (b)
414 dev->hose = b->sysdata;
415 }
416 }
417#endif
418
419 return 0;
420 out_free:
421 drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
422 filp->private_data = NULL;
423 return ret;
424}
425
426/** No-op. */
427int drm_fasync(int fd, struct file *filp, int on)
428{
429 drm_file_t *priv = filp->private_data;
430 drm_device_t *dev = priv->head->dev;
431 int retcode;
432
433 DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
434 (long)old_encode_dev(priv->head->device));
435 retcode = fasync_helper(fd, filp, on, &dev->buf_async);
436 if (retcode < 0)
437 return retcode;
438 return 0;
439}
440
441EXPORT_SYMBOL(drm_fasync);
442
443/** No-op. */ 487/** No-op. */
444unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) 488unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
445{ 489{
446 return 0; 490 return 0;
447} 491}
448
449EXPORT_SYMBOL(drm_poll); 492EXPORT_SYMBOL(drm_poll);