Merge branch 'master' into vblank-rework, fixup remaining drivers

Conflicts:

	linux-core/drmP.h
	linux-core/drm_drv.c
	linux-core/drm_irq.c
	shared-core/i915_drv.h
	shared-core/i915_irq.c
	shared-core/mga_drv.h
	shared-core/mga_irq.c
	shared-core/radeon_drv.h
	shared-core/radeon_irq.c

Merge in the latest master bits and update the remaining drivers (except
mach64 which math_b is working on).  Also remove the 9xx hack from the i915
driver; it seems to be correct.
main
Jesse Barnes 2007-10-30 12:52:46 -07:00
commit 91aae7e683
264 changed files with 21149 additions and 10991 deletions

65
.gitignore vendored
View File

@ -1,55 +1,5 @@
bsd-core/linux
bsd-core/drm.h
bsd-core/drm_sarea.h
bsd-core/i915_dma.c
bsd-core/i915_drm.h
bsd-core/i915_drv.h
bsd-core/i915_irq.c
bsd-core/i915_mem.c
bsd-core/mach64_dma.c
bsd-core/mach64_drm.h
bsd-core/mach64_drv.h
bsd-core/mach64_irq.c
bsd-core/mach64_state.c
bsd-core/mga_dma.c
bsd-core/mga_drm.h
bsd-core/mga_drv.h
bsd-core/mga_irq.c
bsd-core/mga_state.c
bsd-core/mga_ucode.h
bsd-core/mga_warp.c
bsd-core/nv_drv.h
bsd-core/r128_cce.c
bsd-core/r128_drm.h
bsd-core/r128_drv.h
bsd-core/r128_irq.c
bsd-core/r128_state.c
bsd-core/r300_cmdbuf.c
bsd-core/r300_reg.h
bsd-core/radeon_cp.c
bsd-core/radeon_drm.h
bsd-core/radeon_drv.h
bsd-core/radeon_irq.c
bsd-core/radeon_mem.c
bsd-core/radeon_state.c
bsd-core/savage_bci.c
bsd-core/savage_drm.h
bsd-core/savage_drv.h
bsd-core/savage_state.c
bsd-core/sis_drm.h
bsd-core/sis_drv.h
bsd-core/tdfx_drv.h
bsd-core/via_3d_reg.h
bsd-core/via_dma.c
bsd-core/via_drm.h
bsd-core/via_drv.c
bsd-core/via_drv.h
bsd-core/via_irq.c
bsd-core/via_map.c
bsd-core/via_verifier.c
bsd-core/via_verifier.h
bsd-core/via_video.c
*~
bsd-core/*/@
bsd-core/*/machine
*.flags
*.ko
*.ko.cmd
@ -75,6 +25,7 @@ config.log
config.status
config.sub
configure
configure.lineno
cscope.*
depcomp
device_if.h
@ -100,3 +51,13 @@ sis.kld
stamp-h1
tdfx.kld
via.kld
tests/auth
tests/dristat
tests/drmstat
tests/getclient
tests/getstats
tests/getversion
tests/lock
tests/openclose
tests/setversion
tests/updatedraw

View File

@ -22,7 +22,7 @@
# here too, but let's just do libdrm for now
AUTOMAKE_OPTIONS = foreign
SUBDIRS = libdrm shared-core
SUBDIRS = libdrm shared-core tests
pkgconfigdir = @pkgconfigdir@
pkgconfig_DATA = libdrm.pc

View File

@ -1,71 +1,11 @@
SHARED= ../shared-core
SHAREDFILES= drm.h \
drm_sarea.h \
i915_dma.c \
i915_drm.h \
i915_drv.h \
i915_irq.c \
i915_mem.c \
mach64_dma.c \
mach64_drm.h \
mach64_drv.h \
mach64_irq.c \
mach64_state.c \
mga_dma.c \
mga_drm.h \
mga_drv.h \
mga_irq.c \
mga_state.c \
mga_ucode.h \
mga_warp.c \
r128_cce.c \
r128_drm.h \
r128_drv.h \
r128_irq.c \
r128_state.c \
radeon_cp.c \
radeon_drm.h \
radeon_drv.h \
radeon_irq.c \
radeon_mem.c \
radeon_state.c \
r300_cmdbuf.c \
r300_reg.h \
savage_bci.c \
savage_drm.h \
savage_drv.h \
savage_state.c \
sis_drm.h \
sis_drv.h \
sis_ds.c \
sis_ds.h \
sis_mm.c \
tdfx_drv.h \
via_3d_reg.h \
via_dma.c \
via_drm.h \
via_drv.h \
via_ds.c \
via_ds.h \
via_irq.c \
via_map.c \
via_mm.c \
via_mm.h \
via_verifier.c \
via_verifier.h \
via_video.c
SUBDIR = drm mach64 mga r128 radeon savage sis tdfx i915 # via
CLEANFILES+= ${SHAREDFILES}
.include <bsd.obj.mk>
depend: drm_pciids.h ${SHAREDFILES}
all: drm_pciids.h ${SHAREDFILES}
depend: drm_pciids.h
all: drm_pciids.h
drm_pciids.h: ${SHARED}/drm_pciids.txt
sh ../scripts/create_bsd_pci_lists.sh < ${SHARED}/drm_pciids.txt
${SHAREDFILES}:
ln -sf ${SHARED}/$@ $@

View File

@ -1,6 +1,3 @@
/* ati_pcigart.h -- ATI PCI GART support -*- linux-c -*-
* Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com
*/
/*-
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
@ -29,6 +26,11 @@
*
*/
/** @file ati_pcigart.c
* Implementation of ATI's PCIGART, which provides an aperture in card virtual
* address space with addresses remapped to system memory.
*/
#include "drmP.h"
#define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */

1
bsd-core/drm.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/drm.h

View File

@ -59,6 +59,8 @@ typedef struct drm_file drm_file_t;
#include <sys/bus.h>
#include <sys/signalvar.h>
#include <sys/poll.h>
#include <sys/tree.h>
#include <sys/taskqueue.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
@ -152,6 +154,7 @@ typedef struct drm_file drm_file_t;
#define DRM_MEM_CTXBITMAP 17
#define DRM_MEM_STUB 18
#define DRM_MEM_SGLISTS 19
#define DRM_MEM_DRAWABLE 20
#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
@ -184,10 +187,15 @@ MALLOC_DECLARE(M_DRM);
#define DRM_CURPROC curthread
#define DRM_STRUCTPROC struct thread
#define DRM_SPINTYPE struct mtx
#define DRM_SPININIT(l,name) mtx_init(&l, name, NULL, MTX_DEF)
#define DRM_SPINUNINIT(l) mtx_destroy(&l)
#define DRM_SPININIT(l,name) mtx_init(l, name, NULL, MTX_DEF)
#define DRM_SPINUNINIT(l) mtx_destroy(l)
#define DRM_SPINLOCK(l) mtx_lock(l)
#define DRM_SPINUNLOCK(u) mtx_unlock(u);
#define DRM_SPINUNLOCK(u) mtx_unlock(u)
#define DRM_SPINLOCK_IRQSAVE(l, irqflags) do { \
mtx_lock(l); \
(void)irqflags; \
} while (0)
#define DRM_SPINUNLOCK_IRQRESTORE(u, irqflags) mtx_unlock(u)
#define DRM_SPINLOCK_ASSERT(l) mtx_assert(l, MA_OWNED)
#define DRM_CURRENTPID curthread->td_proc->p_pid
#define DRM_LOCK() mtx_lock(&dev->dev_lock)
@ -209,10 +217,6 @@ MALLOC_DECLARE(M_DRM);
#define spldrm() spltty()
#endif /* __NetBSD__ || __OpenBSD__ */
/* Currently our DRMFILE (filp) is a void * which is actually the pid
* of the current process. It should be a per-open unique pointer, but
* code for that is not yet written */
#define DRMFILE void *
#define DRM_IRQ_ARGS void *arg
typedef void irqreturn_t;
#define IRQ_HANDLED /* nothing */
@ -226,11 +230,15 @@ enum {
#define DRM_AGP_MEM struct agp_memory_info
#if defined(__FreeBSD__)
#define DRM_DEVICE \
drm_device_t *dev = kdev->si_drv1
#define DRM_IOCTL_ARGS struct cdev *kdev, u_long cmd, caddr_t data, \
int flags, DRM_STRUCTPROC *p, DRMFILE filp
#define drm_get_device_from_kdev(_kdev) (_kdev->si_drv1)
#elif defined(__NetBSD__)
#define drm_get_device_from_kdev(_kdev) device_lookup(&drm_cd, minor(_kdev))
#elif defined(__OpenBSD__)
#define drm_get_device_from_kdev(_kdev) device_lookup(&drm_cd, \
minor(_kdev)))->dv_cfdata->cf_driver->cd_devs[minor(_kdev)]
#endif
#if defined(__FreeBSD__)
#define PAGE_ALIGN(addr) round_page(addr)
/* DRM_SUSER returns true if the user is superuser */
#if __FreeBSD_version >= 700000
@ -244,17 +252,6 @@ enum {
#else /* __FreeBSD__ */
#if defined(__NetBSD__)
#define DRM_DEVICE \
drm_device_t *dev = device_lookup(&drm_cd, minor(kdev))
#elif defined(__OpenBSD__)
#define DRM_DEVICE \
drm_device_t *dev = (device_lookup(&drm_cd, \
minor(kdev)))->dv_cfdata->cf_driver->cd_devs[minor(kdev)]
#endif /* __OpenBSD__ */
#define DRM_IOCTL_ARGS dev_t kdev, u_long cmd, caddr_t data, \
int flags, DRM_STRUCTPROC *p, DRMFILE filp
#define CDEV_MAJOR 34
#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
/* DRM_SUSER returns true if the user is superuser */
@ -342,14 +339,6 @@ typedef vaddr_t vm_offset_t;
(!uvm_useracc((caddr_t)uaddr, size, VM_PROT_READ))
#endif /* !__FreeBSD__ */
#define DRM_COPY_TO_USER_IOCTL(user, kern, size) \
if ( IOCPARM_LEN(cmd) != size) \
return EINVAL; \
*user = kern;
#define DRM_COPY_FROM_USER_IOCTL(kern, user, size) \
if ( IOCPARM_LEN(cmd) != size) \
return EINVAL; \
kern = *user;
#define DRM_COPY_TO_USER(user, kern, size) \
copyout(kern, user, size)
#define DRM_COPY_FROM_USER(kern, user, size) \
@ -369,7 +358,6 @@ typedef vaddr_t vm_offset_t;
#define cpu_to_le32(x) htole32(x)
#define le32_to_cpu(x) le32toh(x)
#define DRM_ERR(v) v
#define DRM_HZ hz
#define DRM_UDELAY(udelay) DELAY(udelay)
#define DRM_TIME_SLICE (hz/20) /* Time slice for GLXContexts */
@ -378,23 +366,10 @@ typedef vaddr_t vm_offset_t;
(_map) = (_dev)->context_sareas[_ctx]; \
} while(0)
#define DRM_GET_PRIV_WITH_RETURN(_priv, _filp) \
do { \
if (_filp != (DRMFILE)(intptr_t)DRM_CURRENTPID) { \
DRM_ERROR("filp doesn't match curproc\n"); \
return EINVAL; \
} \
_priv = drm_find_file_by_proc(dev, DRM_CURPROC); \
if (_priv == NULL) { \
DRM_ERROR("can't find authenticator\n"); \
return EINVAL; \
} \
} while (0)
#define LOCK_TEST_WITH_RETURN(dev, filp) \
#define LOCK_TEST_WITH_RETURN(dev, file_priv) \
do { \
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || \
dev->lock.filp != filp) { \
dev->lock.file_priv != file_priv) { \
DRM_ERROR("%s called without lock held\n", \
__FUNCTION__); \
return EINVAL; \
@ -402,22 +377,24 @@ do { \
} while (0)
#if defined(__FreeBSD__) && __FreeBSD_version > 500000
/* Returns -errno to shared code */
#define DRM_WAIT_ON( ret, queue, timeout, condition ) \
for ( ret = 0 ; !ret && !(condition) ; ) { \
DRM_UNLOCK(); \
mtx_lock(&dev->irq_lock); \
if (!(condition)) \
ret = msleep(&(queue), &dev->irq_lock, \
ret = -msleep(&(queue), &dev->irq_lock, \
PZERO | PCATCH, "drmwtq", (timeout)); \
mtx_unlock(&dev->irq_lock); \
DRM_LOCK(); \
}
#else
/* Returns -errno to shared code */
#define DRM_WAIT_ON( ret, queue, timeout, condition ) \
for ( ret = 0 ; !ret && !(condition) ; ) { \
int s = spldrm(); \
if (!(condition)) \
ret = tsleep( &(queue), PZERO | PCATCH, \
ret = -tsleep( &(queue), PZERO | PCATCH, \
"drmwtq", (timeout) ); \
splx(s); \
}
@ -447,9 +424,16 @@ typedef struct drm_pci_id_list
#define DRM_MASTER 0x2
#define DRM_ROOT_ONLY 0x4
typedef struct drm_ioctl_desc {
int (*func)(DRM_IOCTL_ARGS);
unsigned long cmd;
int (*func)(drm_device_t *dev, void *data, struct drm_file *file_priv);
int flags;
} drm_ioctl_desc_t;
/**
* Creates a driver or general drm_ioctl_desc array entry for the given
* ioctl, for use by drm_ioctl().
*/
#define DRM_IOCTL_DEF(ioctl, func, flags) \
[DRM_IOCTL_NR(ioctl)] = {ioctl, func, flags}
typedef struct drm_magic_entry {
drm_magic_t magic;
@ -472,7 +456,7 @@ typedef struct drm_buf {
unsigned long bus_address; /* Bus address of buffer */
struct drm_buf *next; /* Kernel-only: used for free list */
__volatile__ int pending; /* On hardware DMA queue */
DRMFILE filp; /* Unique identifier of holding process */
struct drm_file *file_priv; /* Unique identifier of holding process */
int context; /* Kernel queue for this buffer */
enum {
DRM_LIST_NONE = 0,
@ -534,7 +518,7 @@ struct drm_file {
typedef struct drm_lock_data {
drm_hw_lock_t *hw_lock; /* Hardware lock */
DRMFILE filp; /* Unique identifier of holding process (NULL is kernel)*/
struct drm_file *file_priv; /* Unique identifier of holding process (NULL is kernel)*/
int lock_queue; /* Queue of blocked processes */
unsigned long lock_time; /* Time of last lock in jiffies */
} drm_lock_data_t;
@ -638,12 +622,13 @@ struct drm_driver_info {
int (*load)(struct drm_device *, unsigned long flags);
int (*firstopen)(struct drm_device *);
int (*open)(struct drm_device *, drm_file_t *);
void (*preclose)(struct drm_device *, void *filp);
void (*preclose)(struct drm_device *, struct drm_file *file_priv);
void (*postclose)(struct drm_device *, drm_file_t *);
void (*lastclose)(struct drm_device *);
int (*unload)(struct drm_device *);
void (*reclaim_buffers_locked)(struct drm_device *, void *filp);
int (*dma_ioctl)(DRM_IOCTL_ARGS);
void (*reclaim_buffers_locked)(struct drm_device *,
struct drm_file *file_priv);
int (*dma_ioctl)(drm_device_t *dev, void *data, struct drm_file *file_priv);
void (*dma_ready)(struct drm_device *);
int (*dma_quiescent)(struct drm_device *);
int (*dma_flush_block_and_flush)(struct drm_device *, int context,
@ -732,6 +717,8 @@ struct drm_device {
struct mtx irq_lock; /* protects irq condition checks */
struct mtx dev_lock; /* protects everything else */
#endif
DRM_SPINTYPE drw_lock;
/* Usage Counters */
int open_count; /* Outstanding files open */
int buf_use; /* Buffers in use -- cannot alloc */
@ -780,6 +767,7 @@ struct drm_device {
int last_context; /* Last current context */
int vbl_queue; /* vbl wait channel */
atomic_t vbl_received;
atomic_t vbl_received2;
#ifdef __FreeBSD__
struct sigio *buf_sigio; /* Processes waiting for SIGIO */
@ -796,6 +784,13 @@ struct drm_device {
void *dev_private;
unsigned int agp_buffer_token;
drm_local_map_t *agp_buffer_map;
struct unrhdr *drw_unrhdr;
/* RB tree of drawable infos */
RB_HEAD(drawable_tree, bsd_drm_drawable_info) drw_head;
struct task locked_task;
void (*locked_task_call)(drm_device_t *dev);
};
extern int drm_debug_flag;
@ -883,7 +878,7 @@ int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request);
int drm_dma_setup(drm_device_t *dev);
void drm_dma_takedown(drm_device_t *dev);
void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf);
void drm_reclaim_buffers(drm_device_t *dev, DRMFILE filp);
void drm_reclaim_buffers(drm_device_t *dev, struct drm_file *file_priv);
#define drm_core_reclaim_buffers drm_reclaim_buffers
/* IRQ support (drm_irq.c) */
@ -915,6 +910,7 @@ int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request);
/* Scatter Gather Support (drm_scatter.c) */
void drm_sg_cleanup(drm_sg_mem_t *entry);
int drm_sg_alloc(drm_device_t * dev, drm_scatter_gather_t * request);
#ifdef __FreeBSD__
/* sysctl support (drm_sysctl.h) */
@ -929,68 +925,72 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev,
drm_ati_pcigart_info *gart_info);
/* Locking IOCTL support (drm_drv.c) */
int drm_lock(DRM_IOCTL_ARGS);
int drm_unlock(DRM_IOCTL_ARGS);
int drm_version(DRM_IOCTL_ARGS);
int drm_setversion(DRM_IOCTL_ARGS);
int drm_lock(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_unlock(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_version(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_setversion(drm_device_t *dev, void *data, struct drm_file *file_priv);
/* Misc. IOCTL support (drm_ioctl.c) */
int drm_irq_by_busid(DRM_IOCTL_ARGS);
int drm_getunique(DRM_IOCTL_ARGS);
int drm_setunique(DRM_IOCTL_ARGS);
int drm_getmap(DRM_IOCTL_ARGS);
int drm_getclient(DRM_IOCTL_ARGS);
int drm_getstats(DRM_IOCTL_ARGS);
int drm_noop(DRM_IOCTL_ARGS);
int drm_irq_by_busid(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_getunique(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_setunique(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_getmap(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_getclient(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_getstats(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_noop(drm_device_t *dev, void *data, struct drm_file *file_priv);
/* Context IOCTL support (drm_context.c) */
int drm_resctx(DRM_IOCTL_ARGS);
int drm_addctx(DRM_IOCTL_ARGS);
int drm_modctx(DRM_IOCTL_ARGS);
int drm_getctx(DRM_IOCTL_ARGS);
int drm_switchctx(DRM_IOCTL_ARGS);
int drm_newctx(DRM_IOCTL_ARGS);
int drm_rmctx(DRM_IOCTL_ARGS);
int drm_setsareactx(DRM_IOCTL_ARGS);
int drm_getsareactx(DRM_IOCTL_ARGS);
int drm_resctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_addctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_modctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_getctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_switchctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_newctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_rmctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_setsareactx(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_getsareactx(drm_device_t *dev, void *data, struct drm_file *file_priv);
/* Drawable IOCTL support (drm_drawable.c) */
int drm_adddraw(DRM_IOCTL_ARGS);
int drm_rmdraw(DRM_IOCTL_ARGS);
int drm_adddraw(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_rmdraw(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_update_draw(drm_device_t *dev, void *data, struct drm_file *file_priv);
struct drm_drawable_info *drm_get_drawable_info(drm_device_t *dev, int handle);
/* Authentication IOCTL support (drm_auth.c) */
int drm_getmagic(DRM_IOCTL_ARGS);
int drm_authmagic(DRM_IOCTL_ARGS);
int drm_getmagic(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_authmagic(drm_device_t *dev, void *data, struct drm_file *file_priv);
/* Buffer management support (drm_bufs.c) */
int drm_addmap_ioctl(DRM_IOCTL_ARGS);
int drm_rmmap_ioctl(DRM_IOCTL_ARGS);
int drm_addbufs_ioctl(DRM_IOCTL_ARGS);
int drm_infobufs(DRM_IOCTL_ARGS);
int drm_markbufs(DRM_IOCTL_ARGS);
int drm_freebufs(DRM_IOCTL_ARGS);
int drm_mapbufs(DRM_IOCTL_ARGS);
int drm_addmap_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_rmmap_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_addbufs_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_infobufs(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_markbufs(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_freebufs(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_mapbufs(drm_device_t *dev, void *data, struct drm_file *file_priv);
/* DMA support (drm_dma.c) */
int drm_dma(DRM_IOCTL_ARGS);
int drm_dma(drm_device_t *dev, void *data, struct drm_file *file_priv);
/* IRQ support (drm_irq.c) */
int drm_control(DRM_IOCTL_ARGS);
int drm_wait_vblank(DRM_IOCTL_ARGS);
int drm_control(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_wait_vblank(drm_device_t *dev, void *data, struct drm_file *file_priv);
void drm_locked_tasklet(drm_device_t *dev,
void (*tasklet)(drm_device_t *dev));
/* AGP/GART support (drm_agpsupport.c) */
int drm_agp_acquire_ioctl(DRM_IOCTL_ARGS);
int drm_agp_release_ioctl(DRM_IOCTL_ARGS);
int drm_agp_enable_ioctl(DRM_IOCTL_ARGS);
int drm_agp_info_ioctl(DRM_IOCTL_ARGS);
int drm_agp_alloc_ioctl(DRM_IOCTL_ARGS);
int drm_agp_free_ioctl(DRM_IOCTL_ARGS);
int drm_agp_unbind_ioctl(DRM_IOCTL_ARGS);
int drm_agp_bind_ioctl(DRM_IOCTL_ARGS);
int drm_agp_acquire_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_agp_release_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_agp_enable_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_agp_info_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_agp_alloc_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_agp_free_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_agp_unbind_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_agp_bind_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
/* Scatter Gather Support (drm_scatter.c) */
int drm_sg_alloc(DRM_IOCTL_ARGS);
int drm_sg_free(DRM_IOCTL_ARGS);
int drm_sg_alloc_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_sg_free(drm_device_t *dev, void *data, struct drm_file *file_priv);
/* consistent PCI memory functions (drm_pci.c) */
drm_dma_handle_t *drm_pci_alloc(drm_device_t *dev, size_t size, size_t align,

View File

@ -1,6 +1,3 @@
/* drm_agpsupport.h -- DRM support for AGP/GART backend -*- linux-c -*-
* Created: Mon Dec 13 09:56:45 1999 by faith@precisioninsight.com
*/
/*-
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
@ -31,6 +28,11 @@
*
*/
/** @file drm_agpsupport.c
* Support code for tying the kernel AGP support to DRM drivers and
* the DRM's AGP ioctls.
*/
#include "drmP.h"
#ifdef __FreeBSD__
@ -125,11 +127,10 @@ int drm_agp_info(drm_device_t * dev, drm_agp_info_t *info)
return 0;
}
int drm_agp_info_ioctl(DRM_IOCTL_ARGS)
int drm_agp_info_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
int err;
drm_agp_info_t info;
DRM_DEVICE;
err = drm_agp_info(dev, &info);
if (err != 0)
@ -139,9 +140,8 @@ int drm_agp_info_ioctl(DRM_IOCTL_ARGS)
return 0;
}
int drm_agp_acquire_ioctl(DRM_IOCTL_ARGS)
int drm_agp_acquire_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
return drm_agp_acquire(dev);
}
@ -161,9 +161,8 @@ int drm_agp_acquire(drm_device_t *dev)
return 0;
}
int drm_agp_release_ioctl(DRM_IOCTL_ARGS)
int drm_agp_release_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
return drm_agp_release(dev);
}
@ -185,15 +184,13 @@ int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode)
dev->agp->mode = mode.mode;
agp_enable(dev->agp->agpdev, mode.mode);
dev->agp->base = dev->agp->info.ai_aperture_base;
dev->agp->enabled = 1;
return 0;
}
int drm_agp_enable_ioctl(DRM_IOCTL_ARGS)
int drm_agp_enable_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
drm_agp_mode_t mode;
DRM_DEVICE;
mode = *(drm_agp_mode_t *) data;
@ -243,9 +240,8 @@ int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request)
return 0;
}
int drm_agp_alloc_ioctl(DRM_IOCTL_ARGS)
int drm_agp_alloc_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_agp_buffer_t request;
int retcode;
@ -292,9 +288,8 @@ int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request)
return retcode;
}
int drm_agp_unbind_ioctl(DRM_IOCTL_ARGS)
int drm_agp_unbind_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_agp_binding_t request;
int retcode;
@ -333,9 +328,8 @@ int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request)
return retcode;
}
int drm_agp_bind_ioctl(DRM_IOCTL_ARGS)
int drm_agp_bind_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_agp_binding_t request;
int retcode;
@ -378,9 +372,8 @@ int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request)
}
int drm_agp_free_ioctl(DRM_IOCTL_ARGS)
int drm_agp_free_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_agp_buffer_t request;
int retcode;
@ -411,6 +404,7 @@ drm_agp_head_t *drm_agp_init(void)
return NULL;
head->agpdev = agpdev;
agp_get_info(agpdev, &head->info);
head->base = head->info.ai_aperture_base;
head->memory = NULL;
DRM_INFO("AGP at 0x%08lx %dMB\n",
(long)head->info.ai_aperture_base,

View File

@ -1,6 +1,3 @@
/* drm_auth.h -- IOCTLs for authentication -*- linux-c -*-
* Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
*/
/*-
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
@ -31,6 +28,11 @@
*
*/
/** @file drm_auth.c
* Implementation of the get/authmagic ioctls implementing the authentication
* scheme between the master and clients.
*/
#include "drmP.h"
static int drm_hash_magic(drm_magic_t magic)
@ -38,25 +40,29 @@ static int drm_hash_magic(drm_magic_t magic)
return magic & (DRM_HASH_SIZE-1);
}
/**
* Returns the file private associated with the given magic number.
*/
static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
{
drm_file_t *retval = NULL;
drm_magic_entry_t *pt;
int hash;
int hash = drm_hash_magic(magic);
hash = drm_hash_magic(magic);
DRM_SPINLOCK_ASSERT(&dev->dev_lock);
DRM_LOCK();
for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
if (pt->magic == magic) {
retval = pt->priv;
break;
return pt->priv;
}
}
DRM_UNLOCK();
return retval;
return NULL;
}
/**
* Inserts the given magic number into the hash table of used magic number
* lists.
*/
static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
{
int hash;
@ -64,9 +70,11 @@ static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
DRM_DEBUG("%d\n", magic);
DRM_SPINLOCK_ASSERT(&dev->dev_lock);
hash = drm_hash_magic(magic);
entry = malloc(sizeof(*entry), M_DRM, M_ZERO | M_NOWAIT);
if (!entry) return DRM_ERR(ENOMEM);
if (!entry) return ENOMEM;
entry->magic = magic;
entry->priv = priv;
entry->next = NULL;
@ -84,16 +92,21 @@ static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
return 0;
}
/**
* Removes the given magic number from the hash table of used magic number
* lists.
*/
static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
{
drm_magic_entry_t *prev = NULL;
drm_magic_entry_t *pt;
int hash;
DRM_SPINLOCK_ASSERT(&dev->dev_lock);
DRM_DEBUG("%d\n", magic);
hash = drm_hash_magic(magic);
DRM_LOCK();
for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
if (pt->magic == magic) {
if (dev->magiclist[hash].head == pt) {
@ -105,68 +118,69 @@ static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
if (prev) {
prev->next = pt->next;
}
DRM_UNLOCK();
return 0;
}
}
DRM_UNLOCK();
free(pt, M_DRM);
return DRM_ERR(EINVAL);
return EINVAL;
}
int drm_getmagic(DRM_IOCTL_ARGS)
/**
* Called by the client, this returns a unique magic number to be authorized
* by the master.
*
* The master may use its own knowledge of the client (such as the X
* connection that the magic is passed over) to determine if the magic number
* should be authenticated.
*/
int drm_getmagic(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
static drm_magic_t sequence = 0;
drm_auth_t auth;
drm_file_t *priv;
DRM_LOCK();
priv = drm_find_file_by_proc(dev, p);
DRM_UNLOCK();
if (priv == NULL) {
DRM_ERROR("can't find authenticator\n");
return EINVAL;
}
drm_auth_t *auth = data;
/* Find unique magic */
if (priv->magic) {
auth.magic = priv->magic;
if (file_priv->magic) {
auth->magic = file_priv->magic;
} else {
DRM_LOCK();
do {
int old = sequence;
auth.magic = old+1;
auth->magic = old+1;
if (!atomic_cmpset_int(&sequence, old, auth.magic))
if (!atomic_cmpset_int(&sequence, old, auth->magic))
continue;
} while (drm_find_file(dev, auth.magic));
priv->magic = auth.magic;
drm_add_magic(dev, priv, auth.magic);
} while (drm_find_file(dev, auth->magic));
file_priv->magic = auth->magic;
drm_add_magic(dev, file_priv, auth->magic);
DRM_UNLOCK();
}
DRM_DEBUG("%u\n", auth.magic);
DRM_COPY_TO_USER_IOCTL((drm_auth_t *)data, auth, sizeof(auth));
DRM_DEBUG("%u\n", auth->magic);
return 0;
}
int drm_authmagic(DRM_IOCTL_ARGS)
/**
* Marks the client associated with the given magic number as authenticated.
*/
int drm_authmagic(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
drm_auth_t auth;
drm_file_t *file;
DRM_DEVICE;
drm_auth_t *auth = data;
drm_file_t *priv;
DRM_COPY_FROM_USER_IOCTL(auth, (drm_auth_t *)data, sizeof(auth));
DRM_DEBUG("%u\n", auth->magic);
DRM_DEBUG("%u\n", auth.magic);
if ((file = drm_find_file(dev, auth.magic))) {
file->authenticated = 1;
drm_remove_magic(dev, auth.magic);
DRM_LOCK();
priv = drm_find_file(dev, auth->magic);
if (priv != NULL) {
priv->authenticated = 1;
drm_remove_magic(dev, auth->magic);
DRM_UNLOCK();
return 0;
} else {
DRM_UNLOCK();
return EINVAL;
}
return DRM_ERR(EINVAL);
}

View File

@ -1,6 +1,3 @@
/* drm_bufs.h -- Generic buffer template -*- linux-c -*-
* Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
*/
/*-
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
@ -31,6 +28,10 @@
*
*/
/** @file drm_bufs.c
* Implementation of the ioctls for setup of DRM mappings and DMA buffers.
*/
#include "dev/pci/pcireg.h"
#include "drmP.h"
@ -149,7 +150,7 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
*/
map = malloc(sizeof(*map), M_DRM, M_ZERO | M_NOWAIT);
if ( !map )
return DRM_ERR(ENOMEM);
return ENOMEM;
map->offset = offset;
map->size = size;
@ -172,7 +173,7 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
map->size, drm_order(map->size), map->handle );
if ( !map->handle ) {
free(map, M_DRM);
return DRM_ERR(ENOMEM);
return ENOMEM;
}
map->offset = (unsigned long)map->handle;
if ( map->flags & _DRM_CONTAINS_LOCK ) {
@ -182,7 +183,7 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
DRM_UNLOCK();
free(map->handle, M_DRM);
free(map, M_DRM);
return DRM_ERR(EBUSY);
return EBUSY;
}
dev->lock.hw_lock = map->handle; /* Pointer to lock */
DRM_UNLOCK();
@ -190,7 +191,17 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
break;
case _DRM_AGP:
/*valid = 0;*/
map->offset += dev->agp->base;
/* In some cases (i810 driver), user space may have already
* added the AGP base itself, because dev->agp->base previously
* only got set during AGP enable. So, only add the base
* address if the map's offset isn't already within the
* aperture.
*/
if (map->offset < dev->agp->base ||
map->offset > dev->agp->base +
dev->agp->info.ai_aperture_size - 1) {
map->offset += dev->agp->base;
}
map->mtrr = dev->agp->mtrr; /* for getmap */
/*for (entry = dev->agp->memory; entry; entry = entry->next) {
if ((map->offset >= entry->bound) &&
@ -202,13 +213,13 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
}
if (!valid) {
free(map, M_DRM);
return DRM_ERR(EACCES);
return EACCES;
}*/
break;
case _DRM_SCATTER_GATHER:
if (!dev->sg) {
free(map, M_DRM);
return DRM_ERR(EINVAL);
return EINVAL;
}
map->offset = map->offset + dev->sg->handle;
break;
@ -225,7 +236,7 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
map->dmah = drm_pci_alloc(dev, map->size, align, 0xfffffffful);
if (map->dmah == NULL) {
free(map, M_DRM);
return DRM_ERR(ENOMEM);
return ENOMEM;
}
map->handle = map->dmah->vaddr;
map->offset = map->dmah->busaddr;
@ -233,7 +244,7 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
default:
DRM_ERROR("Bad map type %d\n", map->type);
free(map, M_DRM);
return DRM_ERR(EINVAL);
return EINVAL;
}
DRM_LOCK();
@ -250,39 +261,35 @@ done:
return 0;
}
int drm_addmap_ioctl(DRM_IOCTL_ARGS)
int drm_addmap_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
drm_map_t request;
drm_map_t *request = data;
drm_local_map_t *map;
int err;
DRM_DEVICE;
if (!(dev->flags & (FREAD|FWRITE)))
return DRM_ERR(EACCES); /* Require read/write */
return EACCES; /* Require read/write */
DRM_COPY_FROM_USER_IOCTL(request, (drm_map_t *)data, sizeof(drm_map_t));
if (!DRM_SUSER(p) && request.type != _DRM_AGP)
return DRM_ERR(EACCES);
if (!DRM_SUSER(DRM_CURPROC) && request->type != _DRM_AGP)
return EACCES;
DRM_LOCK();
err = drm_addmap(dev, request.offset, request.size, request.type,
request.flags, &map);
err = drm_addmap(dev, request->offset, request->size, request->type,
request->flags, &map);
DRM_UNLOCK();
if (err != 0)
return err;
request.offset = map->offset;
request.size = map->size;
request.type = map->type;
request.flags = map->flags;
request.mtrr = map->mtrr;
request.handle = map->handle;
request->offset = map->offset;
request->size = map->size;
request->type = map->type;
request->flags = map->flags;
request->mtrr = map->mtrr;
request->handle = map->handle;
if (request.type != _DRM_SHM) {
request.handle = (void *)request.offset;
if (request->type != _DRM_SHM) {
request->handle = (void *)request->offset;
}
DRM_COPY_TO_USER_IOCTL((drm_map_t *)data, request, sizeof(drm_map_t));
return 0;
}
@ -333,17 +340,14 @@ void drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
* isn't in use.
*/
int drm_rmmap_ioctl(DRM_IOCTL_ARGS)
int drm_rmmap_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_local_map_t *map;
drm_map_t request;
DRM_COPY_FROM_USER_IOCTL( request, (drm_map_t *)data, sizeof(request) );
drm_map_t *request = data;
DRM_LOCK();
TAILQ_FOREACH(map, &dev->maplist, link) {
if (map->handle == request.handle &&
if (map->handle == request->handle &&
map->flags & _DRM_REMOVABLE)
break;
}
@ -351,7 +355,7 @@ int drm_rmmap_ioctl(DRM_IOCTL_ARGS)
/* No match found. */
if (map == NULL) {
DRM_UNLOCK();
return DRM_ERR(EINVAL);
return EINVAL;
}
drm_rmmap(dev, map);
@ -441,7 +445,7 @@ static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
}
if (!valid) {
DRM_DEBUG("zone invalid\n");
return DRM_ERR(EINVAL);
return EINVAL;
}*/
entry = &dma->bufs[order];
@ -449,7 +453,7 @@ static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
entry->buflist = malloc(count * sizeof(*entry->buflist), M_DRM,
M_NOWAIT | M_ZERO);
if ( !entry->buflist ) {
return DRM_ERR(ENOMEM);
return ENOMEM;
}
entry->buf_size = size;
@ -469,7 +473,7 @@ static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
buf->address = (void *)(agp_offset + offset);
buf->next = NULL;
buf->pending = 0;
buf->filp = NULL;
buf->file_priv = NULL;
buf->dev_priv_size = dev->driver.buf_priv_size;
buf->dev_private = malloc(buf->dev_priv_size, M_DRM,
@ -478,7 +482,7 @@ static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
drm_cleanup_buf_error(dev, entry);
return DRM_ERR(ENOMEM);
return ENOMEM;
}
offset += alignment;
@ -494,7 +498,7 @@ static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
if (temp_buflist == NULL) {
/* Free the entry because it isn't valid */
drm_cleanup_buf_error(dev, entry);
return DRM_ERR(ENOMEM);
return ENOMEM;
}
dma->buflist = temp_buflist;
@ -563,7 +567,7 @@ static int drm_do_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
temp_pagelist == NULL) {
free(entry->buflist, M_DRM);
free(entry->seglist, M_DRM);
return DRM_ERR(ENOMEM);
return ENOMEM;
}
memcpy(temp_pagelist, dma->pagelist, dma->page_count *
@ -586,7 +590,7 @@ static int drm_do_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
entry->seg_count = count;
drm_cleanup_buf_error(dev, entry);
free(temp_pagelist, M_DRM);
return DRM_ERR(ENOMEM);
return ENOMEM;
}
entry->seglist[entry->seg_count++] = dmah;
@ -610,7 +614,7 @@ static int drm_do_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
buf->bus_address = dmah->busaddr + offset;
buf->next = NULL;
buf->pending = 0;
buf->filp = NULL;
buf->file_priv = NULL;
buf->dev_priv_size = dev->driver.buf_priv_size;
buf->dev_private = malloc(buf->dev_priv_size, M_DRM,
@ -621,7 +625,7 @@ static int drm_do_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
entry->seg_count = count;
drm_cleanup_buf_error(dev, entry);
free(temp_pagelist, M_DRM);
return DRM_ERR(ENOMEM);
return ENOMEM;
}
DRM_DEBUG( "buffer %d @ %p\n",
@ -637,7 +641,7 @@ static int drm_do_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
/* Free the entry because it isn't valid */
drm_cleanup_buf_error(dev, entry);
free(temp_pagelist, M_DRM);
return DRM_ERR(ENOMEM);
return ENOMEM;
}
dma->buflist = temp_buflist;
@ -705,7 +709,7 @@ static int drm_do_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)
entry->buflist = malloc(count * sizeof(*entry->buflist), M_DRM,
M_NOWAIT | M_ZERO);
if (entry->buflist == NULL)
return DRM_ERR(ENOMEM);
return ENOMEM;
entry->buf_size = size;
entry->page_order = page_order;
@ -724,7 +728,7 @@ static int drm_do_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)
buf->address = (void *)(agp_offset + offset + dev->sg->handle);
buf->next = NULL;
buf->pending = 0;
buf->filp = NULL;
buf->file_priv = NULL;
buf->dev_priv_size = dev->driver.buf_priv_size;
buf->dev_private = malloc(buf->dev_priv_size, M_DRM,
@ -733,7 +737,7 @@ static int drm_do_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
drm_cleanup_buf_error(dev, entry);
return DRM_ERR(ENOMEM);
return ENOMEM;
}
DRM_DEBUG( "buffer %d @ %p\n",
@ -752,7 +756,7 @@ static int drm_do_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)
if (temp_buflist == NULL) {
/* Free the entry because it isn't valid */
drm_cleanup_buf_error(dev, entry);
return DRM_ERR(ENOMEM);
return ENOMEM;
}
dma->buflist = temp_buflist;
@ -781,21 +785,21 @@ int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
DRM_SPINLOCK(&dev->dma_lock);
if (request->count < 0 || request->count > 4096)
return DRM_ERR(EINVAL);
return EINVAL;
order = drm_order(request->size);
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
return DRM_ERR(EINVAL);
return EINVAL;
/* No more allocations after first buffer-using ioctl. */
if (dev->buf_use != 0) {
DRM_SPINUNLOCK(&dev->dma_lock);
return DRM_ERR(EBUSY);
return EBUSY;
}
/* No more than one allocation per order */
if (dev->dma->bufs[order].buf_count != 0) {
DRM_SPINUNLOCK(&dev->dma_lock);
return DRM_ERR(ENOMEM);
return ENOMEM;
}
ret = drm_do_addbufs_agp(dev, request);
@ -812,24 +816,24 @@ int drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)
DRM_SPINLOCK(&dev->dma_lock);
if (!DRM_SUSER(DRM_CURPROC))
return DRM_ERR(EACCES);
return EACCES;
if (request->count < 0 || request->count > 4096)
return DRM_ERR(EINVAL);
return EINVAL;
order = drm_order(request->size);
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
return DRM_ERR(EINVAL);
return EINVAL;
/* No more allocations after first buffer-using ioctl. */
if (dev->buf_use != 0) {
DRM_SPINUNLOCK(&dev->dma_lock);
return DRM_ERR(EBUSY);
return EBUSY;
}
/* No more than one allocation per order */
if (dev->dma->bufs[order].buf_count != 0) {
DRM_SPINUNLOCK(&dev->dma_lock);
return DRM_ERR(ENOMEM);
return ENOMEM;
}
ret = drm_do_addbufs_sg(dev, request);
@ -846,24 +850,24 @@ int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
DRM_SPINLOCK(&dev->dma_lock);
if (!DRM_SUSER(DRM_CURPROC))
return DRM_ERR(EACCES);
return EACCES;
if (request->count < 0 || request->count > 4096)
return DRM_ERR(EINVAL);
return EINVAL;
order = drm_order(request->size);
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
return DRM_ERR(EINVAL);
return EINVAL;
/* No more allocations after first buffer-using ioctl. */
if (dev->buf_use != 0) {
DRM_SPINUNLOCK(&dev->dma_lock);
return DRM_ERR(EBUSY);
return EBUSY;
}
/* No more than one allocation per order */
if (dev->dma->bufs[order].buf_count != 0) {
DRM_SPINUNLOCK(&dev->dma_lock);
return DRM_ERR(ENOMEM);
return ENOMEM;
}
ret = drm_do_addbufs_pci(dev, request);
@ -873,39 +877,29 @@ int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
return ret;
}
int drm_addbufs_ioctl(DRM_IOCTL_ARGS)
int drm_addbufs_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_buf_desc_t request;
drm_buf_desc_t *request = data;
int err;
DRM_COPY_FROM_USER_IOCTL(request, (drm_buf_desc_t *)data,
sizeof(request));
if (request.flags & _DRM_AGP_BUFFER)
err = drm_addbufs_agp(dev, &request);
else if (request.flags & _DRM_SG_BUFFER)
err = drm_addbufs_sg(dev, &request);
if (request->flags & _DRM_AGP_BUFFER)
err = drm_addbufs_agp(dev, request);
else if (request->flags & _DRM_SG_BUFFER)
err = drm_addbufs_sg(dev, request);
else
err = drm_addbufs_pci(dev, &request);
DRM_COPY_TO_USER_IOCTL((drm_buf_desc_t *)data, request,
sizeof(request));
err = drm_addbufs_pci(dev, request);
return err;
}
int drm_infobufs(DRM_IOCTL_ARGS)
int drm_infobufs(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_device_dma_t *dma = dev->dma;
drm_buf_info_t request;
drm_buf_info_t *request = data;
int i;
int count;
int retcode = 0;
DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_info_t *)data, sizeof(request) );
DRM_SPINLOCK(&dev->dma_lock);
++dev->buf_use; /* Can't allocate more after this call */
DRM_SPINUNLOCK(&dev->dma_lock);
@ -916,7 +910,7 @@ int drm_infobufs(DRM_IOCTL_ARGS)
DRM_DEBUG( "count = %d\n", count );
if ( request.count >= count ) {
if ( request->count >= count ) {
for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) {
if ( dma->bufs[i].buf_count ) {
drm_buf_desc_t from;
@ -926,9 +920,9 @@ int drm_infobufs(DRM_IOCTL_ARGS)
from.low_mark = dma->bufs[i].freelist.low_mark;
from.high_mark = dma->bufs[i].freelist.high_mark;
if (DRM_COPY_TO_USER(&request.list[count], &from,
if (DRM_COPY_TO_USER(&request->list[count], &from,
sizeof(drm_buf_desc_t)) != 0) {
retcode = DRM_ERR(EFAULT);
retcode = EFAULT;
break;
}
@ -942,76 +936,68 @@ int drm_infobufs(DRM_IOCTL_ARGS)
}
}
}
request.count = count;
DRM_COPY_TO_USER_IOCTL( (drm_buf_info_t *)data, request, sizeof(request) );
request->count = count;
return retcode;
}
int drm_markbufs(DRM_IOCTL_ARGS)
int drm_markbufs(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_device_dma_t *dma = dev->dma;
drm_buf_desc_t request;
drm_buf_desc_t *request = data;
int order;
DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_desc_t *)data, sizeof(request) );
DRM_DEBUG( "%d, %d, %d\n",
request.size, request.low_mark, request.high_mark );
request->size, request->low_mark, request->high_mark );
order = drm_order(request.size);
order = drm_order(request->size);
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ||
request.low_mark < 0 || request.high_mark < 0) {
return DRM_ERR(EINVAL);
request->low_mark < 0 || request->high_mark < 0) {
return EINVAL;
}
DRM_SPINLOCK(&dev->dma_lock);
if (request.low_mark > dma->bufs[order].buf_count ||
request.high_mark > dma->bufs[order].buf_count) {
return DRM_ERR(EINVAL);
if (request->low_mark > dma->bufs[order].buf_count ||
request->high_mark > dma->bufs[order].buf_count) {
return EINVAL;
}
dma->bufs[order].freelist.low_mark = request.low_mark;
dma->bufs[order].freelist.high_mark = request.high_mark;
dma->bufs[order].freelist.low_mark = request->low_mark;
dma->bufs[order].freelist.high_mark = request->high_mark;
DRM_SPINUNLOCK(&dev->dma_lock);
return 0;
}
int drm_freebufs(DRM_IOCTL_ARGS)
int drm_freebufs(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_device_dma_t *dma = dev->dma;
drm_buf_free_t request;
drm_buf_free_t *request = data;
int i;
int idx;
drm_buf_t *buf;
int retcode = 0;
DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_free_t *)data, sizeof(request) );
DRM_DEBUG( "%d\n", request.count );
DRM_DEBUG( "%d\n", request->count );
DRM_SPINLOCK(&dev->dma_lock);
for ( i = 0 ; i < request.count ; i++ ) {
if (DRM_COPY_FROM_USER(&idx, &request.list[i], sizeof(idx))) {
retcode = DRM_ERR(EFAULT);
for ( i = 0 ; i < request->count ; i++ ) {
if (DRM_COPY_FROM_USER(&idx, &request->list[i], sizeof(idx))) {
retcode = EFAULT;
break;
}
if ( idx < 0 || idx >= dma->buf_count ) {
DRM_ERROR( "Index %d (of %d max)\n",
idx, dma->buf_count - 1 );
retcode = DRM_ERR(EINVAL);
retcode = EINVAL;
break;
}
buf = dma->buflist[idx];
if ( buf->filp != filp ) {
if ( buf->file_priv != file_priv ) {
DRM_ERROR("Process %d freeing buffer not owned\n",
DRM_CURRENTPID);
retcode = DRM_ERR(EINVAL);
retcode = EINVAL;
break;
}
drm_free_buffer(dev, buf);
@ -1021,9 +1007,8 @@ int drm_freebufs(DRM_IOCTL_ARGS)
return retcode;
}
int drm_mapbufs(DRM_IOCTL_ARGS)
int drm_mapbufs(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_device_dma_t *dma = dev->dma;
int retcode = 0;
const int zero = 0;
@ -1040,27 +1025,25 @@ int drm_mapbufs(DRM_IOCTL_ARGS)
vaddr_t vaddr;
#endif /* __NetBSD__ || __OpenBSD__ */
drm_buf_map_t request;
drm_buf_map_t *request = data;
int i;
DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_map_t *)data, sizeof(request) );
#if defined(__NetBSD__) || defined(__OpenBSD__)
if (!vfinddev(kdev, VCHR, &vn))
return 0; /* FIXME: Shouldn't this be EINVAL or something? */
#endif /* __NetBSD__ || __OpenBSD */
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
vms = p->td_proc->p_vmspace;
vms = DRM_CURPROC->td_proc->p_vmspace;
#else
vms = p->p_vmspace;
vms = DRM_CURPROC->p_vmspace;
#endif
DRM_SPINLOCK(&dev->dma_lock);
dev->buf_use++; /* Can't allocate more after this call */
DRM_SPINUNLOCK(&dev->dma_lock);
if (request.count < dma->buf_count)
if (request->count < dma->buf_count)
goto done;
if ((dev->driver.use_agp && (dma->flags & _DRM_DMA_USE_AGP)) ||
@ -1082,10 +1065,11 @@ int drm_mapbufs(DRM_IOCTL_ARGS)
vaddr = round_page((vm_offset_t)vms->vm_daddr + MAXDSIZ);
#if __FreeBSD_version >= 600023
retcode = vm_mmap(&vms->vm_map, &vaddr, size, PROT_READ | PROT_WRITE,
VM_PROT_ALL, MAP_SHARED, OBJT_DEVICE, kdev, foff );
VM_PROT_ALL, MAP_SHARED, OBJT_DEVICE, dev->devnode, foff);
#else
retcode = vm_mmap(&vms->vm_map, &vaddr, size, PROT_READ | PROT_WRITE,
VM_PROT_ALL, MAP_SHARED, SLIST_FIRST(&kdev->si_hlist), foff );
VM_PROT_ALL, MAP_SHARED, SLIST_FIRST(&dev->devnode->si_hlist),
foff);
#endif
#elif defined(__NetBSD__) || defined(__OpenBSD__)
vaddr = round_page((vaddr_t)vms->vm_daddr + MAXDSIZ);
@ -1096,26 +1080,26 @@ int drm_mapbufs(DRM_IOCTL_ARGS)
if (retcode)
goto done;
request.virtual = (void *)vaddr;
request->virtual = (void *)vaddr;
for ( i = 0 ; i < dma->buf_count ; i++ ) {
if (DRM_COPY_TO_USER(&request.list[i].idx,
&dma->buflist[i]->idx, sizeof(request.list[0].idx))) {
if (DRM_COPY_TO_USER(&request->list[i].idx,
&dma->buflist[i]->idx, sizeof(request->list[0].idx))) {
retcode = EFAULT;
goto done;
}
if (DRM_COPY_TO_USER(&request.list[i].total,
&dma->buflist[i]->total, sizeof(request.list[0].total))) {
if (DRM_COPY_TO_USER(&request->list[i].total,
&dma->buflist[i]->total, sizeof(request->list[0].total))) {
retcode = EFAULT;
goto done;
}
if (DRM_COPY_TO_USER(&request.list[i].used, &zero,
if (DRM_COPY_TO_USER(&request->list[i].used, &zero,
sizeof(zero))) {
retcode = EFAULT;
goto done;
}
address = vaddr + dma->buflist[i]->offset; /* *** */
if (DRM_COPY_TO_USER(&request.list[i].address, &address,
if (DRM_COPY_TO_USER(&request->list[i].address, &address,
sizeof(address))) {
retcode = EFAULT;
goto done;
@ -1123,11 +1107,9 @@ int drm_mapbufs(DRM_IOCTL_ARGS)
}
done:
request.count = dma->buf_count;
request->count = dma->buf_count;
DRM_DEBUG( "%d buffers, retcode = %d\n", request.count, retcode );
DRM_DEBUG( "%d buffers, retcode = %d\n", request->count, retcode );
DRM_COPY_TO_USER_IOCTL((drm_buf_map_t *)data, request, sizeof(request));
return DRM_ERR(retcode);
return retcode;
}

View File

@ -1,6 +1,3 @@
/* drm_context.h -- IOCTLs for generic contexts -*- linux-c -*-
* Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
*/
/*-
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
@ -31,6 +28,10 @@
*
*/
/** @file drm_context.c
* Implementation of the context management ioctls.
*/
#include "drmP.h"
/* ================================================================
@ -109,7 +110,7 @@ int drm_ctxbitmap_init(drm_device_t *dev)
dev->ctx_bitmap = malloc(PAGE_SIZE, M_DRM, M_NOWAIT | M_ZERO);
if ( dev->ctx_bitmap == NULL ) {
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
return ENOMEM;
}
dev->context_sareas = NULL;
dev->max_context = -1;
@ -136,48 +137,39 @@ void drm_ctxbitmap_cleanup(drm_device_t *dev)
* Per Context SAREA Support
*/
int drm_getsareactx( DRM_IOCTL_ARGS )
int drm_getsareactx( drm_device_t *dev, void *data, struct drm_file *file_priv )
{
DRM_DEVICE;
drm_ctx_priv_map_t request;
drm_ctx_priv_map_t *request = data;
drm_local_map_t *map;
DRM_COPY_FROM_USER_IOCTL( request, (drm_ctx_priv_map_t *)data,
sizeof(request) );
DRM_LOCK();
if (dev->max_context < 0 || request.ctx_id >= (unsigned) dev->max_context) {
if (dev->max_context < 0 ||
request->ctx_id >= (unsigned) dev->max_context) {
DRM_UNLOCK();
return DRM_ERR(EINVAL);
return EINVAL;
}
map = dev->context_sareas[request.ctx_id];
map = dev->context_sareas[request->ctx_id];
DRM_UNLOCK();
request.handle = map->handle;
DRM_COPY_TO_USER_IOCTL( (drm_ctx_priv_map_t *)data, request, sizeof(request) );
request->handle = map->handle;
return 0;
}
int drm_setsareactx( DRM_IOCTL_ARGS )
int drm_setsareactx(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_ctx_priv_map_t request;
drm_ctx_priv_map_t *request = data;
drm_local_map_t *map = NULL;
DRM_COPY_FROM_USER_IOCTL( request, (drm_ctx_priv_map_t *)data,
sizeof(request) );
DRM_LOCK();
TAILQ_FOREACH(map, &dev->maplist, link) {
if (map->handle == request.handle) {
if (map->handle == request->handle) {
if (dev->max_context < 0)
goto bad;
if (request.ctx_id >= (unsigned) dev->max_context)
if (request->ctx_id >= (unsigned) dev->max_context)
goto bad;
dev->context_sareas[request.ctx_id] = map;
dev->context_sareas[request->ctx_id] = map;
DRM_UNLOCK();
return 0;
}
@ -185,7 +177,7 @@ int drm_setsareactx( DRM_IOCTL_ARGS )
bad:
DRM_UNLOCK();
return DRM_ERR(EINVAL);
return EINVAL;
}
/* ================================================================
@ -196,7 +188,7 @@ int drm_context_switch(drm_device_t *dev, int old, int new)
{
if ( test_and_set_bit( 0, &dev->context_flag ) ) {
DRM_ERROR( "Reentering -- FIXME\n" );
return DRM_ERR(EBUSY);
return EBUSY;
}
DRM_DEBUG( "Context switch from %d to %d\n", old, new );
@ -225,120 +217,98 @@ int drm_context_switch_complete(drm_device_t *dev, int new)
return 0;
}
int drm_resctx(DRM_IOCTL_ARGS)
int drm_resctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
drm_ctx_res_t res;
drm_ctx_res_t *res = data;
drm_ctx_t ctx;
int i;
DRM_COPY_FROM_USER_IOCTL( res, (drm_ctx_res_t *)data, sizeof(res) );
if ( res.count >= DRM_RESERVED_CONTEXTS ) {
if ( res->count >= DRM_RESERVED_CONTEXTS ) {
bzero(&ctx, sizeof(ctx));
for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
ctx.handle = i;
if ( DRM_COPY_TO_USER( &res.contexts[i],
if ( DRM_COPY_TO_USER( &res->contexts[i],
&ctx, sizeof(ctx) ) )
return DRM_ERR(EFAULT);
return EFAULT;
}
}
res.count = DRM_RESERVED_CONTEXTS;
DRM_COPY_TO_USER_IOCTL( (drm_ctx_res_t *)data, res, sizeof(res) );
res->count = DRM_RESERVED_CONTEXTS;
return 0;
}
int drm_addctx(DRM_IOCTL_ARGS)
int drm_addctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_ctx_t ctx;
drm_ctx_t *ctx = data;
DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
ctx.handle = drm_ctxbitmap_next(dev);
if ( ctx.handle == DRM_KERNEL_CONTEXT ) {
ctx->handle = drm_ctxbitmap_next(dev);
if ( ctx->handle == DRM_KERNEL_CONTEXT ) {
/* Skip kernel's context and get a new one. */
ctx.handle = drm_ctxbitmap_next(dev);
ctx->handle = drm_ctxbitmap_next(dev);
}
DRM_DEBUG( "%d\n", ctx.handle );
if ( ctx.handle == -1 ) {
DRM_DEBUG( "%d\n", ctx->handle );
if ( ctx->handle == -1 ) {
DRM_DEBUG( "Not enough free contexts.\n" );
/* Should this return -EBUSY instead? */
return DRM_ERR(ENOMEM);
return ENOMEM;
}
if (dev->driver.context_ctor && ctx.handle != DRM_KERNEL_CONTEXT) {
if (dev->driver.context_ctor && ctx->handle != DRM_KERNEL_CONTEXT) {
DRM_LOCK();
dev->driver.context_ctor(dev, ctx.handle);
dev->driver.context_ctor(dev, ctx->handle);
DRM_UNLOCK();
}
DRM_COPY_TO_USER_IOCTL( (drm_ctx_t *)data, ctx, sizeof(ctx) );
return 0;
}
int drm_modctx(DRM_IOCTL_ARGS)
int drm_modctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
/* This does nothing */
return 0;
}
int drm_getctx(DRM_IOCTL_ARGS)
int drm_getctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
drm_ctx_t ctx;
DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
drm_ctx_t *ctx = data;
/* This is 0, because we don't handle any context flags */
ctx.flags = 0;
DRM_COPY_TO_USER_IOCTL( (drm_ctx_t *)data, ctx, sizeof(ctx) );
ctx->flags = 0;
return 0;
}
int drm_switchctx(DRM_IOCTL_ARGS)
int drm_switchctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_ctx_t ctx;
drm_ctx_t *ctx = data;
DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
DRM_DEBUG( "%d\n", ctx.handle );
return drm_context_switch(dev, dev->last_context, ctx.handle);
DRM_DEBUG( "%d\n", ctx->handle );
return drm_context_switch(dev, dev->last_context, ctx->handle);
}
int drm_newctx(DRM_IOCTL_ARGS)
int drm_newctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_ctx_t ctx;
drm_ctx_t *ctx = data;
DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
DRM_DEBUG( "%d\n", ctx.handle );
drm_context_switch_complete(dev, ctx.handle);
DRM_DEBUG( "%d\n", ctx->handle );
drm_context_switch_complete(dev, ctx->handle);
return 0;
}
int drm_rmctx(DRM_IOCTL_ARGS)
int drm_rmctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_ctx_t ctx;
drm_ctx_t *ctx = data;
DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
DRM_DEBUG( "%d\n", ctx.handle );
if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
DRM_DEBUG( "%d\n", ctx->handle );
if ( ctx->handle != DRM_KERNEL_CONTEXT ) {
if (dev->driver.context_dtor) {
DRM_LOCK();
dev->driver.context_dtor(dev, ctx.handle);
dev->driver.context_dtor(dev, ctx->handle);
DRM_UNLOCK();
}
drm_ctxbitmap_free(dev, ctx.handle);
drm_ctxbitmap_free(dev, ctx->handle);
}
return 0;

View File

@ -1,6 +1,3 @@
/* drm_dma.c -- DMA IOCTL and function support -*- linux-c -*-
* Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
*/
/*-
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
@ -31,6 +28,14 @@
*
*/
/** @file drm_dma.c
* Support code for DMA buffer management.
*
* The implementation used to be significantly more complicated, but the
* complexity has been moved into the drivers as different buffer management
* schemes evolved.
*/
#include "drmP.h"
int drm_dma_setup(drm_device_t *dev)
@ -38,9 +43,9 @@ int drm_dma_setup(drm_device_t *dev)
dev->dma = malloc(sizeof(*dev->dma), M_DRM, M_NOWAIT | M_ZERO);
if (dev->dma == NULL)
return DRM_ERR(ENOMEM);
return ENOMEM;
DRM_SPININIT(dev->dma_lock, "drmdma");
DRM_SPININIT(&dev->dma_lock, "drmdma");
return 0;
}
@ -80,7 +85,7 @@ void drm_dma_takedown(drm_device_t *dev)
free(dma->pagelist, M_DRM);
free(dev->dma, M_DRM);
dev->dma = NULL;
DRM_SPINUNINIT(dev->dma_lock);
DRM_SPINUNINIT(&dev->dma_lock);
}
@ -89,18 +94,18 @@ void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf)
if (!buf) return;
buf->pending = 0;
buf->filp = NULL;
buf->file_priv= NULL;
buf->used = 0;
}
void drm_reclaim_buffers(drm_device_t *dev, DRMFILE filp)
void drm_reclaim_buffers(drm_device_t *dev, struct drm_file *file_priv)
{
drm_device_dma_t *dma = dev->dma;
int i;
if (!dma) return;
for (i = 0; i < dma->buf_count; i++) {
if (dma->buflist[i]->filp == filp) {
if (dma->buflist[i]->file_priv == file_priv) {
switch (dma->buflist[i]->list) {
case DRM_LIST_NONE:
drm_free_buffer(dev, dma->buflist[i]);
@ -117,12 +122,12 @@ void drm_reclaim_buffers(drm_device_t *dev, DRMFILE filp)
}
/* Call into the driver-specific DMA handler */
int drm_dma(DRM_IOCTL_ARGS)
int drm_dma(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
if (dev->driver.dma_ioctl) {
return dev->driver.dma_ioctl(kdev, cmd, data, flags, p, filp);
/* shared code returns -errno */
return -dev->driver.dma_ioctl(dev, data, file_priv);
} else {
DRM_DEBUG("DMA ioctl on driver with no dma handler\n");
return EINVAL;

View File

@ -1,6 +1,3 @@
/* drm_drawable.h -- IOCTLs for drawables -*- linux-c -*-
* Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
*/
/*-
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
@ -31,21 +28,123 @@
*
*/
/** @file drm_drawable.c
* This file implements ioctls to store information along with DRM drawables,
* such as the current set of cliprects for vblank-synced buffer swaps.
*/
#include "drmP.h"
int drm_adddraw(DRM_IOCTL_ARGS)
struct bsd_drm_drawable_info {
struct drm_drawable_info info;
int handle;
RB_ENTRY(bsd_drm_drawable_info) tree;
};
static int
drm_drawable_compare(struct bsd_drm_drawable_info *a,
struct bsd_drm_drawable_info *b)
{
drm_draw_t draw;
if (a->handle > b->handle)
return 1;
if (a->handle < b->handle)
return -1;
return 0;
}
draw.handle = 0; /* NOOP */
DRM_DEBUG("%d\n", draw.handle);
RB_GENERATE_STATIC(drawable_tree, bsd_drm_drawable_info, tree,
drm_drawable_compare);
DRM_COPY_TO_USER_IOCTL( (drm_draw_t *)data, draw, sizeof(draw) );
struct drm_drawable_info *
drm_get_drawable_info(drm_device_t *dev, int handle)
{
struct bsd_drm_drawable_info find, *result;
find.handle = handle;
result = RB_FIND(drawable_tree, &dev->drw_head, &find);
return &result->info;
}
int drm_adddraw(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
drm_draw_t *draw = data;
struct bsd_drm_drawable_info *info;
info = drm_calloc(1, sizeof(struct bsd_drm_drawable_info),
DRM_MEM_DRAWABLE);
if (info == NULL)
return ENOMEM;
info->handle = alloc_unr(dev->drw_unrhdr);
DRM_SPINLOCK(&dev->drw_lock);
RB_INSERT(drawable_tree, &dev->drw_head, info);
draw->handle = info->handle;
DRM_SPINUNLOCK(&dev->drw_lock);
DRM_DEBUG("%d\n", draw->handle);
return 0;
}
int drm_rmdraw(DRM_IOCTL_ARGS)
int drm_rmdraw(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
return 0; /* NOOP */
drm_draw_t *draw = (drm_draw_t *)data;
struct drm_drawable_info *info;
DRM_SPINLOCK(&dev->drw_lock);
info = drm_get_drawable_info(dev, draw->handle);
if (info != NULL) {
RB_REMOVE(drawable_tree, &dev->drw_head,
(struct bsd_drm_drawable_info *)info);
DRM_SPINUNLOCK(&dev->drw_lock);
free_unr(dev->drw_unrhdr, draw->handle);
drm_free(info, sizeof(struct bsd_drm_drawable_info),
DRM_MEM_DRAWABLE);
return 0;
} else {
DRM_SPINUNLOCK(&dev->drw_lock);
return EINVAL;
}
}
int drm_update_draw(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
struct drm_drawable_info *info;
struct drm_update_draw *update = (struct drm_update_draw *)data;
int ret;
info = drm_get_drawable_info(dev, update->handle);
if (info == NULL)
return EINVAL;
switch (update->type) {
case DRM_DRAWABLE_CLIPRECTS:
DRM_SPINLOCK(&dev->drw_lock);
if (update->num != info->num_rects) {
drm_free(info->rects,
sizeof(*info->rects) * info->num_rects,
DRM_MEM_DRAWABLE);
info->rects = NULL;
info->num_rects = 0;
}
if (update->num == 0) {
DRM_SPINUNLOCK(&dev->drw_lock);
return 0;
}
if (info->rects == NULL) {
info->rects = drm_alloc(sizeof(*info->rects) *
update->num, DRM_MEM_DRAWABLE);
if (info->rects == NULL)
return ENOMEM;
info->num_rects = update->num;
}
/* For some reason the pointer arg is unsigned long long. */
ret = copyin((void *)(intptr_t)update->data, info->rects,
sizeof(*info->rects) * info->num_rects);
DRM_SPINUNLOCK(&dev->drw_lock);
return ret;
default:
return EINVAL;
}
}

View File

@ -1,6 +1,3 @@
/* drm_drv.h -- Generic driver template -*- linux-c -*-
* Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
*/
/*-
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
@ -31,6 +28,13 @@
*
*/
/** @file drm_drv.c
* The catch-all file for DRM device support, including module setup/teardown,
* open/close, and ioctl dispatch.
*/
#include <sys/limits.h>
#include "drmP.h"
#include "drm.h"
#include "drm_sarea.h"
@ -64,63 +68,64 @@ MODULE_DEPEND(drm, mem, 1, 1, 1);
#endif /* __NetBSD__ || __OpenBSD__ */
static drm_ioctl_desc_t drm_ioctls[256] = {
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { drm_version, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { drm_getmap, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { drm_getclient, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { drm_getstats, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = { drm_setversion, DRM_MASTER|DRM_ROOT_ONLY },
DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0),
DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER|DRM_ROOT_ONLY),
[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { drm_rmmap_ioctl, DRM_AUTH },
DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
[DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { drm_getsareactx, DRM_AUTH },
DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { drm_getctx, DRM_AUTH },
[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { drm_resctx, DRM_AUTH },
DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
[DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { drm_lock, DRM_AUTH },
[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { drm_unlock, DRM_AUTH },
[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_noop, DRM_AUTH },
DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { drm_addbufs_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, DRM_AUTH|DRM_MASTER },
[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, DRM_AUTH },
[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { drm_mapbufs, DRM_AUTH },
[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, DRM_AUTH },
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { drm_dma, DRM_AUTH },
DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER),
DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma, DRM_AUTH),
[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info_ioctl, DRM_AUTH },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = { drm_wait_vblank, 0 },
DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_draw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
};
#ifdef __FreeBSD__
@ -198,6 +203,7 @@ int drm_attach(device_t nbdev, drm_pci_id_list_t *idlist)
"dri/card%d", unit);
#if __FreeBSD_version >= 500000
mtx_init(&dev->dev_lock, "drm device", NULL, MTX_DEF);
mtx_init(&dev->drw_lock, "drmdrw", NULL, MTX_DEF);
#endif
id_entry = drm_find_description(pci_get_vendor(dev->device),
@ -496,7 +502,7 @@ static int drm_lastclose(drm_device_t *dev)
drm_dma_takedown(dev);
if ( dev->lock.hw_lock ) {
dev->lock.hw_lock = NULL; /* SHM removed */
dev->lock.filp = NULL;
dev->lock.file_priv = NULL;
DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
}
@ -510,8 +516,11 @@ static int drm_load(drm_device_t *dev)
DRM_DEBUG( "\n" );
dev->irq = pci_get_irq(dev->device);
/* XXX Fix domain number (alpha hoses) */
#if defined(__FreeBSD__) && __FreeBSD_version >= 700053
dev->pci_domain = pci_get_domain(dev->device);
#else
dev->pci_domain = 0;
#endif
dev->pci_bus = pci_get_bus(dev->device);
dev->pci_slot = pci_get_slot(dev->device);
dev->pci_func = pci_get_function(dev->device);
@ -529,7 +538,9 @@ static int drm_load(drm_device_t *dev)
if (dev->driver.load != NULL) {
DRM_LOCK();
retcode = dev->driver.load(dev, dev->id_entry->driver_private);
/* Shared code returns -errno. */
retcode = -dev->driver.load(dev,
dev->id_entry->driver_private);
DRM_UNLOCK();
if (retcode != 0)
goto error;
@ -541,7 +552,7 @@ static int drm_load(drm_device_t *dev)
if (dev->driver.require_agp && dev->agp == NULL) {
DRM_ERROR("Card isn't AGP, or couldn't initialize "
"AGP.\n");
retcode = DRM_ERR(ENOMEM);
retcode = ENOMEM;
goto error;
}
if (dev->agp != NULL) {
@ -557,6 +568,12 @@ static int drm_load(drm_device_t *dev)
goto error;
}
dev->drw_unrhdr = new_unrhdr(1, INT_MAX, NULL);
if (dev->drw_unrhdr == NULL) {
DRM_ERROR("Couldn't allocate drawable number allocator\n");
goto error;
}
DRM_INFO("Initialized %s %d.%d.%d %s\n",
dev->driver.name,
dev->driver.major,
@ -628,6 +645,8 @@ static void drm_unload(drm_device_t *dev)
if (dev->driver.unload != NULL)
dev->driver.unload(dev);
delete_unrhdr(dev->drw_unrhdr);
drm_mem_uninit();
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
mtx_destroy(&dev->dev_lock);
@ -635,32 +654,27 @@ static void drm_unload(drm_device_t *dev)
}
int drm_version(DRM_IOCTL_ARGS)
int drm_version(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_version_t version;
drm_version_t *version = data;
int len;
DRM_COPY_FROM_USER_IOCTL( version, (drm_version_t *)data, sizeof(version) );
#define DRM_COPY( name, value ) \
len = strlen( value ); \
if ( len > name##_len ) len = name##_len; \
name##_len = strlen( value ); \
if ( len && name ) { \
if ( DRM_COPY_TO_USER( name, value, len ) ) \
return DRM_ERR(EFAULT); \
return EFAULT; \
}
version.version_major = dev->driver.major;
version.version_minor = dev->driver.minor;
version.version_patchlevel = dev->driver.patchlevel;
version->version_major = dev->driver.major;
version->version_minor = dev->driver.minor;
version->version_patchlevel = dev->driver.patchlevel;
DRM_COPY(version.name, dev->driver.name);
DRM_COPY(version.date, dev->driver.date);
DRM_COPY(version.desc, dev->driver.desc);
DRM_COPY_TO_USER_IOCTL( (drm_version_t *)data, version, sizeof(version) );
DRM_COPY(version->name, dev->driver.name);
DRM_COPY(version->date, dev->driver.date);
DRM_COPY(version->desc, dev->driver.desc);
return 0;
}
@ -692,24 +706,26 @@ int drm_open(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
{
drm_file_t *priv;
DRM_DEVICE;
drm_device_t *dev = drm_get_device_from_kdev(kdev);
drm_file_t *file_priv;
int retcode = 0;
DRMFILE filp = (void *)(uintptr_t)(DRM_CURRENTPID);
DRM_DEBUG( "open_count = %d\n", dev->open_count );
DRM_LOCK();
priv = drm_find_file_by_proc(dev, p);
if (!priv) {
file_priv = drm_find_file_by_proc(dev, p);
if (!file_priv) {
DRM_UNLOCK();
DRM_ERROR("can't find authenticator\n");
return EINVAL;
}
if (--file_priv->refs != 0)
goto done;
if (dev->driver.preclose != NULL)
dev->driver.preclose(dev, filp);
dev->driver.preclose(dev, file_priv);
/* ========================================================
* Begin inline drm_release
@ -724,12 +740,12 @@ int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
#endif
if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
&& dev->lock.filp == filp) {
&& dev->lock.file_priv == file_priv) {
DRM_DEBUG("Process %d dead, freeing lock for context %d\n",
DRM_CURRENTPID,
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
if (dev->driver.reclaim_buffers_locked != NULL)
dev->driver.reclaim_buffers_locked(dev, filp);
dev->driver.reclaim_buffers_locked(dev, file_priv);
drm_lock_free(dev, &dev->lock.hw_lock->lock,
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
@ -744,12 +760,12 @@ int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
for (;;) {
if ( !dev->lock.hw_lock ) {
/* Device has been unregistered */
retcode = DRM_ERR(EINTR);
retcode = EINTR;
break;
}
if (drm_lock_take(&dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT)) {
dev->lock.filp = filp;
dev->lock.file_priv = file_priv;
dev->lock.lock_time = jiffies;
atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
break; /* Got lock */
@ -766,14 +782,14 @@ int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
break;
}
if (retcode == 0) {
dev->driver.reclaim_buffers_locked(dev, filp);
dev->driver.reclaim_buffers_locked(dev, file_priv);
drm_lock_free(dev, &dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT);
}
}
if (dev->driver.use_dma && !dev->driver.reclaim_buffers_locked)
drm_reclaim_buffers(dev, filp);
drm_reclaim_buffers(dev, file_priv);
#if defined (__FreeBSD__) && (__FreeBSD_version >= 500000)
funsetown(&dev->buf_sigio);
@ -783,17 +799,16 @@ int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
dev->buf_pgid = 0;
#endif /* __NetBSD__ || __OpenBSD__ */
if (--priv->refs == 0) {
if (dev->driver.postclose != NULL)
dev->driver.postclose(dev, priv);
TAILQ_REMOVE(&dev->files, priv, link);
free(priv, M_DRM);
}
if (dev->driver.postclose != NULL)
dev->driver.postclose(dev, file_priv);
TAILQ_REMOVE(&dev->files, file_priv, link);
free(file_priv, M_DRM);
/* ========================================================
* End inline drm_release
*/
done:
atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
#ifdef __FreeBSD__
device_unbusy(dev->device);
@ -812,32 +827,33 @@ int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags,
DRM_STRUCTPROC *p)
{
DRM_DEVICE;
drm_device_t *dev = drm_get_device_from_kdev(kdev);
int retcode = 0;
drm_ioctl_desc_t *ioctl;
int (*func)(DRM_IOCTL_ARGS);
int (*func)(drm_device_t *dev, void *data, struct drm_file *file_priv);
int nr = DRM_IOCTL_NR(cmd);
int is_driver_ioctl = 0;
drm_file_t *priv;
DRMFILE filp = (DRMFILE)(uintptr_t)DRM_CURRENTPID;
drm_file_t *file_priv;
DRM_LOCK();
priv = drm_find_file_by_proc(dev, p);
file_priv = drm_find_file_by_proc(dev, p);
DRM_UNLOCK();
if (priv == NULL) {
if (file_priv == NULL) {
DRM_ERROR("can't find authenticator\n");
return EINVAL;
}
atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
++priv->ioctl_count;
++file_priv->ioctl_count;
#ifdef __FreeBSD__
DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
DRM_CURRENTPID, cmd, nr, (long)dev->device, priv->authenticated );
DRM_CURRENTPID, cmd, nr, (long)dev->device,
file_priv->authenticated );
#elif defined(__NetBSD__) || defined(__OpenBSD__)
DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
DRM_CURRENTPID, cmd, nr, (long)&dev->device, priv->authenticated );
DRM_CURRENTPID, cmd, nr, (long)&dev->device,
file_priv->authenticated );
#endif
switch (cmd) {
@ -892,24 +908,25 @@ int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags,
DRM_DEBUG( "no function\n" );
return EINVAL;
}
/* ioctl->master check should be against something in the filp set up
* for the first opener, but it doesn't matter yet.
*/
if (((ioctl->flags & DRM_ROOT_ONLY) && !DRM_SUSER(p)) ||
((ioctl->flags & DRM_AUTH) && !priv->authenticated) ||
((ioctl->flags & DRM_MASTER) && !priv->master))
((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
((ioctl->flags & DRM_MASTER) && !file_priv->master))
return EACCES;
if (is_driver_ioctl)
if (is_driver_ioctl) {
DRM_LOCK();
retcode = func(kdev, cmd, data, flags, p, filp);
if (is_driver_ioctl)
/* shared code returns -errno */
retcode = -func(dev, data, file_priv);
DRM_UNLOCK();
} else {
retcode = func(dev, data, file_priv);
}
if (retcode != 0)
DRM_DEBUG(" returning %d\n", retcode);
return DRM_ERR(retcode);
return retcode;
}
drm_local_map_t *drm_getsarea(drm_device_t *dev)

View File

@ -1,6 +1,3 @@
/* drm_fops.h -- File operations for DRM -*- linux-c -*-
* Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com
*/
/*-
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
@ -32,6 +29,11 @@
*
*/
/** @file drm_fops.c
* Support code for dealing with the file privates associated with each
* open of the DRM device.
*/
#include "drmP.h"
drm_file_t *drm_find_file_by_proc(drm_device_t *dev, DRM_STRUCTPROC *p)
@ -75,7 +77,7 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
priv = malloc(sizeof(*priv), M_DRM, M_NOWAIT | M_ZERO);
if (priv == NULL) {
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
return ENOMEM;
}
#if __FreeBSD_version >= 500000
priv->uid = p->td_ucred->cr_svuid;
@ -93,7 +95,8 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
priv->authenticated = DRM_SUSER(p);
if (dev->driver.open) {
retcode = dev->driver.open(dev, priv);
/* shared code returns -errno */
retcode = -dev->driver.open(dev, priv);
if (retcode != 0) {
free(priv, M_DRM);
DRM_UNLOCK();

View File

@ -1,6 +1,3 @@
/* drm_ioctl.h -- IOCTL processing for DRM -*- linux-c -*-
* Created: Fri Jan 8 09:01:26 1999 by faith@valinux.com
*/
/*-
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
@ -31,6 +28,11 @@
*
*/
/** @file drm_ioctl.c
* Varios minor DRM ioctls not applicable to other files, such as versioning
* information and reporting DRM information to userland.
*/
#include "drmP.h"
/*
@ -39,20 +41,15 @@
* before setunique has been called. The format for the bus-specific part of
* the unique is not defined for any other bus.
*/
int drm_getunique(DRM_IOCTL_ARGS)
int drm_getunique(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_unique_t u;
drm_unique_t *u = data;
DRM_COPY_FROM_USER_IOCTL( u, (drm_unique_t *)data, sizeof(u) );
if (u.unique_len >= dev->unique_len) {
if (DRM_COPY_TO_USER(u.unique, dev->unique, dev->unique_len))
return DRM_ERR(EFAULT);
if (u->unique_len >= dev->unique_len) {
if (DRM_COPY_TO_USER(u->unique, dev->unique, dev->unique_len))
return EFAULT;
}
u.unique_len = dev->unique_len;
DRM_COPY_TO_USER_IOCTL( (drm_unique_t *)data, u, sizeof(u) );
u->unique_len = dev->unique_len;
return 0;
}
@ -60,28 +57,25 @@ int drm_getunique(DRM_IOCTL_ARGS)
/* Deprecated in DRM version 1.1, and will return EBUSY when setversion has
* requested version 1.1 or greater.
*/
int drm_setunique(DRM_IOCTL_ARGS)
int drm_setunique(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_unique_t u;
drm_unique_t *u = data;
int domain, bus, slot, func, ret;
char *busid;
DRM_COPY_FROM_USER_IOCTL( u, (drm_unique_t *)data, sizeof(u) );
/* Check and copy in the submitted Bus ID */
if (!u.unique_len || u.unique_len > 1024)
return DRM_ERR(EINVAL);
if (!u->unique_len || u->unique_len > 1024)
return EINVAL;
busid = malloc(u.unique_len + 1, M_DRM, M_WAITOK);
busid = malloc(u->unique_len + 1, M_DRM, M_WAITOK);
if (busid == NULL)
return DRM_ERR(ENOMEM);
return ENOMEM;
if (DRM_COPY_FROM_USER(busid, u.unique, u.unique_len)) {
if (DRM_COPY_FROM_USER(busid, u->unique, u->unique_len)) {
free(busid, M_DRM);
return DRM_ERR(EFAULT);
return EFAULT;
}
busid[u.unique_len] = '\0';
busid[u->unique_len] = '\0';
/* Return error if the busid submitted doesn't match the device's actual
* busid.
@ -89,7 +83,7 @@ int drm_setunique(DRM_IOCTL_ARGS)
ret = sscanf(busid, "PCI:%d:%d:%d", &bus, &slot, &func);
if (ret != 3) {
free(busid, M_DRM);
return DRM_ERR(EINVAL);
return EINVAL;
}
domain = bus >> 8;
bus &= 0xff;
@ -99,17 +93,17 @@ int drm_setunique(DRM_IOCTL_ARGS)
(slot != dev->pci_slot) ||
(func != dev->pci_func)) {
free(busid, M_DRM);
return DRM_ERR(EINVAL);
return EINVAL;
}
/* Actually set the device's busid now. */
DRM_LOCK();
if (dev->unique_len || dev->unique) {
DRM_UNLOCK();
return DRM_ERR(EBUSY);
return EBUSY;
}
dev->unique_len = u.unique_len;
dev->unique_len = u->unique_len;
dev->unique = busid;
DRM_UNLOCK();
@ -143,32 +137,29 @@ drm_set_busid(drm_device_t *dev)
return 0;
}
int drm_getmap(DRM_IOCTL_ARGS)
int drm_getmap(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_map_t map;
drm_map_t *map = data;
drm_local_map_t *mapinlist;
int idx;
int i = 0;
DRM_COPY_FROM_USER_IOCTL( map, (drm_map_t *)data, sizeof(map) );
idx = map.offset;
idx = map->offset;
DRM_LOCK();
if (idx < 0) {
DRM_UNLOCK();
return DRM_ERR(EINVAL);
return EINVAL;
}
TAILQ_FOREACH(mapinlist, &dev->maplist, link) {
if (i==idx) {
map.offset = mapinlist->offset;
map.size = mapinlist->size;
map.type = mapinlist->type;
map.flags = mapinlist->flags;
map.handle = mapinlist->handle;
map.mtrr = mapinlist->mtrr;
map->offset = mapinlist->offset;
map->size = mapinlist->size;
map->type = mapinlist->type;
map->flags = mapinlist->flags;
map->handle = mapinlist->handle;
map->mtrr = mapinlist->mtrr;
break;
}
i++;
@ -179,100 +170,89 @@ int drm_getmap(DRM_IOCTL_ARGS)
if (mapinlist == NULL)
return EINVAL;
DRM_COPY_TO_USER_IOCTL( (drm_map_t *)data, map, sizeof(map) );
return 0;
}
int drm_getclient(DRM_IOCTL_ARGS)
int drm_getclient(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_client_t client;
drm_client_t *client = data;
drm_file_t *pt;
int idx;
int i = 0;
DRM_COPY_FROM_USER_IOCTL( client, (drm_client_t *)data, sizeof(client) );
idx = client.idx;
idx = client->idx;
DRM_LOCK();
TAILQ_FOREACH(pt, &dev->files, link) {
if (i==idx)
{
client.auth = pt->authenticated;
client.pid = pt->pid;
client.uid = pt->uid;
client.magic = pt->magic;
client.iocs = pt->ioctl_count;
client->auth = pt->authenticated;
client->pid = pt->pid;
client->uid = pt->uid;
client->magic = pt->magic;
client->iocs = pt->ioctl_count;
DRM_UNLOCK();
*(drm_client_t *)data = client;
return 0;
}
i++;
}
DRM_UNLOCK();
DRM_COPY_TO_USER_IOCTL( (drm_client_t *)data, client, sizeof(client) );
return 0;
return EINVAL;
}
int drm_getstats(DRM_IOCTL_ARGS)
int drm_getstats(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_stats_t stats;
drm_stats_t *stats = data;
int i;
memset(&stats, 0, sizeof(stats));
memset(stats, 0, sizeof(drm_stats_t));
DRM_LOCK();
for (i = 0; i < dev->counters; i++) {
if (dev->types[i] == _DRM_STAT_LOCK)
stats.data[i].value
stats->data[i].value
= (dev->lock.hw_lock
? dev->lock.hw_lock->lock : 0);
else
stats.data[i].value = atomic_read(&dev->counts[i]);
stats.data[i].type = dev->types[i];
stats->data[i].value = atomic_read(&dev->counts[i]);
stats->data[i].type = dev->types[i];
}
stats.count = dev->counters;
stats->count = dev->counters;
DRM_UNLOCK();
DRM_COPY_TO_USER_IOCTL( (drm_stats_t *)data, stats, sizeof(stats) );
return 0;
}
#define DRM_IF_MAJOR 1
#define DRM_IF_MINOR 2
int drm_setversion(DRM_IOCTL_ARGS)
int drm_setversion(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_set_version_t sv;
drm_set_version_t retv;
drm_set_version_t *sv = data;
drm_set_version_t ver;
int if_version;
DRM_COPY_FROM_USER_IOCTL(sv, (drm_set_version_t *)data, sizeof(sv));
/* Save the incoming data, and set the response before continuing
* any further.
*/
ver = *sv;
sv->drm_di_major = DRM_IF_MAJOR;
sv->drm_di_minor = DRM_IF_MINOR;
sv->drm_dd_major = dev->driver.major;
sv->drm_dd_minor = dev->driver.minor;
retv.drm_di_major = DRM_IF_MAJOR;
retv.drm_di_minor = DRM_IF_MINOR;
retv.drm_dd_major = dev->driver.major;
retv.drm_dd_minor = dev->driver.minor;
DRM_COPY_TO_USER_IOCTL((drm_set_version_t *)data, retv, sizeof(sv));
if (sv.drm_di_major != -1) {
if (sv.drm_di_major != DRM_IF_MAJOR ||
sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
if (ver.drm_di_major != -1) {
if (ver.drm_di_major != DRM_IF_MAJOR ||
ver.drm_di_minor < 0 || ver.drm_di_minor > DRM_IF_MINOR) {
return EINVAL;
if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor);
}
if_version = DRM_IF_VERSION(ver.drm_di_major,
ver.drm_dd_minor);
dev->if_version = DRM_MAX(if_version, dev->if_version);
if (sv.drm_di_minor >= 1) {
if (ver.drm_di_minor >= 1) {
/*
* Version 1.1 includes tying of DRM to specific device
*/
@ -280,16 +260,20 @@ int drm_setversion(DRM_IOCTL_ARGS)
}
}
if (sv.drm_dd_major != -1) {
if (sv.drm_dd_major != dev->driver.major ||
sv.drm_dd_minor < 0 || sv.drm_dd_minor > dev->driver.minor)
if (ver.drm_dd_major != -1) {
if (ver.drm_dd_major != dev->driver.major ||
ver.drm_dd_minor < 0 ||
ver.drm_dd_minor > dev->driver.minor)
{
return EINVAL;
}
}
return 0;
}
int drm_noop(DRM_IOCTL_ARGS)
int drm_noop(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEBUG("\n");
return 0;

View File

@ -1,6 +1,3 @@
/* drm_irq.c -- IRQ IOCTL and function support
* Created: Fri Oct 18 2003 by anholt@FreeBSD.org
*/
/*-
* Copyright 2003 Eric Anholt
* All Rights Reserved.
@ -28,28 +25,30 @@
*
*/
/** @file drm_irq.c
* Support code for handling setup/teardown of interrupt handlers and
* handing interrupt handlers off to the drivers.
*/
#include "drmP.h"
#include "drm.h"
int drm_irq_by_busid(DRM_IOCTL_ARGS)
static void drm_locked_task(void *context, int pending __unused);
int drm_irq_by_busid(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_irq_busid_t irq;
drm_irq_busid_t *irq = data;
DRM_COPY_FROM_USER_IOCTL(irq, (drm_irq_busid_t *)data, sizeof(irq));
if ((irq.busnum >> 8) != dev->pci_domain ||
(irq.busnum & 0xff) != dev->pci_bus ||
irq.devnum != dev->pci_slot ||
irq.funcnum != dev->pci_func)
if ((irq->busnum >> 8) != dev->pci_domain ||
(irq->busnum & 0xff) != dev->pci_bus ||
irq->devnum != dev->pci_slot ||
irq->funcnum != dev->pci_func)
return EINVAL;
irq.irq = dev->irq;
irq->irq = dev->irq;
DRM_DEBUG("%d:%d:%d => IRQ %d\n",
irq.busnum, irq.devnum, irq.funcnum, irq.irq);
DRM_COPY_TO_USER_IOCTL( (drm_irq_busid_t *)data, irq, sizeof(irq) );
irq->busnum, irq->devnum, irq->funcnum, irq->irq);
return 0;
}
@ -74,20 +73,20 @@ int drm_irq_install(drm_device_t *dev)
#endif
if (dev->irq == 0 || dev->dev_private == NULL)
return DRM_ERR(EINVAL);
return EINVAL;
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
DRM_LOCK();
if (dev->irq_enabled) {
DRM_UNLOCK();
return DRM_ERR(EBUSY);
return EBUSY;
}
dev->irq_enabled = 1;
dev->context_flag = 0;
DRM_SPININIT(dev->irq_lock, "DRM IRQ lock");
DRM_SPININIT(&dev->irq_lock, "DRM IRQ lock");
/* Before installing handler */
dev->driver.irq_preinstall(dev);
@ -131,6 +130,7 @@ int drm_irq_install(drm_device_t *dev)
dev->driver.irq_postinstall(dev);
DRM_UNLOCK();
TASK_INIT(&dev->locked_task, 0, drm_locked_task, dev);
return 0;
err:
DRM_LOCK();
@ -142,7 +142,7 @@ err:
dev->irqrid = 0;
}
#endif
DRM_SPINUNINIT(dev->irq_lock);
DRM_SPINUNINIT(&dev->irq_lock);
DRM_UNLOCK();
return retcode;
}
@ -154,7 +154,7 @@ int drm_irq_uninstall(drm_device_t *dev)
#endif
if (!dev->irq_enabled)
return DRM_ERR(EINVAL);
return EINVAL;
dev->irq_enabled = 0;
#ifdef __FreeBSD__
@ -174,20 +174,17 @@ int drm_irq_uninstall(drm_device_t *dev)
#elif defined(__NetBSD__) || defined(__OpenBSD__)
pci_intr_disestablish(&dev->pa.pa_pc, dev->irqh);
#endif
DRM_SPINUNINIT(dev->irq_lock);
DRM_SPINUNINIT(&dev->irq_lock);
return 0;
}
int drm_control(DRM_IOCTL_ARGS)
int drm_control(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_control_t ctl;
drm_control_t *ctl = data;
int err;
DRM_COPY_FROM_USER_IOCTL( ctl, (drm_control_t *) data, sizeof(ctl) );
switch ( ctl.func ) {
switch ( ctl->func ) {
case DRM_INST_HANDLER:
/* Handle drivers whose DRM used to require IRQ setup but the
* no longer does.
@ -195,8 +192,8 @@ int drm_control(DRM_IOCTL_ARGS)
if (!dev->driver.use_irq)
return 0;
if (dev->if_version < DRM_IF_VERSION(1, 2) &&
ctl.irq != dev->irq)
return DRM_ERR(EINVAL);
ctl->irq != dev->irq)
return EINVAL;
return drm_irq_install(dev);
case DRM_UNINST_HANDLER:
if (!dev->driver.use_irq)
@ -206,29 +203,25 @@ int drm_control(DRM_IOCTL_ARGS)
DRM_UNLOCK();
return err;
default:
return DRM_ERR(EINVAL);
return EINVAL;
}
}
int drm_wait_vblank(DRM_IOCTL_ARGS)
int drm_wait_vblank(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_wait_vblank_t vblwait;
drm_wait_vblank_t *vblwait = data;
struct timeval now;
int ret;
int ret, flags;
if (!dev->irq_enabled)
return DRM_ERR(EINVAL);
return EINVAL;
DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
sizeof(vblwait) );
if (vblwait.request.type & _DRM_VBLANK_RELATIVE) {
vblwait.request.sequence += atomic_read(&dev->vbl_received);
vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
if (vblwait->request.type & _DRM_VBLANK_RELATIVE) {
vblwait->request.sequence += atomic_read(&dev->vbl_received);
vblwait->request.type &= ~_DRM_VBLANK_RELATIVE;
}
flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
if (flags & _DRM_VBLANK_SIGNAL) {
#if 0 /* disabled */
drm_vbl_sig_t *vbl_sig = malloc(sizeof(drm_vbl_sig_t), M_DRM,
@ -236,11 +229,11 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
if (vbl_sig == NULL)
return ENOMEM;
vbl_sig->sequence = vblwait.request.sequence;
vbl_sig->signo = vblwait.request.signal;
vbl_sig->sequence = vblwait->request.sequence;
vbl_sig->signo = vblwait->request.signal;
vbl_sig->pid = DRM_CURRENTPID;
vblwait.reply.sequence = atomic_read(&dev->vbl_received);
vblwait->reply.sequence = atomic_read(&dev->vbl_received);
DRM_SPINLOCK(&dev->irq_lock);
TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link);
@ -250,17 +243,16 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
ret = EINVAL;
} else {
DRM_LOCK();
ret = dev->driver.vblank_wait(dev, &vblwait.request.sequence);
/* shared code returns -errno */
ret = -dev->driver.vblank_wait(dev,
&vblwait->request.sequence);
DRM_UNLOCK();
microtime(&now);
vblwait.reply.tval_sec = now.tv_sec;
vblwait.reply.tval_usec = now.tv_usec;
vblwait->reply.tval_sec = now.tv_sec;
vblwait->reply.tval_usec = now.tv_usec;
}
DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
sizeof(vblwait) );
return ret;
}
@ -291,3 +283,45 @@ void drm_vbl_send_signals( drm_device_t *dev )
}
}
#endif
static void drm_locked_task(void *context, int pending __unused)
{
drm_device_t *dev = context;
DRM_LOCK();
for (;;) {
int ret;
if (drm_lock_take(&dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT))
{
dev->lock.file_priv = NULL; /* kernel owned */
dev->lock.lock_time = jiffies;
atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
break; /* Got lock */
}
/* Contention */
#if defined(__FreeBSD__) && __FreeBSD_version > 500000
ret = msleep((void *)&dev->lock.lock_queue, &dev->dev_lock,
PZERO | PCATCH, "drmlk2", 0);
#else
ret = tsleep((void *)&dev->lock.lock_queue, PZERO | PCATCH,
"drmlk2", 0);
#endif
if (ret != 0)
return;
}
DRM_UNLOCK();
dev->locked_task_call(dev);
drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
}
void
drm_locked_tasklet(drm_device_t *dev, void (*tasklet)(drm_device_t *dev))
{
dev->locked_task_call = tasklet;
taskqueue_enqueue(taskqueue_swi, &dev->locked_task);
}

View File

@ -1,6 +1,3 @@
/* lock.c -- IOCTLs for locking -*- linux-c -*-
* Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
*/
/*-
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
@ -31,6 +28,25 @@
*
*/
/** @file drm_lock.c
* Implementation of the ioctls and other support code for dealing with the
* hardware lock.
*
* The DRM hardware lock is a shared structure between the kernel and userland.
*
* On uncontended access where the new context was the last context, the
* client may take the lock without dropping down into the kernel, using atomic
* compare-and-set.
*
* If the client finds during compare-and-set that it was not the last owner
* of the lock, it calls the DRM lock ioctl, which may sleep waiting for the
* lock, and may have side-effects of kernel-managed context switching.
*
* When the client releases the lock, if the lock is marked as being contended
* by another client, then the DRM unlock ioctl is called so that the
* contending client may be woken up.
*/
#include "drmP.h"
int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
@ -66,7 +82,7 @@ int drm_lock_transfer(drm_device_t *dev,
{
unsigned int old, new;
dev->lock.filp = NULL;
dev->lock.file_priv = NULL;
do {
old = *lock;
new = context | _DRM_LOCK_HELD;
@ -80,7 +96,7 @@ int drm_lock_free(drm_device_t *dev,
{
unsigned int old, new;
dev->lock.filp = NULL;
dev->lock.file_priv = NULL;
do {
old = *lock;
new = 0;
@ -95,30 +111,28 @@ int drm_lock_free(drm_device_t *dev,
return 0;
}
int drm_lock(DRM_IOCTL_ARGS)
int drm_lock(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_lock_t lock;
drm_lock_t *lock = data;
int ret = 0;
DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t *)data, sizeof(lock));
if (lock.context == DRM_KERNEL_CONTEXT) {
if (lock->context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
DRM_CURRENTPID, lock.context);
DRM_CURRENTPID, lock->context);
return EINVAL;
}
DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
lock.context, DRM_CURRENTPID, dev->lock.hw_lock->lock, lock.flags);
lock->context, DRM_CURRENTPID, dev->lock.hw_lock->lock,
lock->flags);
if (dev->driver.use_dma_queue && lock.context < 0)
if (dev->driver.use_dma_queue && lock->context < 0)
return EINVAL;
DRM_LOCK();
for (;;) {
if (drm_lock_take(&dev->lock.hw_lock->lock, lock.context)) {
dev->lock.filp = (void *)(uintptr_t)DRM_CURRENTPID;
if (drm_lock_take(&dev->lock.hw_lock->lock, lock->context)) {
dev->lock.file_priv = file_priv;
dev->lock.lock_time = jiffies;
atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
break; /* Got lock */
@ -136,7 +150,7 @@ int drm_lock(DRM_IOCTL_ARGS)
break;
}
DRM_UNLOCK();
DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
DRM_DEBUG("%d %s\n", lock->context, ret ? "interrupted" : "has lock");
if (ret != 0)
return ret;
@ -144,24 +158,27 @@ int drm_lock(DRM_IOCTL_ARGS)
/* XXX: Add signal blocking here */
if (dev->driver.dma_quiescent != NULL &&
(lock.flags & _DRM_LOCK_QUIESCENT))
(lock->flags & _DRM_LOCK_QUIESCENT))
dev->driver.dma_quiescent(dev);
return 0;
}
int drm_unlock(DRM_IOCTL_ARGS)
int drm_unlock(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_lock_t lock;
drm_lock_t *lock = data;
DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t *)data, sizeof(lock));
if (lock.context == DRM_KERNEL_CONTEXT) {
if (lock->context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
DRM_CURRENTPID, lock.context);
DRM_CURRENTPID, lock->context);
return EINVAL;
}
/* Check that the context unlock being requested actually matches
* who currently holds the lock.
*/
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ||
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) != lock->context)
return EINVAL;
atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);

View File

@ -1,6 +1,3 @@
/* drm_memory.h -- Memory management wrappers for DRM -*- linux-c -*-
* Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com
*/
/*-
*Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
@ -31,6 +28,14 @@
*
*/
/** @file drm_memory.c
* Wrappers for kernel memory allocation routines, and MTRR management support.
*
* This file previously implemented a memory consumption tracking system using
* the "area" argument for various different types of allocations, but that
* has been stripped out for now.
*/
#include "drmP.h"
MALLOC_DEFINE(M_DRM, "drm", "DRM Data Structures");

View File

@ -1,10 +1,3 @@
/**
* \file drm_pci.h
* \brief PCI consistent, DMA-accessible memory functions.
*
* \author Eric Anholt <anholt@FreeBSD.org>
*/
/*-
* Copyright 2003 Eric Anholt.
* All Rights Reserved.
@ -28,6 +21,13 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* \file drm_pci.h
* \brief PCI consistent, DMA-accessible memory allocation.
*
* \author Eric Anholt <anholt@FreeBSD.org>
*/
#include "drmP.h"
/**********************************************************************/

1
bsd-core/drm_sarea.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/drm_sarea.h

View File

@ -1,5 +1,3 @@
/* drm_scatter.h -- IOCTLs to manage scatter/gather memory -*- linux-c -*-
* Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com */
/*-
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
@ -29,6 +27,13 @@
*
*/
/** @file drm_scatter.c
* Allocation of memory for scatter-gather mappings by the graphics chip.
*
* The memory allocated here is then made into an aperture in the card
* by drm_ati_pcigart_init().
*/
#include "drmP.h"
#define DEBUG_SCATTER 0
@ -40,28 +45,21 @@ void drm_sg_cleanup(drm_sg_mem_t *entry)
free(entry, M_DRM);
}
int drm_sg_alloc(DRM_IOCTL_ARGS)
int drm_sg_alloc(drm_device_t * dev, drm_scatter_gather_t * request)
{
DRM_DEVICE;
drm_scatter_gather_t request;
drm_sg_mem_t *entry;
unsigned long pages;
int i;
DRM_DEBUG( "%s\n", __FUNCTION__ );
if ( dev->sg )
return EINVAL;
DRM_COPY_FROM_USER_IOCTL(request, (drm_scatter_gather_t *)data,
sizeof(request) );
entry = malloc(sizeof(*entry), M_DRM, M_WAITOK | M_ZERO);
if ( !entry )
return ENOMEM;
pages = round_page(request.size) / PAGE_SIZE;
DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
pages = round_page(request->size) / PAGE_SIZE;
DRM_DEBUG( "sg size=%ld pages=%ld\n", request->size, pages );
entry->pages = pages;
@ -86,11 +84,7 @@ int drm_sg_alloc(DRM_IOCTL_ARGS)
DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle );
entry->virtual = (void *)entry->handle;
request.handle = entry->handle;
DRM_COPY_TO_USER_IOCTL( (drm_scatter_gather_t *)data,
request,
sizeof(request) );
request->handle = entry->handle;
DRM_LOCK();
if (dev->sg) {
@ -104,21 +98,28 @@ int drm_sg_alloc(DRM_IOCTL_ARGS)
return 0;
}
int drm_sg_free(DRM_IOCTL_ARGS)
int drm_sg_alloc_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_scatter_gather_t request;
drm_sg_mem_t *entry;
drm_scatter_gather_t *request = data;
int ret;
DRM_COPY_FROM_USER_IOCTL( request, (drm_scatter_gather_t *)data,
sizeof(request) );
DRM_DEBUG( "%s\n", __FUNCTION__ );
ret = drm_sg_alloc(dev, request);
return ret;
}
int drm_sg_free(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
drm_scatter_gather_t *request = data;
drm_sg_mem_t *entry;
DRM_LOCK();
entry = dev->sg;
dev->sg = NULL;
DRM_UNLOCK();
if ( !entry || entry->handle != request.handle )
if ( !entry || entry->handle != request->handle )
return EINVAL;
DRM_DEBUG( "sg free virtual = 0x%lx\n", entry->handle );

View File

@ -21,6 +21,11 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/** @file drm_sysctl.c
* Implementation of various sysctls for controlling DRM behavior and reporting
* debug information.
*/
#include "drmP.h"
#include "drm.h"

View File

@ -21,6 +21,10 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/** @file drm_vm.c
* Support code for mmaping of DRM maps.
*/
#include "drmP.h"
#include "drm.h"
@ -33,7 +37,7 @@ int drm_mmap(dev_t kdev, vm_offset_t offset, int prot)
paddr_t drm_mmap(dev_t kdev, off_t offset, int prot)
#endif
{
DRM_DEVICE;
drm_device_t *dev = drm_get_device_from_kdev(kdev);
drm_local_map_t *map;
drm_file_t *priv;
drm_map_type_t type;
@ -52,7 +56,7 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot)
}
if (!priv->authenticated)
return DRM_ERR(EACCES);
return EACCES;
if (dev->dma && offset >= 0 && offset < ptoa(dev->dma->page_count)) {
drm_device_dma_t *dma = dev->dma;

1
bsd-core/i915_dma.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/i915_dma.c

1
bsd-core/i915_drm.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/i915_drm.h

1
bsd-core/i915_drv.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/i915_drv.h

1
bsd-core/i915_irq.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/i915_irq.c

1
bsd-core/i915_mem.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/i915_mem.c

1
bsd-core/mach64_dma.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/mach64_dma.c

1
bsd-core/mach64_drm.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/mach64_drm.h

1
bsd-core/mach64_drv.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/mach64_drv.h

1
bsd-core/mach64_irq.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/mach64_irq.c

1
bsd-core/mach64_state.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/mach64_state.c

1
bsd-core/mga_dma.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/mga_dma.c

1
bsd-core/mga_drm.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/mga_drm.h

1
bsd-core/mga_drv.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/mga_drv.h

1
bsd-core/mga_irq.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/mga_irq.c

1
bsd-core/mga_state.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/mga_state.c

1
bsd-core/mga_ucode.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/mga_ucode.h

1
bsd-core/mga_warp.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/mga_warp.c

1
bsd-core/r128_cce.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/r128_cce.c

1
bsd-core/r128_drm.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/r128_drm.h

1
bsd-core/r128_drv.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/r128_drv.h

1
bsd-core/r128_irq.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/r128_irq.c

1
bsd-core/r128_state.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/r128_state.c

1
bsd-core/r300_cmdbuf.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/r300_cmdbuf.c

1
bsd-core/r300_reg.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/r300_reg.h

1
bsd-core/radeon_cp.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/radeon_cp.c

1
bsd-core/radeon_drm.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/radeon_drm.h

1
bsd-core/radeon_drv.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/radeon_drv.h

1
bsd-core/radeon_irq.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/radeon_irq.c

1
bsd-core/radeon_mem.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/radeon_mem.c

1
bsd-core/radeon_state.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/radeon_state.c

1
bsd-core/savage_bci.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/savage_bci.c

1
bsd-core/savage_drm.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/savage_drm.h

1
bsd-core/savage_drv.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/savage_drv.h

1
bsd-core/savage_state.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/savage_state.c

1
bsd-core/sis_drm.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/sis_drm.h

1
bsd-core/sis_drv.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/sis_drv.h

1
bsd-core/sis_ds.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/sis_ds.c

1
bsd-core/sis_ds.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/sis_ds.h

1
bsd-core/sis_mm.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/sis_mm.c

1
bsd-core/tdfx_drv.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/tdfx_drv.h

1
bsd-core/via_3d_reg.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/via_3d_reg.h

1
bsd-core/via_dma.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/via_dma.c

1
bsd-core/via_drm.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/via_drm.h

1
bsd-core/via_drv.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/via_drv.h

1
bsd-core/via_ds.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/via_ds.c

1
bsd-core/via_ds.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/via_ds.h

1
bsd-core/via_irq.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/via_irq.c

1
bsd-core/via_map.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/via_map.c

1
bsd-core/via_mm.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/via_mm.c

1
bsd-core/via_mm.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/via_mm.h

1
bsd-core/via_verifier.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/via_verifier.c

1
bsd-core/via_verifier.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/via_verifier.h

1
bsd-core/via_video.c Symbolic link
View File

@ -0,0 +1 @@
../shared-core/via_video.c

View File

@ -35,4 +35,9 @@ AC_SYS_LARGEFILE
pkgconfigdir=${libdir}/pkgconfig
AC_SUBST(pkgconfigdir)
AC_OUTPUT([Makefile libdrm/Makefile shared-core/Makefile libdrm.pc])
AC_OUTPUT([
Makefile
libdrm/Makefile
shared-core/Makefile
tests/Makefile
libdrm.pc])

View File

@ -49,7 +49,6 @@
#include <sys/mman.h>
#include <sys/time.h>
#include <stdarg.h>
#include "drm.h"
/* Not all systems have MAP_FAILED defined */
#ifndef MAP_FAILED
@ -2346,7 +2345,7 @@ int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data,
* DRM_FENCE_MASK_DRIVER
*/
int drmFenceCreate(int fd, unsigned flags, int class, unsigned type,
int drmFenceCreate(int fd, unsigned flags, int fence_class, unsigned type,
drmFence *fence)
{
drm_fence_arg_t arg;
@ -2354,12 +2353,12 @@ int drmFenceCreate(int fd, unsigned flags, int class, unsigned type,
memset(&arg, 0, sizeof(arg));
arg.flags = flags;
arg.type = type;
arg.class = class;
arg.op = drm_fence_create;
if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
arg.fence_class = fence_class;
if (ioctl(fd, DRM_IOCTL_FENCE_CREATE, &arg))
return -errno;
fence->handle = arg.handle;
fence->class = arg.class;
fence->fence_class = arg.fence_class;
fence->type = arg.type;
fence->flags = arg.flags;
fence->signaled = 0;
@ -2372,46 +2371,36 @@ int drmFenceCreate(int fd, unsigned flags, int class, unsigned type,
* DRM_FENCE_MASK_DRIVER
*/
int drmFenceBuffers(int fd, unsigned flags, drmFence *fence)
int drmFenceBuffers(int fd, unsigned flags, uint32_t fence_class, drmFence *fence)
{
drm_fence_arg_t arg;
memset(&arg, 0, sizeof(arg));
arg.flags = flags;
arg.op = drm_fence_buffers;
if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
arg.fence_class = fence_class;
if (ioctl(fd, DRM_IOCTL_FENCE_BUFFERS, &arg))
return -errno;
fence->handle = arg.handle;
fence->class = arg.class;
fence->fence_class = arg.fence_class;
fence->type = arg.type;
fence->flags = arg.flags;
fence->sequence = arg.sequence;
fence->signaled = 0;
return 0;
}
int drmFenceDestroy(int fd, const drmFence *fence)
{
drm_fence_arg_t arg;
memset(&arg, 0, sizeof(arg));
arg.handle = fence->handle;
arg.op = drm_fence_destroy;
if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
return -errno;
return 0;
}
int drmFenceReference(int fd, unsigned handle, drmFence *fence)
{
drm_fence_arg_t arg;
memset(&arg, 0, sizeof(arg));
arg.handle = handle;
arg.op = drm_fence_reference;
if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
if (ioctl(fd, DRM_IOCTL_FENCE_REFERENCE, &arg))
return -errno;
fence->handle = arg.handle;
fence->class = arg.class;
fence->fence_class = arg.fence_class;
fence->type = arg.type;
fence->flags = arg.flags;
fence->signaled = arg.signaled;
@ -2424,8 +2413,8 @@ int drmFenceUnreference(int fd, const drmFence *fence)
memset(&arg, 0, sizeof(arg));
arg.handle = fence->handle;
arg.op = drm_fence_unreference;
if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
if (ioctl(fd, DRM_IOCTL_FENCE_UNREFERENCE, &arg))
return -errno;
return 0;
}
@ -2437,10 +2426,10 @@ int drmFenceFlush(int fd, drmFence *fence, unsigned flush_type)
memset(&arg, 0, sizeof(arg));
arg.handle = fence->handle;
arg.type = flush_type;
arg.op = drm_fence_flush;
if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
if (ioctl(fd, DRM_IOCTL_FENCE_FLUSH, &arg))
return -errno;
fence->class = arg.class;
fence->fence_class = arg.fence_class;
fence->type = arg.type;
fence->signaled = arg.signaled;
return 0;
@ -2452,10 +2441,10 @@ int drmFenceUpdate(int fd, drmFence *fence)
memset(&arg, 0, sizeof(arg));
arg.handle = fence->handle;
arg.op = drm_fence_signaled;
if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
if (ioctl(fd, DRM_IOCTL_FENCE_SIGNALED, &arg))
return -errno;
fence->class = arg.class;
fence->fence_class = arg.fence_class;
fence->type = arg.type;
fence->signaled = arg.signaled;
return 0;
@ -2488,14 +2477,14 @@ int drmFenceEmit(int fd, unsigned flags, drmFence *fence, unsigned emit_type)
drm_fence_arg_t arg;
memset(&arg, 0, sizeof(arg));
arg.class = fence->class;
arg.fence_class = fence->fence_class;
arg.flags = flags;
arg.handle = fence->handle;
arg.type = emit_type;
arg.op = drm_fence_emit;
if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
if (ioctl(fd, DRM_IOCTL_FENCE_EMIT, &arg))
return -errno;
fence->class = arg.class;
fence->fence_class = arg.fence_class;
fence->type = arg.type;
fence->signaled = arg.signaled;
return 0;
@ -2526,159 +2515,21 @@ int drmFenceWait(int fd, unsigned flags, drmFence *fence, unsigned flush_type)
arg.handle = fence->handle;
arg.type = flush_type;
arg.flags = flags;
arg.op = drm_fence_wait;
do {
ret = ioctl(fd, DRM_IOCTL_FENCE, &arg);
ret = ioctl(fd, DRM_IOCTL_FENCE_WAIT, &arg);
} while (ret != 0 && errno == EAGAIN);
if (ret)
return -errno;
fence->class = arg.class;
fence->fence_class = arg.fence_class;
fence->type = arg.type;
fence->signaled = arg.signaled;
return 0;
}
static int drmAdjustListNodes(drmBOList *list)
{
drmBONode *node;
drmMMListHead *l;
int ret = 0;
while(list->numCurrent < list->numTarget) {
node = (drmBONode *) malloc(sizeof(*node));
if (!node) {
ret = -ENOMEM;
break;
}
list->numCurrent++;
DRMLISTADD(&node->head, &list->free);
}
while(list->numCurrent > list->numTarget) {
l = list->free.next;
if (l == &list->free)
break;
DRMLISTDEL(l);
node = DRMLISTENTRY(drmBONode, l, head);
free(node);
list->numCurrent--;
}
return ret;
}
void drmBOFreeList(drmBOList *list)
{
drmBONode *node;
drmMMListHead *l;
l = list->list.next;
while(l != &list->list) {
DRMLISTDEL(l);
node = DRMLISTENTRY(drmBONode, l, head);
free(node);
l = list->list.next;
list->numCurrent--;
list->numOnList--;
}
l = list->free.next;
while(l != &list->free) {
DRMLISTDEL(l);
node = DRMLISTENTRY(drmBONode, l, head);
free(node);
l = list->free.next;
list->numCurrent--;
}
}
int drmBOResetList(drmBOList *list)
{
drmMMListHead *l;
int ret;
ret = drmAdjustListNodes(list);
if (ret)
return ret;
l = list->list.next;
while (l != &list->list) {
DRMLISTDEL(l);
DRMLISTADD(l, &list->free);
list->numOnList--;
l = list->list.next;
}
return drmAdjustListNodes(list);
}
static drmBONode *drmAddListItem(drmBOList *list, drmBO *item,
unsigned long arg0,
unsigned long arg1)
{
drmBONode *node;
drmMMListHead *l;
l = list->free.next;
if (l == &list->free) {
node = (drmBONode *) malloc(sizeof(*node));
if (!node) {
return NULL;
}
list->numCurrent++;
}
else {
DRMLISTDEL(l);
node = DRMLISTENTRY(drmBONode, l, head);
}
node->buf = item;
node->arg0 = arg0;
node->arg1 = arg1;
DRMLISTADD(&node->head, &list->list);
list->numOnList++;
return node;
}
void *drmBOListIterator(drmBOList *list)
{
void *ret = list->list.next;
if (ret == &list->list)
return NULL;
return ret;
}
void *drmBOListNext(drmBOList *list, void *iterator)
{
void *ret;
drmMMListHead *l = (drmMMListHead *) iterator;
ret = l->next;
if (ret == &list->list)
return NULL;
return ret;
}
drmBO *drmBOListBuf(void *iterator)
{
drmBONode *node;
drmMMListHead *l = (drmMMListHead *) iterator;
node = DRMLISTENTRY(drmBONode, l, head);
return node->buf;
}
int drmBOCreateList(int numTarget, drmBOList *list)
{
DRMINITLISTHEAD(&list->list);
DRMINITLISTHEAD(&list->free);
list->numTarget = numTarget;
list->numCurrent = 0;
list->numOnList = 0;
return drmAdjustListNodes(list);
}
static void drmBOCopyReply(const drm_bo_arg_reply_t *rep, drmBO *buf)
static void drmBOCopyReply(const struct drm_bo_info_rep *rep, drmBO *buf)
{
buf->handle = rep->handle;
buf->flags = rep->flags;
@ -2690,16 +2541,21 @@ static void drmBOCopyReply(const drm_bo_arg_reply_t *rep, drmBO *buf)
buf->fenceFlags = rep->fence_flags;
buf->replyFlags = rep->rep_flags;
buf->pageAlignment = rep->page_alignment;
buf->tileInfo = rep->tile_info;
buf->hwTileStride = rep->hw_tile_stride;
buf->desiredTileStride = rep->desired_tile_stride;
}
int drmBOCreate(int fd, unsigned long start, unsigned long size,
unsigned pageAlignment, void *user_buffer, drm_bo_type_t type,
unsigned mask,
int drmBOCreate(int fd, unsigned long size,
unsigned pageAlignment, void *user_buffer,
uint64_t mask,
unsigned hint, drmBO *buf)
{
drm_bo_arg_t arg;
drm_bo_arg_request_t *req = &arg.d.req;
drm_bo_arg_reply_t *rep = &arg.d.rep;
struct drm_bo_create_arg arg;
struct drm_bo_create_req *req = &arg.d.req;
struct drm_bo_info_rep *rep = &arg.d.rep;
int ret;
memset(buf, 0, sizeof(*buf));
@ -2707,40 +2563,17 @@ int drmBOCreate(int fd, unsigned long start, unsigned long size,
req->mask = mask;
req->hint = hint;
req->size = size;
req->type = type;
req->page_alignment = pageAlignment;
req->buffer_start = (unsigned long) user_buffer;
buf->virtual = NULL;
switch(type) {
case drm_bo_type_dc:
req->buffer_start = start;
break;
case drm_bo_type_user:
req->buffer_start = (unsigned long) user_buffer;
buf->virtual = user_buffer;
break;
case drm_bo_type_fake:
req->buffer_start = start;
break;
default:
return -EINVAL;
}
req->op = drm_bo_create;
do {
ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
ret = ioctl(fd, DRM_IOCTL_BO_CREATE, &arg);
} while (ret != 0 && errno == EAGAIN);
if (ret)
return -errno;
if (!arg.handled) {
return -EFAULT;
}
if (rep->ret) {
fprintf(stderr, "Error %d\n", rep->ret);
return rep->ret;
}
drmBOCopyReply(rep, buf);
buf->mapVirtual = NULL;
@ -2749,56 +2582,19 @@ int drmBOCreate(int fd, unsigned long start, unsigned long size,
return 0;
}
int drmBODestroy(int fd, drmBO *buf)
{
drm_bo_arg_t arg;
drm_bo_arg_request_t *req = &arg.d.req;
drm_bo_arg_reply_t *rep = &arg.d.rep;
if (buf->mapVirtual && (buf->type != drm_bo_type_fake)) {
(void) drmUnmap(buf->mapVirtual, buf->start + buf->size);
buf->mapVirtual = NULL;
buf->virtual = NULL;
}
memset(&arg, 0, sizeof(arg));
req->handle = buf->handle;
req->op = drm_bo_destroy;
if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg))
return -errno;
if (!arg.handled) {
return -EFAULT;
}
if (rep->ret) {
return rep->ret;
}
buf->handle = 0;
return 0;
}
int drmBOReference(int fd, unsigned handle, drmBO *buf)
{
drm_bo_arg_t arg;
drm_bo_arg_request_t *req = &arg.d.req;
drm_bo_arg_reply_t *rep = &arg.d.rep;
struct drm_bo_reference_info_arg arg;
struct drm_bo_handle_arg *req = &arg.d.req;
struct drm_bo_info_rep *rep = &arg.d.rep;
memset(&arg, 0, sizeof(arg));
req->handle = handle;
req->op = drm_bo_reference;
if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg))
if (ioctl(fd, DRM_IOCTL_BO_REFERENCE, &arg))
return -errno;
if (!arg.handled) {
return -EFAULT;
}
if (rep->ret) {
return rep->ret;
}
drmBOCopyReply(rep, buf);
buf->type = drm_bo_type_dc;
buf->mapVirtual = NULL;
buf->mapCount = 0;
buf->virtual = NULL;
@ -2806,35 +2602,27 @@ int drmBOReference(int fd, unsigned handle, drmBO *buf)
return 0;
}
int drmBOUnReference(int fd, drmBO *buf)
int drmBOUnreference(int fd, drmBO *buf)
{
drm_bo_arg_t arg;
drm_bo_arg_request_t *req = &arg.d.req;
drm_bo_arg_reply_t *rep = &arg.d.rep;
struct drm_bo_handle_arg arg;
if (buf->mapVirtual && (buf->type != drm_bo_type_fake)) {
if (buf->mapVirtual) {
(void) munmap(buf->mapVirtual, buf->start + buf->size);
buf->mapVirtual = NULL;
buf->virtual = NULL;
}
memset(&arg, 0, sizeof(arg));
req->handle = buf->handle;
req->op = drm_bo_unreference;
arg.handle = buf->handle;
if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg))
if (ioctl(fd, DRM_IOCTL_BO_UNREFERENCE, &arg))
return -errno;
if (!arg.handled) {
return -EFAULT;
}
if (rep->ret) {
return rep->ret;
}
buf->handle = 0;
return 0;
}
/*
* Flags can be DRM_BO_FLAG_READ, DRM_BO_FLAG_WRITE or'ed together
* Hint currently be DRM_BO_HINT_DONT_BLOCK, which makes the
@ -2844,16 +2632,16 @@ int drmBOUnReference(int fd, drmBO *buf)
int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint,
void **address)
{
drm_bo_arg_t arg;
drm_bo_arg_request_t *req = &arg.d.req;
drm_bo_arg_reply_t *rep = &arg.d.rep;
struct drm_bo_map_wait_idle_arg arg;
struct drm_bo_info_req *req = &arg.d.req;
struct drm_bo_info_rep *rep = &arg.d.rep;
int ret = 0;
/*
* Make sure we have a virtual address of the buffer.
*/
if (!buf->virtual && buf->type != drm_bo_type_fake) {
if (!buf->virtual) {
drmAddress virtual;
virtual = mmap(0, buf->size + buf->start,
PROT_READ | PROT_WRITE, MAP_SHARED,
@ -2871,7 +2659,6 @@ int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint,
req->handle = buf->handle;
req->mask = mapFlags;
req->hint = mapHint;
req->op = drm_bo_map;
/*
* May hang if the buffer object is busy.
@ -2879,15 +2666,11 @@ int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint,
*/
do {
ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
ret = ioctl(fd, DRM_IOCTL_BO_MAP, &arg);
} while (ret != 0 && errno == EAGAIN);
if (ret)
return -errno;
if (!arg.handled)
return -EFAULT;
if (rep->ret)
return rep->ret;
drmBOCopyReply(rep, buf);
buf->mapFlags = mapFlags;
@ -2897,129 +2680,90 @@ int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint,
return 0;
}
int drmBOUnmap(int fd, drmBO *buf)
{
drm_bo_arg_t arg;
drm_bo_arg_request_t *req = &arg.d.req;
drm_bo_arg_reply_t *rep = &arg.d.rep;
struct drm_bo_handle_arg arg;
memset(&arg, 0, sizeof(arg));
req->handle = buf->handle;
req->op = drm_bo_unmap;
arg.handle = buf->handle;
if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg)) {
if (ioctl(fd, DRM_IOCTL_BO_UNMAP, &arg)) {
return -errno;
}
if (!arg.handled)
return -EFAULT;
if (rep->ret)
return rep->ret;
buf->mapCount--;
return 0;
}
int drmBOValidate(int fd, drmBO *buf, unsigned flags, unsigned mask,
unsigned hint)
int drmBOSetStatus(int fd, drmBO *buf,
uint64_t flags, uint64_t mask,
unsigned int hint,
unsigned int desired_tile_stride,
unsigned int tile_info)
{
drm_bo_arg_t arg;
drm_bo_arg_request_t *req = &arg.d.req;
drm_bo_arg_reply_t *rep = &arg.d.rep;
struct drm_bo_map_wait_idle_arg arg;
struct drm_bo_info_req *req = &arg.d.req;
struct drm_bo_info_rep *rep = &arg.d.rep;
int ret = 0;
memset(&arg, 0, sizeof(arg));
req->mask = mask;
req->flags = flags;
req->handle = buf->handle;
req->mask = flags;
req->hint = hint;
req->arg_handle = mask; /* Encode mask in the arg_handle field :/ */
req->op = drm_bo_validate;
req->desired_tile_stride = desired_tile_stride;
req->tile_info = tile_info;
do{
ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
do {
ret = ioctl(fd, DRM_IOCTL_BO_SETSTATUS, &arg);
} while (ret && errno == EAGAIN);
if (ret)
return -errno;
if (!arg.handled)
return -EFAULT;
if (rep->ret)
return rep->ret;
return -errno;
drmBOCopyReply(rep, buf);
return 0;
}
int drmBOFence(int fd, drmBO *buf, unsigned flags, unsigned fenceHandle)
{
drm_bo_arg_t arg;
drm_bo_arg_request_t *req = &arg.d.req;
drm_bo_arg_reply_t *rep = &arg.d.rep;
int ret = 0;
memset(&arg, 0, sizeof(arg));
req->handle = buf->handle;
req->mask = flags;
req->arg_handle = fenceHandle;
req->op = drm_bo_fence;
ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
if (ret)
return -errno;
if (!arg.handled)
return -EFAULT;
if (rep->ret)
return rep->ret;
return 0;
}
int drmBOInfo(int fd, drmBO *buf)
{
drm_bo_arg_t arg;
drm_bo_arg_request_t *req = &arg.d.req;
drm_bo_arg_reply_t *rep = &arg.d.rep;
struct drm_bo_reference_info_arg arg;
struct drm_bo_handle_arg *req = &arg.d.req;
struct drm_bo_info_rep *rep = &arg.d.rep;
int ret = 0;
memset(&arg, 0, sizeof(arg));
req->handle = buf->handle;
req->op = drm_bo_info;
ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
ret = ioctl(fd, DRM_IOCTL_BO_INFO, &arg);
if (ret)
return -errno;
if (!arg.handled)
return -EFAULT;
if (rep->ret)
return rep->ret;
drmBOCopyReply(rep, buf);
return 0;
}
int drmBOWaitIdle(int fd, drmBO *buf, unsigned hint)
{
drm_bo_arg_t arg;
drm_bo_arg_request_t *req = &arg.d.req;
drm_bo_arg_reply_t *rep = &arg.d.rep;
struct drm_bo_map_wait_idle_arg arg;
struct drm_bo_info_req *req = &arg.d.req;
struct drm_bo_info_rep *rep = &arg.d.rep;
int ret = 0;
if ((buf->flags & DRM_BO_FLAG_SHAREABLE) ||
(buf->replyFlags & DRM_BO_REP_BUSY)) {
memset(&arg, 0, sizeof(arg));
req->handle = buf->handle;
req->op = drm_bo_wait_idle;
req->hint = hint;
do {
ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
ret = ioctl(fd, DRM_IOCTL_BO_WAIT_IDLE, &arg);
} while (ret && errno == EAGAIN);
if (ret)
return -errno;
if (!arg.handled)
return -EFAULT;
if (rep->ret)
return rep->ret;
drmBOCopyReply(rep, buf);
}
return 0;
@ -3041,194 +2785,19 @@ int drmBOBusy(int fd, drmBO *buf, int *busy)
}
}
int drmAddValidateItem(drmBOList *list, drmBO *buf, unsigned flags,
unsigned mask,
int *newItem)
{
drmBONode *node, *cur;
drmMMListHead *l;
*newItem = 0;
cur = NULL;
for (l = list->list.next; l != &list->list; l = l->next) {
node = DRMLISTENTRY(drmBONode, l, head);
if (node->buf == buf) {
cur = node;
break;
}
}
if (!cur) {
cur = drmAddListItem(list, buf, flags, mask);
if (!cur) {
drmMsg("Out of memory creating validate list node.\n");
return -ENOMEM;
}
*newItem = 1;
cur->arg0 = flags;
cur->arg1 = mask;
}
else {
unsigned memMask = (cur->arg1 | mask) & DRM_BO_MASK_MEM;
unsigned memFlags = cur->arg0 & flags & memMask;
if (!memFlags) {
drmMsg("Incompatible memory location requests "
"on validate list.\n");
drmMsg("Previous flag: 0x%08lx, mask: 0x%08lx\n",
cur->arg0, cur->arg1);
drmMsg("Current flag: 0x%08lx, mask: 0x%08lx\n",
flags, mask);
return -EINVAL;
}
if (mask & cur->arg1 & ~DRM_BO_MASK_MEM & (cur->arg0 ^ flags)) {
drmMsg("Incompatible buffer flag requests "
"on validate list.\n");
drmMsg("Previous flag: 0x%08lx, mask: 0x%08lx\n",
cur->arg0, cur->arg1);
drmMsg("Current flag: 0x%08lx, mask: 0x%08lx\n",
flags, mask);
return -EINVAL;
}
cur->arg1 |= mask;
cur->arg0 = memFlags | ((cur->arg0 | flags) &
cur->arg1 & ~DRM_BO_MASK_MEM);
}
return 0;
}
int drmBOValidateList(int fd, drmBOList *list)
{
drmBONode *node;
drmMMListHead *l;
drm_bo_arg_t *arg, *first;
drm_bo_arg_request_t *req;
drm_bo_arg_reply_t *rep;
drm_u64_t *prevNext = NULL;
drmBO *buf;
int ret;
first = NULL;
for (l = list->list.next; l != &list->list; l = l->next) {
node = DRMLISTENTRY(drmBONode, l, head);
arg = &node->bo_arg;
req = &arg->d.req;
if (!first)
first = arg;
if (prevNext)
*prevNext = (unsigned long) arg;
memset(arg, 0, sizeof(*arg));
prevNext = &arg->next;
req->handle = node->buf->handle;
req->op = drm_bo_validate;
req->mask = node->arg0;
req->hint = 0;
req->arg_handle = node->arg1;
}
if (!first)
return 0;
do {
ret = ioctl(fd, DRM_IOCTL_BUFOBJ, first);
} while (ret && errno == EAGAIN);
if (ret)
return -errno;
for (l = list->list.next; l != &list->list; l = l->next) {
node = DRMLISTENTRY(drmBONode, l, head);
arg = &node->bo_arg;
rep = &arg->d.rep;
if (!arg->handled) {
drmMsg("Unhandled request\n");
return -EFAULT;
}
if (rep->ret)
return rep->ret;
buf = node->buf;
drmBOCopyReply(rep, buf);
}
return 0;
}
int drmBOFenceList(int fd, drmBOList *list, unsigned fenceHandle)
{
drmBONode *node;
drmMMListHead *l;
drm_bo_arg_t *arg, *first;
drm_bo_arg_request_t *req;
drm_bo_arg_reply_t *rep;
drm_u64_t *prevNext = NULL;
drmBO *buf;
unsigned fence_flags;
int ret;
first = NULL;
for (l = list->list.next; l != &list->list; l = l->next) {
node = DRMLISTENTRY(drmBONode, l, head);
arg = &node->bo_arg;
req = &arg->d.req;
if (!first)
first = arg;
if (prevNext)
*prevNext = (unsigned long) arg;
memset(arg, 0, sizeof(*arg));
prevNext = &arg->next;
req->handle = node->buf->handle;
req->op = drm_bo_fence;
req->mask = node->arg0;
req->arg_handle = fenceHandle;
}
if (!first)
return 0;
ret = ioctl(fd, DRM_IOCTL_BUFOBJ, first);
if (ret)
return -errno;
for (l = list->list.next; l != &list->list; l = l->next) {
node = DRMLISTENTRY(drmBONode, l, head);
arg = &node->bo_arg;
rep = &arg->d.rep;
if (!arg->handled)
return -EFAULT;
if (rep->ret)
return rep->ret;
drmBOCopyReply(rep, node->buf);
}
return 0;
}
int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize,
unsigned memType)
{
drm_mm_init_arg_t arg;
struct drm_mm_init_arg arg;
memset(&arg, 0, sizeof(arg));
arg.req.op = mm_init;
arg.req.p_offset = pOffset;
arg.req.p_size = pSize;
arg.req.mem_type = memType;
arg.magic = DRM_BO_INIT_MAGIC;
arg.major = DRM_BO_INIT_MAJOR;
arg.minor = DRM_BO_INIT_MINOR;
arg.p_offset = pOffset;
arg.p_size = pSize;
arg.mem_type = memType;
if (ioctl(fd, DRM_IOCTL_MM_INIT, &arg))
return -errno;
@ -3237,47 +2806,79 @@ int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize,
int drmMMTakedown(int fd, unsigned memType)
{
drm_mm_init_arg_t arg;
struct drm_mm_type_arg arg;
memset(&arg, 0, sizeof(arg));
arg.req.op = mm_takedown;
arg.req.mem_type = memType;
arg.mem_type = memType;
if (ioctl(fd, DRM_IOCTL_MM_INIT, &arg))
if (ioctl(fd, DRM_IOCTL_MM_TAKEDOWN, &arg))
return -errno;
return 0;
}
int drmMMLock(int fd, unsigned memType)
/*
* If this function returns an error, and lockBM was set to 1,
* the buffer manager is NOT locked.
*/
int drmMMLock(int fd, unsigned memType, int lockBM, int ignoreNoEvict)
{
drm_mm_init_arg_t arg;
struct drm_mm_type_arg arg;
int ret;
memset(&arg, 0, sizeof(arg));
arg.req.op = mm_lock;
arg.req.mem_type = memType;
arg.mem_type = memType;
arg.lock_flags |= (lockBM) ? DRM_BO_LOCK_UNLOCK_BM : 0;
arg.lock_flags |= (ignoreNoEvict) ? DRM_BO_LOCK_IGNORE_NO_EVICT : 0;
do{
ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg);
ret = ioctl(fd, DRM_IOCTL_MM_LOCK, &arg);
} while (ret && errno == EAGAIN);
return -errno;
return (ret) ? -errno : 0;
}
int drmMMUnlock(int fd, unsigned memType)
int drmMMUnlock(int fd, unsigned memType, int unlockBM)
{
drm_mm_init_arg_t arg;
struct drm_mm_type_arg arg;
int ret;
memset(&arg, 0, sizeof(arg));
arg.req.op = mm_unlock;
arg.req.mem_type = memType;
arg.mem_type = memType;
arg.lock_flags |= (unlockBM) ? DRM_BO_LOCK_UNLOCK_BM : 0;
do{
ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg);
ret = ioctl(fd, DRM_IOCTL_MM_UNLOCK, &arg);
} while (ret && errno == EAGAIN);
return -errno;
return (ret) ? -errno : 0;
}
int drmBOVersion(int fd, unsigned int *major,
unsigned int *minor,
unsigned int *patchlevel)
{
struct drm_bo_version_arg arg;
int ret;
memset(&arg, 0, sizeof(arg));
ret = ioctl(fd, DRM_IOCTL_BO_VERSION, &arg);
if (ret)
return -errno;
if (major)
*major = arg.major;
if (minor)
*minor = arg.minor;
if (patchlevel)
*patchlevel = arg.patchlevel;
return 0;
}
#define DRM_MAX_FDS 16
static struct {
char *BusID;

View File

@ -36,6 +36,7 @@
#include <stdarg.h>
#include <sys/types.h>
#include <stdint.h>
#include <drm.h>
/* Defaults, if nothing set in xf86config */

View File

@ -74,7 +74,6 @@
#define HASH_MAIN 0
#if !HASH_MAIN
# include "drm.h"
# include "xf86drm.h"
#endif

View File

@ -77,7 +77,6 @@
#define RANDOM_MAIN 0
#if !RANDOM_MAIN
# include "drm.h"
# include "xf86drm.h"
#endif

View File

@ -44,7 +44,6 @@
#define SL_MAIN 0
#if !SL_MAIN
# include "drm.h"
# include "xf86drm.h"
#else
# include <sys/time.h>

View File

@ -29,6 +29,7 @@
#ifndef _XF86MM_H_
#define _XF86MM_H_
#include <stddef.h>
#include <stdint.h>
#include "drm.h"
/*
@ -37,7 +38,7 @@
* be protected using an external mutex.
*
* Note: Don't protect the following functions, as it may lead to deadlocks:
* drmBOUnmap(), drmFenceBuffers().
* drmBOUnmap().
* The kernel is synchronizing and refcounting buffer maps.
* User space only needs to refcount object usage within the same application.
*/
@ -96,20 +97,20 @@ typedef struct _drmMMListHead
typedef struct _drmFence
{
unsigned handle;
int class;
int fence_class;
unsigned type;
unsigned flags;
unsigned signaled;
uint32_t sequence;
unsigned pad[4]; /* for future expansion */
} drmFence;
typedef struct _drmBO
{
drm_bo_type_t type;
unsigned handle;
drm_u64_t mapHandle;
unsigned flags;
unsigned mask;
uint64_t mapHandle;
uint64_t flags;
uint64_t mask;
unsigned mapFlags;
unsigned long size;
unsigned long offset;
@ -117,37 +118,21 @@ typedef struct _drmBO
unsigned replyFlags;
unsigned fenceFlags;
unsigned pageAlignment;
unsigned tileInfo;
unsigned hwTileStride;
unsigned desiredTileStride;
void *virtual;
void *mapVirtual;
int mapCount;
unsigned pad[8]; /* for future expansion */
} drmBO;
typedef struct _drmBONode
{
drmMMListHead head;
drmBO *buf;
drm_bo_arg_t bo_arg;
unsigned long arg0;
unsigned long arg1;
} drmBONode;
typedef struct _drmBOList {
unsigned numTarget;
unsigned numCurrent;
unsigned numOnList;
drmMMListHead list;
drmMMListHead free;
} drmBOList;
/*
* Fence functions.
*/
extern int drmFenceCreate(int fd, unsigned flags, int class,
extern int drmFenceCreate(int fd, unsigned flags, int fence_class,
unsigned type, drmFence *fence);
extern int drmFenceDestroy(int fd, const drmFence *fence);
extern int drmFenceReference(int fd, unsigned handle, drmFence *fence);
extern int drmFenceUnreference(int fd, const drmFence *fence);
extern int drmFenceFlush(int fd, drmFence *fence, unsigned flush_type);
@ -157,46 +142,25 @@ extern int drmFenceWait(int fd, unsigned flags, drmFence *fence,
unsigned flush_type);
extern int drmFenceEmit(int fd, unsigned flags, drmFence *fence,
unsigned emit_type);
extern int drmFenceBuffers(int fd, unsigned flags, drmFence *fence);
extern int drmFenceBuffers(int fd, unsigned flags, uint32_t fence_class, drmFence *fence);
/*
* Buffer object list functions.
*/
extern void drmBOFreeList(drmBOList *list);
extern int drmBOResetList(drmBOList *list);
extern void *drmBOListIterator(drmBOList *list);
extern void *drmBOListNext(drmBOList *list, void *iterator);
extern drmBO *drmBOListBuf(void *iterator);
extern int drmBOCreateList(int numTarget, drmBOList *list);
/*
* Buffer object functions.
*/
extern int drmBOCreate(int fd, unsigned long start, unsigned long size,
unsigned pageAlignment,void *user_buffer,
drm_bo_type_t type, unsigned mask,
unsigned hint, drmBO *buf);
extern int drmBODestroy(int fd, drmBO *buf);
extern int drmBOCreate(int fd, unsigned long size,
unsigned pageAlignment, void *user_buffer,
uint64_t mask, unsigned hint, drmBO *buf);
extern int drmBOReference(int fd, unsigned handle, drmBO *buf);
extern int drmBOUnReference(int fd, drmBO *buf);
extern int drmBOUnreference(int fd, drmBO *buf);
extern int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint,
void **address);
extern int drmBOUnmap(int fd, drmBO *buf);
extern int drmBOValidate(int fd, drmBO *buf, unsigned flags, unsigned mask,
unsigned hint);
extern int drmBOFence(int fd, drmBO *buf, unsigned flags, unsigned fenceHandle);
extern int drmBOInfo(int fd, drmBO *buf);
extern int drmBOBusy(int fd, drmBO *buf, int *busy);
extern int drmAddValidateItem(drmBOList *list, drmBO *buf, unsigned flags,
unsigned mask,
int *newItem);
extern int drmBOValidateList(int fd, drmBOList *list);
extern int drmBOFenceList(int fd, drmBOList *list, unsigned fenceHandle);
extern int drmBOWaitIdle(int fd, drmBO *buf, unsigned hint);
/*
@ -206,8 +170,16 @@ extern int drmBOWaitIdle(int fd, drmBO *buf, unsigned hint);
extern int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize,
unsigned memType);
extern int drmMMTakedown(int fd, unsigned memType);
extern int drmMMLock(int fd, unsigned memType);
extern int drmMMUnlock(int fd, unsigned memType);
extern int drmMMLock(int fd, unsigned memType, int lockBM, int ignoreNoEvict);
extern int drmMMUnlock(int fd, unsigned memType, int unlockBM);
extern int drmBOSetStatus(int fd, drmBO *buf,
uint64_t flags, uint64_t mask,
unsigned int hint,
unsigned int desired_tile_stride,
unsigned int tile_info);
extern int drmBOVersion(int fd, unsigned int *major,
unsigned int *minor,
unsigned int *patchlevel);
#endif

View File

@ -58,7 +58,7 @@ endif
# Modules for all architectures
MODULE_LIST := drm.o tdfx.o r128.o radeon.o mga.o sis.o savage.o via.o \
mach64.o nv.o nouveau.o
mach64.o nv.o nouveau.o xgi.o
# Modules only for ix86 architectures
ifneq (,$(findstring 86,$(MACHINE)))
@ -91,6 +91,7 @@ MACH64HEADERS = mach64_drv.h mach64_drm.h $(DRMHEADERS)
NVHEADERS = nv_drv.h $(DRMHEADERS)
FFBHEADERS = ffb_drv.h $(DRMHEADERS)
NOUVEAUHEADERS = nouveau_drv.h nouveau_drm.h nouveau_reg.h $(DRMHEADERS)
XGIHEADERS = xgi_cmdlist.h xgi_drv.h xgi_misc.h xgi_regs.h $(DRMHEADERS)
PROGS = dristat drmstat
@ -162,7 +163,7 @@ endif
all: modules
modules: includes
make -C $(LINUXDIR) $(GETCONFIG) SUBDIRS=`pwd` DRMSRCDIR=`pwd` modules
+make -C $(LINUXDIR) $(GETCONFIG) SUBDIRS=`pwd` DRMSRCDIR=`pwd` modules
ifeq ($(HEADERFROMBOOT),1)
@ -284,6 +285,7 @@ CONFIG_DRM_VIA := n
CONFIG_DRM_MACH64 := n
CONFIG_DRM_NV := n
CONFIG_DRM_NOUVEAU := n
CONFIG_DRM_XGI := n
# Enable module builds for the modules requested/supported.
@ -320,6 +322,9 @@ endif
ifneq (,$(findstring nouveau,$(DRM_MODULES)))
CONFIG_DRM_NOUVEAU := m
endif
ifneq (,$(findstring xgi,$(DRM_MODULES)))
CONFIG_DRM_XGI := m
endif
# These require AGP support
@ -347,6 +352,7 @@ $(via-objs): $(VIAHEADERS)
$(mach64-objs): $(MACH64HEADERS)
$(nv-objs): $(NVHEADERS)
$(nouveau-objs): $(NOUVEAUHEADERS)
$(xgi-objs): $(XGIHEADERS)
endif

View File

@ -13,7 +13,7 @@ drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
drm_sysfs.o drm_pci.o drm_agpsupport.o drm_scatter.o \
drm_memory_debug.o ati_pcigart.o drm_sman.o \
drm_hashtab.o drm_mm.o drm_object.o drm_compat.o \
drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o
drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o drm_bo_lock.o
tdfx-objs := tdfx_drv.o
r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o
mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
@ -21,12 +21,15 @@ i810-objs := i810_drv.o i810_dma.o
i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \
i915_buffer.o
nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \
nouveau_object.o nouveau_irq.o \
nouveau_object.o nouveau_irq.o nouveau_notifier.o nouveau_swmthd.o \
nouveau_sgdma.o nouveau_dma.o \
nv04_timer.o \
nv04_mc.o nv40_mc.o \
nv04_mc.o nv40_mc.o nv50_mc.o \
nv04_fb.o nv10_fb.o nv40_fb.o \
nv04_graph.o nv10_graph.o nv20_graph.o nv30_graph.o \
nv40_graph.o
nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \
nv04_graph.o nv10_graph.o nv20_graph.o \
nv40_graph.o nv50_graph.o \
nv04_instmem.o nv50_instmem.o
radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o
sis-objs := sis_drv.o sis_mm.o
ffb-objs := ffb_drv.o ffb_context.o
@ -35,6 +38,8 @@ via-objs := via_irq.o via_drv.o via_map.o via_mm.o via_dma.o via_verifier.o \
via_video.o via_dmablit.o via_fence.o via_buffer.o
mach64-objs := mach64_drv.o mach64_dma.o mach64_irq.o mach64_state.o
nv-objs := nv_drv.o
xgi-objs := xgi_cmdlist.o xgi_drv.o xgi_fb.o xgi_misc.o xgi_pcie.o \
xgi_fence.o
ifeq ($(CONFIG_COMPAT),y)
drm-objs += drm_ioc32.o
@ -43,6 +48,7 @@ mga-objs += mga_ioc32.o
r128-objs += r128_ioc32.o
i915-objs += i915_ioc32.o
nouveau-objs += nouveau_ioc32.o
xgi-objs += xgi_ioc32.o
endif
obj-m += drm.o
@ -59,3 +65,4 @@ obj-$(CONFIG_DRM_VIA) += via.o
obj-$(CONFIG_DRM_MACH64)+= mach64.o
obj-$(CONFIG_DRM_NV) += nv.o
obj-$(CONFIG_DRM_NOUVEAU) += nouveau.o
obj-$(CONFIG_DRM_XGI) += xgi.o

View File

@ -81,9 +81,9 @@ static void drm_ati_free_pcigart_table(void *address, int order)
free_pages((unsigned long)address, order);
}
int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
int drm_ati_pcigart_cleanup(struct drm_device *dev, struct ati_pcigart_info *gart_info)
{
drm_sg_mem_t *entry = dev->sg;
struct drm_sg_mem *entry = dev->sg;
unsigned long pages;
int i;
int order;
@ -132,9 +132,9 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
}
EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
int drm_ati_pcigart_init(struct drm_device *dev, struct ati_pcigart_info *gart_info)
{
drm_sg_mem_t *entry = dev->sg;
struct drm_sg_mem *entry = dev->sg;
void *address = NULL;
unsigned long pages;
u32 *pci_gart, page_base, bus_address = 0;

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,7 @@
* Get AGP information.
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg pointer to a (output) drm_agp_info structure.
* \return zero on success or a negative number on failure.
@ -48,7 +48,7 @@
* Verifies the AGP device has been initialized and acquired and fills in the
* drm_agp_info structure with the information in drm_agp_head::agp_info.
*/
int drm_agp_info(drm_device_t * dev, drm_agp_info_t *info)
int drm_agp_info(struct drm_device * dev, struct drm_agp_info *info)
{
DRM_AGP_KERN *kern;
@ -70,20 +70,16 @@ int drm_agp_info(drm_device_t * dev, drm_agp_info_t *info)
}
EXPORT_SYMBOL(drm_agp_info);
int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_agp_info_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_agp_info_t info;
struct drm_agp_info *info = data;
int err;
err = drm_agp_info(dev, &info);
err = drm_agp_info(dev, info);
if (err)
return err;
if (copy_to_user((drm_agp_info_t __user *) arg, &info, sizeof(info)))
return -EFAULT;
return 0;
}
@ -96,7 +92,7 @@ int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
* Verifies the AGP device hasn't been acquired before and calls
* \c agp_backend_acquire.
*/
int drm_agp_acquire(drm_device_t * dev)
int drm_agp_acquire(struct drm_device * dev)
{
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,11)
int retcode;
@ -123,7 +119,7 @@ EXPORT_SYMBOL(drm_agp_acquire);
* Acquire the AGP device (ioctl).
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument.
* \return zero on success or a negative number on failure.
@ -131,12 +127,10 @@ EXPORT_SYMBOL(drm_agp_acquire);
* Verifies the AGP device hasn't been acquired before and calls
* \c agp_backend_acquire.
*/
int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
return drm_agp_acquire( (drm_device_t *) priv->head->dev );
return drm_agp_acquire( (struct drm_device *) file_priv->head->dev );
}
/**
@ -147,7 +141,7 @@ int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
*
* Verifies the AGP device has been acquired and calls \c agp_backend_release.
*/
int drm_agp_release(drm_device_t *dev)
int drm_agp_release(struct drm_device *dev)
{
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
@ -162,12 +156,9 @@ int drm_agp_release(drm_device_t *dev)
}
EXPORT_SYMBOL(drm_agp_release);
int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_agp_release_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
return drm_agp_release(dev);
}
@ -181,7 +172,7 @@ int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
* Verifies the AGP device has been acquired but not enabled, and calls
* \c agp_enable.
*/
int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode)
int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode)
{
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
@ -192,31 +183,24 @@ int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode)
#else
agp_enable(dev->agp->bridge, mode.mode);
#endif
dev->agp->base = dev->agp->agp_info.aper_base;
dev->agp->enabled = 1;
return 0;
}
EXPORT_SYMBOL(drm_agp_enable);
int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_agp_mode_t mode;
struct drm_agp_mode *mode = data;
if (copy_from_user(&mode, (drm_agp_mode_t __user *) arg, sizeof(mode)))
return -EFAULT;
return drm_agp_enable(dev, mode);
return drm_agp_enable(dev, *mode);
}
/**
* Allocate AGP memory.
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv file private pointer.
* \param cmd command.
* \param arg pointer to a drm_agp_buffer structure.
* \return zero on success or a negative number on failure.
@ -224,9 +208,9 @@ int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
* Verifies the AGP device is present and has been acquired, allocates the
* memory via alloc_agp() and creates a drm_agp_mem entry for it.
*/
int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request)
int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
{
drm_agp_mem_t *entry;
struct drm_agp_mem *entry;
DRM_AGP_MEM *memory;
unsigned long pages;
u32 type;
@ -259,35 +243,12 @@ int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request)
EXPORT_SYMBOL(drm_agp_alloc);
int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_agp_buffer_t request;
drm_agp_buffer_t __user *argp = (void __user *)arg;
int err;
struct drm_agp_buffer *request = data;
if (copy_from_user(&request, argp, sizeof(request)))
return -EFAULT;
err = drm_agp_alloc(dev, &request);
if (err)
return err;
if (copy_to_user(argp, &request, sizeof(request))) {
drm_agp_mem_t *entry;
list_for_each_entry(entry, &dev->agp->memory, head) {
if (entry->handle == request.handle)
break;
}
list_del(&entry->head);
drm_free_agp(entry->memory, entry->pages);
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
return -EFAULT;
}
return 0;
return drm_agp_alloc(dev, request);
}
/**
@ -299,10 +260,10 @@ int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,
*
* Walks through drm_agp_head::memory until finding a matching handle.
*/
static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t * dev,
static struct drm_agp_mem *drm_agp_lookup_entry(struct drm_device * dev,
unsigned long handle)
{
drm_agp_mem_t *entry;
struct drm_agp_mem *entry;
list_for_each_entry(entry, &dev->agp->memory, head) {
if (entry->handle == handle)
@ -315,7 +276,7 @@ static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t * dev,
* Unbind AGP memory from the GATT (ioctl).
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg pointer to a drm_agp_binding structure.
* \return zero on success or a negative number on failure.
@ -323,9 +284,9 @@ static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t * dev,
* Verifies the AGP device is present and acquired, looks-up the AGP memory
* entry and passes it to the unbind_agp() function.
*/
int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request)
int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
{
drm_agp_mem_t *entry;
struct drm_agp_mem *entry;
int ret;
if (!dev->agp || !dev->agp->acquired)
@ -342,18 +303,12 @@ int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request)
EXPORT_SYMBOL(drm_agp_unbind);
int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_agp_binding_t request;
struct drm_agp_binding *request = data;
if (copy_from_user
(&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
return -EFAULT;
return drm_agp_unbind(dev, &request);
return drm_agp_unbind(dev, request);
}
@ -361,7 +316,7 @@ int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,
* Bind AGP memory into the GATT (ioctl)
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg pointer to a drm_agp_binding structure.
* \return zero on success or a negative number on failure.
@ -370,9 +325,9 @@ int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,
* is currently bound into the GATT. Looks-up the AGP memory entry and passes
* it to bind_agp() function.
*/
int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request)
int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
{
drm_agp_mem_t *entry;
struct drm_agp_mem *entry;
int retcode;
int page;
@ -393,18 +348,12 @@ int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request)
EXPORT_SYMBOL(drm_agp_bind);
int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_agp_binding_t request;
struct drm_agp_binding *request = data;
if (copy_from_user
(&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
return -EFAULT;
return drm_agp_bind(dev, &request);
return drm_agp_bind(dev, request);
}
@ -412,7 +361,7 @@ int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,
* Free AGP memory (ioctl).
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg pointer to a drm_agp_buffer structure.
* \return zero on success or a negative number on failure.
@ -422,9 +371,9 @@ int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,
* unbind_agp(). Frees it via free_agp() as well as the entry itself
* and unlinks from the doubly linked list it's inserted in.
*/
int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request)
int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
{
drm_agp_mem_t *entry;
struct drm_agp_mem *entry;
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
@ -443,18 +392,12 @@ EXPORT_SYMBOL(drm_agp_free);
int drm_agp_free_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_agp_free_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_agp_buffer_t request;
struct drm_agp_buffer *request = data;
if (copy_from_user
(&request, (drm_agp_buffer_t __user *) arg, sizeof(request)))
return -EFAULT;
return drm_agp_free(dev, &request);
return drm_agp_free(dev, request);
}
@ -467,9 +410,9 @@ int drm_agp_free_ioctl(struct inode *inode, struct file *filp,
* via the inter_module_* functions. Creates and initializes a drm_agp_head
* structure.
*/
drm_agp_head_t *drm_agp_init(drm_device_t *dev)
struct drm_agp_head *drm_agp_init(struct drm_device *dev)
{
drm_agp_head_t *head = NULL;
struct drm_agp_head *head = NULL;
if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
return NULL;
@ -497,6 +440,7 @@ drm_agp_head_t *drm_agp_init(drm_device_t *dev)
INIT_LIST_HEAD(&head->memory);
head->cant_use_aperture = head->agp_info.cant_use_aperture;
head->page_mask = head->agp_info.page_mask;
head->base = head->agp_info.aper_base;
return head;
}
@ -554,16 +498,16 @@ int drm_agp_unbind_memory(DRM_AGP_MEM * handle)
#define AGP_REQUIRED_MAJOR 0
#define AGP_REQUIRED_MINOR 102
static int drm_agp_needs_unbind_cache_adjust(drm_ttm_backend_t *backend) {
static int drm_agp_needs_unbind_cache_adjust(struct drm_ttm_backend *backend) {
return ((backend->flags & DRM_BE_FLAG_BOUND_CACHED) ? 0 : 1);
}
static int drm_agp_populate(drm_ttm_backend_t *backend, unsigned long num_pages,
static int drm_agp_populate(struct drm_ttm_backend *backend, unsigned long num_pages,
struct page **pages) {
drm_agp_ttm_backend_t *agp_be =
container_of(backend, drm_agp_ttm_backend_t, backend);
struct drm_agp_ttm_backend *agp_be =
container_of(backend, struct drm_agp_ttm_backend, backend);
struct page **cur_page, **last_page = pages + num_pages;
DRM_AGP_MEM *mem;
@ -590,32 +534,32 @@ static int drm_agp_populate(drm_ttm_backend_t *backend, unsigned long num_pages,
return 0;
}
static int drm_agp_bind_ttm(drm_ttm_backend_t *backend,
unsigned long offset,
int cached)
static int drm_agp_bind_ttm(struct drm_ttm_backend *backend,
struct drm_bo_mem_reg *bo_mem)
{
drm_agp_ttm_backend_t *agp_be =
container_of(backend, drm_agp_ttm_backend_t, backend);
struct drm_agp_ttm_backend *agp_be =
container_of(backend, struct drm_agp_ttm_backend, backend);
DRM_AGP_MEM *mem = agp_be->mem;
int ret;
DRM_DEBUG("drm_agp_bind_ttm\n");
mem->is_flushed = TRUE;
mem->type = (cached) ? AGP_USER_CACHED_MEMORY :
mem->type = (bo_mem->flags & DRM_BO_FLAG_CACHED) ? AGP_USER_CACHED_MEMORY :
AGP_USER_MEMORY;
ret = drm_agp_bind_memory(mem, offset);
ret = drm_agp_bind_memory(mem, bo_mem->mm_node->start);
if (ret) {
DRM_ERROR("AGP Bind memory failed\n");
}
DRM_FLAG_MASKED(backend->flags, (cached) ? DRM_BE_FLAG_BOUND_CACHED : 0,
DRM_FLAG_MASKED(backend->flags, (bo_mem->flags & DRM_BO_FLAG_CACHED) ?
DRM_BE_FLAG_BOUND_CACHED : 0,
DRM_BE_FLAG_BOUND_CACHED);
return ret;
}
static int drm_agp_unbind_ttm(drm_ttm_backend_t *backend) {
static int drm_agp_unbind_ttm(struct drm_ttm_backend *backend) {
drm_agp_ttm_backend_t *agp_be =
container_of(backend, drm_agp_ttm_backend_t, backend);
struct drm_agp_ttm_backend *agp_be =
container_of(backend, struct drm_agp_ttm_backend, backend);
DRM_DEBUG("drm_agp_unbind_ttm\n");
if (agp_be->mem->is_bound)
@ -624,10 +568,10 @@ static int drm_agp_unbind_ttm(drm_ttm_backend_t *backend) {
return 0;
}
static void drm_agp_clear_ttm(drm_ttm_backend_t *backend) {
static void drm_agp_clear_ttm(struct drm_ttm_backend *backend) {
drm_agp_ttm_backend_t *agp_be =
container_of(backend, drm_agp_ttm_backend_t, backend);
struct drm_agp_ttm_backend *agp_be =
container_of(backend, struct drm_agp_ttm_backend, backend);
DRM_AGP_MEM *mem = agp_be->mem;
DRM_DEBUG("drm_agp_clear_ttm\n");
@ -640,13 +584,13 @@ static void drm_agp_clear_ttm(drm_ttm_backend_t *backend) {
agp_be->mem = NULL;
}
static void drm_agp_destroy_ttm(drm_ttm_backend_t *backend) {
static void drm_agp_destroy_ttm(struct drm_ttm_backend *backend) {
drm_agp_ttm_backend_t *agp_be;
struct drm_agp_ttm_backend *agp_be;
if (backend) {
DRM_DEBUG("drm_agp_destroy_ttm\n");
agp_be = container_of(backend, drm_agp_ttm_backend_t, backend);
agp_be = container_of(backend, struct drm_agp_ttm_backend, backend);
if (agp_be) {
if (agp_be->mem) {
backend->func->clear(backend);
@ -656,7 +600,7 @@ static void drm_agp_destroy_ttm(drm_ttm_backend_t *backend) {
}
}
static drm_ttm_backend_func_t agp_ttm_backend =
static struct drm_ttm_backend_func agp_ttm_backend =
{
.needs_ub_cache_adjust = drm_agp_needs_unbind_cache_adjust,
.populate = drm_agp_populate,
@ -666,10 +610,10 @@ static drm_ttm_backend_func_t agp_ttm_backend =
.destroy = drm_agp_destroy_ttm,
};
drm_ttm_backend_t *drm_agp_init_ttm(struct drm_device *dev)
struct drm_ttm_backend *drm_agp_init_ttm(struct drm_device *dev)
{
drm_agp_ttm_backend_t *agp_be;
struct drm_agp_ttm_backend *agp_be;
struct agp_kern_info *info;
if (!dev->agp) {
@ -699,7 +643,8 @@ drm_ttm_backend_t *drm_agp_init_ttm(struct drm_device *dev)
agp_be->bridge = dev->agp->bridge;
agp_be->populated = FALSE;
agp_be->backend.func = &agp_ttm_backend;
agp_be->backend.mem_type = DRM_BO_MEM_TT;
// agp_be->backend.mem_type = DRM_BO_MEM_TT;
agp_be->backend.dev = dev;
return &agp_be->backend;
}

View File

@ -45,15 +45,15 @@
* the one with matching magic number, while holding the drm_device::struct_mutex
* lock.
*/
static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
static struct drm_file *drm_find_file(struct drm_device * dev, drm_magic_t magic)
{
drm_file_t *retval = NULL;
drm_magic_entry_t *pt;
drm_hash_item_t *hash;
struct drm_file *retval = NULL;
struct drm_magic_entry *pt;
struct drm_hash_item *hash;
mutex_lock(&dev->struct_mutex);
if (!drm_ht_find_item(&dev->magiclist, (unsigned long) magic, &hash)) {
pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
retval = pt->priv;
}
mutex_unlock(&dev->struct_mutex);
@ -71,10 +71,10 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
* associated the magic number hash key in drm_device::magiclist, while holding
* the drm_device::struct_mutex lock.
*/
static int drm_add_magic(drm_device_t *dev, drm_file_t *priv,
static int drm_add_magic(struct drm_device * dev, struct drm_file * priv,
drm_magic_t magic)
{
drm_magic_entry_t *entry;
struct drm_magic_entry *entry;
DRM_DEBUG("%d\n", magic);
@ -101,10 +101,10 @@ static int drm_add_magic(drm_device_t *dev, drm_file_t *priv,
* Searches and unlinks the entry in drm_device::magiclist with the magic
* number hash key, while holding the drm_device::struct_mutex lock.
*/
static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
static int drm_remove_magic(struct drm_device * dev, drm_magic_t magic)
{
drm_magic_entry_t *pt;
drm_hash_item_t *hash;
struct drm_magic_entry *pt;
struct drm_hash_item *hash;
DRM_DEBUG("%d\n", magic);
@ -113,7 +113,7 @@ static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
drm_ht_remove_item(&dev->magiclist, hash);
list_del(&pt->head);
mutex_unlock(&dev->struct_mutex);
@ -127,42 +127,38 @@ static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
* Get a unique magic number (ioctl).
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg pointer to a resulting drm_auth structure.
* \return zero on success, or a negative number on failure.
*
* If there is a magic number in drm_file::magic then use it, otherwise
* searches an unique non-zero magic number and add it associating it with \p
* filp.
* file_priv.
*/
int drm_getmagic(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
static drm_magic_t sequence = 0;
static DEFINE_SPINLOCK(lock);
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_auth_t auth;
struct drm_auth *auth = data;
/* Find unique magic */
if (priv->magic) {
auth.magic = priv->magic;
if (file_priv->magic) {
auth->magic = file_priv->magic;
} else {
do {
spin_lock(&lock);
if (!sequence)
++sequence; /* reserve 0 */
auth.magic = sequence++;
auth->magic = sequence++;
spin_unlock(&lock);
} while (drm_find_file(dev, auth.magic));
priv->magic = auth.magic;
drm_add_magic(dev, priv, auth.magic);
} while (drm_find_file(dev, auth->magic));
file_priv->magic = auth->magic;
drm_add_magic(dev, file_priv, auth->magic);
}
DRM_DEBUG("%u\n", auth.magic);
if (copy_to_user((drm_auth_t __user *) arg, &auth, sizeof(auth)))
return -EFAULT;
DRM_DEBUG("%u\n", auth->magic);
return 0;
}
@ -170,27 +166,23 @@ int drm_getmagic(struct inode *inode, struct file *filp,
* Authenticate with a magic.
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg pointer to a drm_auth structure.
* \return zero if authentication successed, or a negative number otherwise.
*
* Checks if \p filp is associated with the magic number passed in \arg.
* Checks if \p file_priv is associated with the magic number passed in \arg.
*/
int drm_authmagic(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_authmagic(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_auth_t auth;
drm_file_t *file;
struct drm_auth *auth = data;
struct drm_file *file;
if (copy_from_user(&auth, (drm_auth_t __user *) arg, sizeof(auth)))
return -EFAULT;
DRM_DEBUG("%u\n", auth.magic);
if ((file = drm_find_file(dev, auth.magic))) {
DRM_DEBUG("%u\n", auth->magic);
if ((file = drm_find_file(dev, auth->magic))) {
file->authenticated = 1;
drm_remove_magic(dev, auth.magic);
drm_remove_magic(dev, auth->magic);
return 0;
}
return -EINVAL;

File diff suppressed because it is too large Load Diff

178
linux-core/drm_bo_lock.c Normal file
View File

@ -0,0 +1,178 @@
/**************************************************************************
*
* Copyright (c) 2007 Tungsten Graphics, Inc., Cedar Park, TX., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/*
* Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
/*
* This file implements a simple replacement for the buffer manager use
* of the heavyweight hardware lock.
* The lock is a read-write lock. Taking it in read mode is fast, and
* intended for in-kernel use only.
* Taking it in write mode is slow.
*
* The write mode is used only when there is a need to block all
* user-space processes from allocating a
* new memory area.
* Typical use in write mode is X server VT switching, and it's allowed
* to leave kernel space with the write lock held. If a user-space process
* dies while having the write-lock, it will be released during the file
* descriptor release.
*
* The read lock is typically placed at the start of an IOCTL- or
* user-space callable function that may end up allocating a memory area.
* This includes setstatus, super-ioctls and no_pfn; the latter may move
* unmappable regions to mappable. It's a bug to leave kernel space with the
* read lock held.
*
* Both read- and write lock taking is interruptible for low signal-delivery
* latency. The locking functions will return -EAGAIN if interrupted by a
* signal.
*
* Locking order: The lock should be taken BEFORE any kernel mutexes
* or spinlocks.
*/
#include "drmP.h"
void drm_bo_init_lock(struct drm_bo_lock *lock)
{
DRM_INIT_WAITQUEUE(&lock->queue);
atomic_set(&lock->write_lock_pending, 0);
atomic_set(&lock->readers, 0);
}
void drm_bo_read_unlock(struct drm_bo_lock *lock)
{
if (unlikely(atomic_add_negative(-1, &lock->readers)))
BUG();
if (atomic_read(&lock->readers) == 0)
wake_up_interruptible(&lock->queue);
}
EXPORT_SYMBOL(drm_bo_read_unlock);
int drm_bo_read_lock(struct drm_bo_lock *lock)
{
while (unlikely(atomic_read(&lock->write_lock_pending) != 0)) {
int ret;
ret = wait_event_interruptible
(lock->queue, atomic_read(&lock->write_lock_pending) == 0);
if (ret)
return -EAGAIN;
}
while (unlikely(!atomic_add_unless(&lock->readers, 1, -1))) {
int ret;
ret = wait_event_interruptible
(lock->queue, atomic_add_unless(&lock->readers, 1, -1));
if (ret)
return -EAGAIN;
}
return 0;
}
EXPORT_SYMBOL(drm_bo_read_lock);
static int __drm_bo_write_unlock(struct drm_bo_lock *lock)
{
if (unlikely(atomic_cmpxchg(&lock->readers, -1, 0) != -1))
return -EINVAL;
if (unlikely(atomic_cmpxchg(&lock->write_lock_pending, 1, 0) != 1))
return -EINVAL;
wake_up_interruptible(&lock->queue);
return 0;
}
static void drm_bo_write_lock_remove(struct drm_file *file_priv,
struct drm_user_object *item)
{
struct drm_bo_lock *lock = container_of(item, struct drm_bo_lock, base);
int ret;
ret = __drm_bo_write_unlock(lock);
BUG_ON(ret);
}
int drm_bo_write_lock(struct drm_bo_lock *lock, struct drm_file *file_priv)
{
int ret = 0;
struct drm_device *dev;
if (unlikely(atomic_cmpxchg(&lock->write_lock_pending, 0, 1) != 0)) {
return -EINVAL;
}
while (unlikely(atomic_cmpxchg(&lock->readers, 0, -1) != 0)) {
ret = wait_event_interruptible
(lock->queue, atomic_cmpxchg(&lock->readers, 0, -1) == 0);
if (ret) {
atomic_set(&lock->write_lock_pending, 0);
wake_up_interruptible(&lock->queue);
return -EAGAIN;
}
}
/*
* Add a dummy user-object, the destructor of which will
* make sure the lock is released if the client dies
* while holding it.
*/
dev = file_priv->head->dev;
mutex_lock(&dev->struct_mutex);
ret = drm_add_user_object(file_priv, &lock->base, 0);
lock->base.remove = &drm_bo_write_lock_remove;
lock->base.type = drm_lock_type;
if (ret) {
(void)__drm_bo_write_unlock(lock);
}
mutex_unlock(&dev->struct_mutex);
return ret;
}
int drm_bo_write_unlock(struct drm_bo_lock *lock, struct drm_file *file_priv)
{
struct drm_device *dev = file_priv->head->dev;
struct drm_ref_object *ro;
mutex_lock(&dev->struct_mutex);
if (lock->base.owner != file_priv) {
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
ro = drm_lookup_ref_object(file_priv, &lock->base, _DRM_REF_USE);
BUG_ON(!ro);
drm_remove_ref_object(file_priv, ro);
lock->base.owner = NULL;
mutex_unlock(&dev->struct_mutex);
return 0;
}

View File

@ -35,9 +35,9 @@
* have not been requested to free also pinned regions.
*/
static void drm_bo_free_old_node(drm_buffer_object_t * bo)
static void drm_bo_free_old_node(struct drm_buffer_object * bo)
{
drm_bo_mem_reg_t *old_mem = &bo->mem;
struct drm_bo_mem_reg *old_mem = &bo->mem;
if (old_mem->mm_node && (old_mem->mm_node != bo->pinned_node)) {
mutex_lock(&bo->dev->struct_mutex);
@ -48,13 +48,13 @@ static void drm_bo_free_old_node(drm_buffer_object_t * bo)
old_mem->mm_node = NULL;
}
int drm_bo_move_ttm(drm_buffer_object_t * bo,
int evict, int no_wait, drm_bo_mem_reg_t * new_mem)
int drm_bo_move_ttm(struct drm_buffer_object * bo,
int evict, int no_wait, struct drm_bo_mem_reg * new_mem)
{
drm_ttm_t *ttm = bo->ttm;
drm_bo_mem_reg_t *old_mem = &bo->mem;
uint32_t save_flags = old_mem->flags;
uint32_t save_mask = old_mem->mask;
struct drm_ttm *ttm = bo->ttm;
struct drm_bo_mem_reg *old_mem = &bo->mem;
uint64_t save_flags = old_mem->flags;
uint64_t save_mask = old_mem->mask;
int ret;
if (old_mem->mem_type == DRM_BO_MEM_TT) {
@ -71,9 +71,7 @@ int drm_bo_move_ttm(drm_buffer_object_t * bo,
save_flags = old_mem->flags;
}
if (new_mem->mem_type != DRM_BO_MEM_LOCAL) {
ret = drm_bind_ttm(ttm,
new_mem->flags & DRM_BO_FLAG_CACHED,
new_mem->mm_node->start);
ret = drm_bind_ttm(ttm, new_mem);
if (ret)
return ret;
}
@ -102,11 +100,11 @@ EXPORT_SYMBOL(drm_bo_move_ttm);
* Call bo->mutex locked.
*/
int drm_mem_reg_ioremap(drm_device_t * dev, drm_bo_mem_reg_t * mem,
int drm_mem_reg_ioremap(struct drm_device * dev, struct drm_bo_mem_reg * mem,
void **virtual)
{
drm_buffer_manager_t *bm = &dev->bm;
drm_mem_type_manager_t *man = &bm->man[mem->mem_type];
struct drm_buffer_manager *bm = &dev->bm;
struct drm_mem_type_manager *man = &bm->man[mem->mem_type];
unsigned long bus_offset;
unsigned long bus_size;
unsigned long bus_base;
@ -128,6 +126,7 @@ int drm_mem_reg_ioremap(drm_device_t * dev, drm_bo_mem_reg_t * mem,
*virtual = addr;
return 0;
}
EXPORT_SYMBOL(drm_mem_reg_ioremap);
/**
* \c Unmap mapping obtained using drm_bo_ioremap
@ -137,11 +136,11 @@ int drm_mem_reg_ioremap(drm_device_t * dev, drm_bo_mem_reg_t * mem,
* Call bo->mutex locked.
*/
void drm_mem_reg_iounmap(drm_device_t * dev, drm_bo_mem_reg_t * mem,
void drm_mem_reg_iounmap(struct drm_device * dev, struct drm_bo_mem_reg * mem,
void *virtual)
{
drm_buffer_manager_t *bm;
drm_mem_type_manager_t *man;
struct drm_buffer_manager *bm;
struct drm_mem_type_manager *man;
bm = &dev->bm;
man = &bm->man[mem->mem_type];
@ -164,7 +163,7 @@ static int drm_copy_io_page(void *dst, void *src, unsigned long page)
return 0;
}
static int drm_copy_io_ttm_page(drm_ttm_t * ttm, void *src, unsigned long page)
static int drm_copy_io_ttm_page(struct drm_ttm * ttm, void *src, unsigned long page)
{
struct page *d = drm_ttm_get_page(ttm, page);
void *dst;
@ -182,7 +181,7 @@ static int drm_copy_io_ttm_page(drm_ttm_t * ttm, void *src, unsigned long page)
return 0;
}
static int drm_copy_ttm_io_page(drm_ttm_t * ttm, void *dst, unsigned long page)
static int drm_copy_ttm_io_page(struct drm_ttm * ttm, void *dst, unsigned long page)
{
struct page *s = drm_ttm_get_page(ttm, page);
void *src;
@ -200,19 +199,19 @@ static int drm_copy_ttm_io_page(drm_ttm_t * ttm, void *dst, unsigned long page)
return 0;
}
int drm_bo_move_memcpy(drm_buffer_object_t * bo,
int evict, int no_wait, drm_bo_mem_reg_t * new_mem)
int drm_bo_move_memcpy(struct drm_buffer_object * bo,
int evict, int no_wait, struct drm_bo_mem_reg * new_mem)
{
drm_device_t *dev = bo->dev;
drm_mem_type_manager_t *man = &dev->bm.man[new_mem->mem_type];
drm_ttm_t *ttm = bo->ttm;
drm_bo_mem_reg_t *old_mem = &bo->mem;
drm_bo_mem_reg_t old_copy = *old_mem;
struct drm_device *dev = bo->dev;
struct drm_mem_type_manager *man = &dev->bm.man[new_mem->mem_type];
struct drm_ttm *ttm = bo->ttm;
struct drm_bo_mem_reg *old_mem = &bo->mem;
struct drm_bo_mem_reg old_copy = *old_mem;
void *old_iomap;
void *new_iomap;
int ret;
uint32_t save_flags = old_mem->flags;
uint32_t save_mask = old_mem->mask;
uint64_t save_flags = old_mem->flags;
uint64_t save_mask = old_mem->mask;
unsigned long i;
unsigned long page;
unsigned long add = 0;
@ -281,12 +280,12 @@ EXPORT_SYMBOL(drm_bo_move_memcpy);
* object. Call bo->mutex locked.
*/
int drm_buffer_object_transfer(drm_buffer_object_t * bo,
drm_buffer_object_t ** new_obj)
int drm_buffer_object_transfer(struct drm_buffer_object * bo,
struct drm_buffer_object ** new_obj)
{
drm_buffer_object_t *fbo;
drm_device_t *dev = bo->dev;
drm_buffer_manager_t *bm = &dev->bm;
struct drm_buffer_object *fbo;
struct drm_device *dev = bo->dev;
struct drm_buffer_manager *bm = &dev->bm;
fbo = drm_ctl_calloc(1, sizeof(*fbo), DRM_MEM_BUFOBJ);
if (!fbo)
@ -306,7 +305,7 @@ int drm_buffer_object_transfer(drm_buffer_object_t * bo,
INIT_LIST_HEAD(&fbo->p_mm_list);
#endif
atomic_inc(&bo->fence->usage);
drm_fence_reference_unlocked(&fbo->fence, bo->fence);
fbo->pinned_node = NULL;
fbo->mem.mm_node->private = (void *)fbo;
atomic_set(&fbo->usage, 1);
@ -323,26 +322,27 @@ int drm_buffer_object_transfer(drm_buffer_object_t * bo,
* We cannot restart until it has finished.
*/
int drm_bo_move_accel_cleanup(drm_buffer_object_t * bo,
int drm_bo_move_accel_cleanup(struct drm_buffer_object * bo,
int evict,
int no_wait,
uint32_t fence_class,
uint32_t fence_type,
uint32_t fence_flags, drm_bo_mem_reg_t * new_mem)
uint32_t fence_flags, struct drm_bo_mem_reg * new_mem)
{
drm_device_t *dev = bo->dev;
drm_mem_type_manager_t *man = &dev->bm.man[new_mem->mem_type];
drm_bo_mem_reg_t *old_mem = &bo->mem;
struct drm_device *dev = bo->dev;
struct drm_mem_type_manager *man = &dev->bm.man[new_mem->mem_type];
struct drm_bo_mem_reg *old_mem = &bo->mem;
int ret;
uint32_t save_flags = old_mem->flags;
uint32_t save_mask = old_mem->mask;
drm_buffer_object_t *old_obj;
uint64_t save_flags = old_mem->flags;
uint64_t save_mask = old_mem->mask;
struct drm_buffer_object *old_obj;
if (bo->fence)
drm_fence_usage_deref_unlocked(dev, bo->fence);
drm_fence_usage_deref_unlocked(&bo->fence);
ret = drm_fence_object_create(dev, fence_class, fence_type,
fence_flags | DRM_FENCE_FLAG_EMIT,
&bo->fence);
bo->fence_type = fence_type;
if (ret)
return ret;
@ -396,7 +396,7 @@ int drm_bo_move_accel_cleanup(drm_buffer_object_t * bo,
DRM_FLAG_MASKED(bo->priv_flags, 0, _DRM_BO_FLAG_UNFENCED);
drm_bo_add_to_lru(old_obj);
drm_bo_usage_deref_locked(old_obj);
drm_bo_usage_deref_locked(&old_obj);
mutex_unlock(&dev->struct_mutex);
}
@ -409,3 +409,194 @@ int drm_bo_move_accel_cleanup(drm_buffer_object_t * bo,
}
EXPORT_SYMBOL(drm_bo_move_accel_cleanup);
int drm_bo_same_page(unsigned long offset,
unsigned long offset2)
{
return (offset & PAGE_MASK) == (offset2 & PAGE_MASK);
}
EXPORT_SYMBOL(drm_bo_same_page);
unsigned long drm_bo_offset_end(unsigned long offset,
unsigned long end)
{
offset = (offset + PAGE_SIZE) & PAGE_MASK;
return (end < offset) ? end : offset;
}
EXPORT_SYMBOL(drm_bo_offset_end);
static pgprot_t drm_kernel_io_prot(uint32_t map_type)
{
pgprot_t tmp = PAGE_KERNEL;
#if defined(__i386__) || defined(__x86_64__)
#ifdef USE_PAT_WC
#warning using pat
if (drm_use_pat() && map_type == _DRM_TTM) {
pgprot_val(tmp) |= _PAGE_PAT;
return tmp;
}
#endif
if (boot_cpu_data.x86 > 3 && map_type != _DRM_AGP) {
pgprot_val(tmp) |= _PAGE_PCD;
pgprot_val(tmp) &= ~_PAGE_PWT;
}
#elif defined(__powerpc__)
pgprot_val(tmp) |= _PAGE_NO_CACHE;
if (map_type == _DRM_REGISTERS)
pgprot_val(tmp) |= _PAGE_GUARDED;
#endif
#if defined(__ia64__)
if (map_type == _DRM_TTM)
tmp = pgprot_writecombine(tmp);
else
tmp = pgprot_noncached(tmp);
#endif
return tmp;
}
static int drm_bo_ioremap(struct drm_buffer_object *bo, unsigned long bus_base,
unsigned long bus_offset, unsigned long bus_size,
struct drm_bo_kmap_obj *map)
{
struct drm_device *dev = bo->dev;
struct drm_bo_mem_reg *mem = &bo->mem;
struct drm_mem_type_manager *man = &dev->bm.man[mem->mem_type];
if (!(man->flags & _DRM_FLAG_NEEDS_IOREMAP)) {
map->bo_kmap_type = bo_map_premapped;
map->virtual = (void *)(((u8 *) man->io_addr) + bus_offset);
} else {
map->bo_kmap_type = bo_map_iomap;
map->virtual = ioremap_nocache(bus_base + bus_offset, bus_size);
}
return (!map->virtual) ? -ENOMEM : 0;
}
static int drm_bo_kmap_ttm(struct drm_buffer_object *bo, unsigned long start_page,
unsigned long num_pages, struct drm_bo_kmap_obj *map)
{
struct drm_device *dev = bo->dev;
struct drm_bo_mem_reg *mem = &bo->mem;
struct drm_mem_type_manager *man = &dev->bm.man[mem->mem_type];
pgprot_t prot;
struct drm_ttm *ttm = bo->ttm;
struct page *d;
int i;
BUG_ON(!ttm);
if (num_pages == 1 && (mem->flags & DRM_BO_FLAG_CACHED)) {
/*
* We're mapping a single page, and the desired
* page protection is consistent with the bo.
*/
map->bo_kmap_type = bo_map_kmap;
map->page = drm_ttm_get_page(ttm, start_page);
map->virtual = kmap(map->page);
} else {
/*
* Populate the part we're mapping;
*/
for (i = start_page; i< start_page + num_pages; ++i) {
d = drm_ttm_get_page(ttm, i);
if (!d)
return -ENOMEM;
}
/*
* We need to use vmap to get the desired page protection
* or to make the buffer object look contigous.
*/
prot = (mem->flags & DRM_BO_FLAG_CACHED) ?
PAGE_KERNEL :
drm_kernel_io_prot(man->drm_bus_maptype);
map->bo_kmap_type = bo_map_vmap;
map->virtual = vmap(ttm->pages + start_page,
num_pages, 0, prot);
}
return (!map->virtual) ? -ENOMEM : 0;
}
/*
* This function is to be used for kernel mapping of buffer objects.
* It chooses the appropriate mapping method depending on the memory type
* and caching policy the buffer currently has.
* Mapping multiple pages or buffers that live in io memory is a bit slow and
* consumes vmalloc space. Be restrictive with such mappings.
* Mapping single pages usually returns the logical kernel address, (which is fast)
* BUG may use slower temporary mappings for high memory pages or
* uncached / write-combined pages.
*
* The function fills in a drm_bo_kmap_obj which can be used to return the
* kernel virtual address of the buffer.
*
* Code servicing a non-priviliged user request is only allowed to map one
* page at a time. We might need to implement a better scheme to stop such
* processes from consuming all vmalloc space.
*/
int drm_bo_kmap(struct drm_buffer_object *bo, unsigned long start_page,
unsigned long num_pages, struct drm_bo_kmap_obj *map)
{
int ret;
unsigned long bus_base;
unsigned long bus_offset;
unsigned long bus_size;
map->virtual = NULL;
if (num_pages > bo->num_pages)
return -EINVAL;
if (start_page > bo->num_pages)
return -EINVAL;
#if 0
if (num_pages > 1 && !DRM_SUSER(DRM_CURPROC))
return -EPERM;
#endif
ret = drm_bo_pci_offset(bo->dev, &bo->mem, &bus_base,
&bus_offset, &bus_size);
if (ret)
return ret;
if (bus_size == 0) {
return drm_bo_kmap_ttm(bo, start_page, num_pages, map);
} else {
bus_offset += start_page << PAGE_SHIFT;
bus_size = num_pages << PAGE_SHIFT;
return drm_bo_ioremap(bo, bus_base, bus_offset, bus_size, map);
}
}
EXPORT_SYMBOL(drm_bo_kmap);
void drm_bo_kunmap(struct drm_bo_kmap_obj *map)
{
if (!map->virtual)
return;
switch(map->bo_kmap_type) {
case bo_map_iomap:
iounmap(map->virtual);
break;
case bo_map_vmap:
vunmap(map->virtual);
break;
case bo_map_kmap:
kunmap(map->page);
break;
case bo_map_premapped:
break;
default:
BUG();
}
map->virtual = NULL;
map->page = NULL;
}
EXPORT_SYMBOL(drm_bo_kunmap);

View File

@ -36,22 +36,21 @@
#include <linux/vmalloc.h>
#include "drmP.h"
unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)
unsigned long drm_get_resource_start(struct drm_device *dev, unsigned int resource)
{
return pci_resource_start(dev->pdev, resource);
}
EXPORT_SYMBOL(drm_get_resource_start);
unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)
unsigned long drm_get_resource_len(struct drm_device *dev, unsigned int resource)
{
return pci_resource_len(dev->pdev, resource);
}
EXPORT_SYMBOL(drm_get_resource_len);
static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
drm_local_map_t *map)
struct drm_map_list *drm_find_matching_map(struct drm_device *dev, drm_local_map_t *map)
{
drm_map_list_t *entry;
struct drm_map_list *entry;
list_for_each_entry(entry, &dev->maplist, head) {
if (entry->map && map->type == entry->map->type &&
((entry->map->offset == map->offset) ||
@ -62,8 +61,9 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
return NULL;
}
EXPORT_SYMBOL(drm_find_matching_map);
static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash,
static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash,
unsigned long user_token, int hashed_handle)
{
int use_hashed_handle;
@ -92,7 +92,7 @@ static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash,
* Ioctl to specify a range of memory that is available for mapping by a non-root process.
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg pointer to a drm_map structure.
* \return zero on success or a negative value on error.
@ -101,12 +101,13 @@ static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash,
* type. Adds the map to the map list drm_device::maplist. Adds MTRR's where
* applicable and if supported by the kernel.
*/
static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
unsigned int size, drm_map_type_t type,
drm_map_flags_t flags, drm_map_list_t ** maplist)
static int drm_addmap_core(struct drm_device *dev, unsigned int offset,
unsigned int size, enum drm_map_type type,
enum drm_map_flags flags,
struct drm_map_list **maplist)
{
drm_map_t *map;
drm_map_list_t *list;
struct drm_map *map;
struct drm_map_list *list;
drm_dma_handle_t *dmah;
unsigned long user_token;
int ret;
@ -212,7 +213,7 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
}
break;
case _DRM_AGP: {
drm_agp_mem_t *entry;
struct drm_agp_mem *entry;
int valid = 0;
if (!drm_core_has_AGP(dev)) {
@ -222,11 +223,17 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
#ifdef __alpha__
map->offset += dev->hose->mem_space->start;
#endif
/* Note: dev->agp->base may actually be 0 when the DRM
* is not in control of AGP space. But if user space is
* it should already have added the AGP base itself.
/* In some cases (i810 driver), user space may have already
* added the AGP base itself, because dev->agp->base previously
* only got set during AGP enable. So, only add the base
* address if the map's offset isn't already within the
* aperture.
*/
map->offset += dev->agp->base;
if (map->offset < dev->agp->base ||
map->offset > dev->agp->base +
dev->agp->agp_info.aper_size * 1024 * 1024 - 1) {
map->offset += dev->agp->base;
}
map->mtrr = dev->agp->agp_mtrr; /* for getmap */
/* This assumes the DRM is in total control of AGP space.
@ -310,11 +317,11 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
return 0;
}
int drm_addmap(drm_device_t * dev, unsigned int offset,
unsigned int size, drm_map_type_t type,
drm_map_flags_t flags, drm_local_map_t ** map_ptr)
int drm_addmap(struct drm_device *dev, unsigned int offset,
unsigned int size, enum drm_map_type type,
enum drm_map_flags flags, drm_local_map_t ** map_ptr)
{
drm_map_list_t *list;
struct drm_map_list *list;
int rc;
rc = drm_addmap_core(dev, offset, size, type, flags, &list);
@ -325,38 +332,24 @@ int drm_addmap(drm_device_t * dev, unsigned int offset,
EXPORT_SYMBOL(drm_addmap);
int drm_addmap_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_addmap_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_map_t map;
drm_map_list_t *maplist;
drm_map_t __user *argp = (void __user *)arg;
struct drm_map *map = data;
struct drm_map_list *maplist;
int err;
if (!(filp->f_mode & 3))
return -EACCES; /* Require read/write */
if (copy_from_user(&map, argp, sizeof(map))) {
return -EFAULT;
}
if (!(capable(CAP_SYS_ADMIN) || map.type == _DRM_AGP))
if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP))
return -EPERM;
err = drm_addmap_core(dev, map.offset, map.size, map.type, map.flags,
&maplist);
err = drm_addmap_core(dev, map->offset, map->size, map->type,
map->flags, &maplist);
if (err)
return err;
if (copy_to_user(argp, maplist->map, sizeof(drm_map_t)))
return -EFAULT;
/* avoid a warning on 64-bit, this casting isn't very nice, but the API is set so too late */
if (put_user((void *)(unsigned long)maplist->user_token, &argp->handle))
return -EFAULT;
map->handle = (void *)(unsigned long)maplist->user_token;
return 0;
}
@ -365,9 +358,9 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
* isn't in use.
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg pointer to a drm_map_t structure.
* \param arg pointer to a struct drm_map structure.
* \return zero on success or a negative value on error.
*
* Searches the map on drm_device::maplist, removes it from the list, see if
@ -376,9 +369,9 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
*
* \sa drm_addmap
*/
int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)
{
drm_map_list_t *r_list = NULL, *list_t;
struct drm_map_list *r_list = NULL, *list_t;
drm_dma_handle_t dmah;
int found = 0;
@ -433,7 +426,7 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
}
EXPORT_SYMBOL(drm_rmmap_locked);
int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
int drm_rmmap(struct drm_device *dev, drm_local_map_t *map)
{
int ret;
@ -454,24 +447,18 @@ EXPORT_SYMBOL(drm_rmmap);
* gets used by drivers that the server doesn't need to care about. This seems
* unlikely.
*/
int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_rmmap_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_map_t request;
struct drm_map *request = data;
drm_local_map_t *map = NULL;
drm_map_list_t *r_list;
struct drm_map_list *r_list;
int ret;
if (copy_from_user(&request, (drm_map_t __user *) arg, sizeof(request))) {
return -EFAULT;
}
mutex_lock(&dev->struct_mutex);
list_for_each_entry(r_list, &dev->maplist, head) {
if (r_list->map &&
r_list->user_token == (unsigned long)request.handle &&
r_list->user_token == (unsigned long)request->handle &&
r_list->map->flags & _DRM_REMOVABLE) {
map = r_list->map;
break;
@ -486,11 +473,6 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
return -EINVAL;
}
if (!map) {
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
/* Register and framebuffer maps are permanent */
if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
mutex_unlock(&dev->struct_mutex);
@ -512,7 +494,7 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
*
* Frees any pages and buffers associated with the given entry.
*/
static void drm_cleanup_buf_error(drm_device_t * dev, drm_buf_entry_t * entry)
static void drm_cleanup_buf_error(struct drm_device *dev, struct drm_buf_entry * entry)
{
int i;
@ -549,20 +531,20 @@ static void drm_cleanup_buf_error(drm_device_t * dev, drm_buf_entry_t * entry)
/**
* Add AGP buffers for DMA transfers
*
* \param dev drm_device_t to which the buffers are to be added.
* \param request pointer to a drm_buf_desc_t describing the request.
* \param dev struct drm_device to which the buffers are to be added.
* \param request pointer to a struct drm_buf_desc describing the request.
* \return zero on success or a negative number on failure.
*
* After some sanity checks creates a drm_buf structure for each buffer and
* reallocates the buffer list of the same size order to accommodate the new
* buffers.
*/
int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc * request)
{
drm_device_dma_t *dma = dev->dma;
drm_buf_entry_t *entry;
drm_agp_mem_t *agp_entry;
drm_buf_t *buf;
struct drm_device_dma *dma = dev->dma;
struct drm_buf_entry *entry;
struct drm_agp_mem *agp_entry;
struct drm_buf *buf;
unsigned long offset;
unsigned long agp_offset;
int count;
@ -573,7 +555,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
int total;
int byte_count;
int i, valid;
drm_buf_t **temp_buflist;
struct drm_buf **temp_buflist;
if (!dma)
return -EINVAL;
@ -666,7 +648,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
buf->waiting = 0;
buf->pending = 0;
init_waitqueue_head(&buf->dma_wait);
buf->filp = NULL;
buf->file_priv = NULL;
buf->dev_priv_size = dev->driver->dev_priv_size;
buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
@ -727,24 +709,24 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
EXPORT_SYMBOL(drm_addbufs_agp);
#endif /* __OS_HAS_AGP */
int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc * request)
{
drm_device_dma_t *dma = dev->dma;
struct drm_device_dma *dma = dev->dma;
int count;
int order;
int size;
int total;
int page_order;
drm_buf_entry_t *entry;
struct drm_buf_entry *entry;
drm_dma_handle_t *dmah;
drm_buf_t *buf;
struct drm_buf *buf;
int alignment;
unsigned long offset;
int i;
int byte_count;
int page_count;
unsigned long *temp_pagelist;
drm_buf_t **temp_buflist;
struct drm_buf **temp_buflist;
if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))
return -EINVAL;
@ -877,7 +859,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
buf->waiting = 0;
buf->pending = 0;
init_waitqueue_head(&buf->dma_wait);
buf->filp = NULL;
buf->file_priv = NULL;
buf->dev_priv_size = dev->driver->dev_priv_size;
buf->dev_private = drm_alloc(buf->dev_priv_size,
@ -953,11 +935,11 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
}
EXPORT_SYMBOL(drm_addbufs_pci);
static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
static int drm_addbufs_sg(struct drm_device *dev, struct drm_buf_desc * request)
{
drm_device_dma_t *dma = dev->dma;
drm_buf_entry_t *entry;
drm_buf_t *buf;
struct drm_device_dma *dma = dev->dma;
struct drm_buf_entry *entry;
struct drm_buf *buf;
unsigned long offset;
unsigned long agp_offset;
int count;
@ -968,7 +950,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
int total;
int byte_count;
int i;
drm_buf_t **temp_buflist;
struct drm_buf **temp_buflist;
if (!drm_core_check_feature(dev, DRIVER_SG))
return -EINVAL;
@ -1055,7 +1037,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
buf->waiting = 0;
buf->pending = 0;
init_waitqueue_head(&buf->dma_wait);
buf->filp = NULL;
buf->file_priv = NULL;
buf->dev_priv_size = dev->driver->dev_priv_size;
buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
@ -1115,11 +1097,11 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
return 0;
}
int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
int drm_addbufs_fb(struct drm_device *dev, struct drm_buf_desc *request)
{
drm_device_dma_t *dma = dev->dma;
drm_buf_entry_t *entry;
drm_buf_t *buf;
struct drm_device_dma *dma = dev->dma;
struct drm_buf_entry *entry;
struct drm_buf *buf;
unsigned long offset;
unsigned long agp_offset;
int count;
@ -1130,7 +1112,7 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
int total;
int byte_count;
int i;
drm_buf_t **temp_buflist;
struct drm_buf **temp_buflist;
if (!drm_core_check_feature(dev, DRIVER_FB_DMA))
return -EINVAL;
@ -1216,7 +1198,7 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
buf->waiting = 0;
buf->pending = 0;
init_waitqueue_head(&buf->dma_wait);
buf->filp = NULL;
buf->file_priv = NULL;
buf->dev_priv_size = dev->driver->dev_priv_size;
buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
@ -1281,9 +1263,9 @@ EXPORT_SYMBOL(drm_addbufs_fb);
* Add buffers for DMA transfers (ioctl).
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg pointer to a drm_buf_desc_t request.
* \param arg pointer to a struct drm_buf_desc request.
* \return zero on success or a negative number on failure.
*
* According with the memory type specified in drm_buf_desc::flags and the
@ -1291,39 +1273,27 @@ EXPORT_SYMBOL(drm_addbufs_fb);
* addbufs_sg() or addbufs_pci() for AGP, scatter-gather or consistent
* PCI memory respectively.
*/
int drm_addbufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_addbufs(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_buf_desc_t request;
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
struct drm_buf_desc *request = data;
int ret;
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
return -EINVAL;
if (copy_from_user(&request, (drm_buf_desc_t __user *) arg,
sizeof(request)))
return -EFAULT;
#if __OS_HAS_AGP
if (request.flags & _DRM_AGP_BUFFER)
ret = drm_addbufs_agp(dev, &request);
if (request->flags & _DRM_AGP_BUFFER)
ret = drm_addbufs_agp(dev, request);
else
#endif
if (request.flags & _DRM_SG_BUFFER)
ret = drm_addbufs_sg(dev, &request);
else if (request.flags & _DRM_FB_BUFFER)
ret = drm_addbufs_fb(dev, &request);
if (request->flags & _DRM_SG_BUFFER)
ret = drm_addbufs_sg(dev, request);
else if (request->flags & _DRM_FB_BUFFER)
ret = drm_addbufs_fb(dev, request);
else
ret = drm_addbufs_pci(dev, &request);
ret = drm_addbufs_pci(dev, request);
if (ret == 0) {
if (copy_to_user((void __user *) arg, &request,
sizeof(request))) {
ret = -EFAULT;
}
}
return ret;
}
@ -1335,7 +1305,7 @@ int drm_addbufs(struct inode *inode, struct file *filp,
* large buffers can be used for image transfer).
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg pointer to a drm_buf_info structure.
* \return zero on success or a negative number on failure.
@ -1344,14 +1314,11 @@ int drm_addbufs(struct inode *inode, struct file *filp,
* lock, preventing of allocating more buffers after this call. Information
* about each requested buffer is then copied into user space.
*/
int drm_infobufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_infobufs(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
drm_buf_info_t request;
drm_buf_info_t __user *argp = (void __user *)arg;
struct drm_device_dma *dma = dev->dma;
struct drm_buf_info *request = data;
int i;
int count;
@ -1369,9 +1336,6 @@ int drm_infobufs(struct inode *inode, struct file *filp,
++dev->buf_use; /* Can't allocate more after this call */
spin_unlock(&dev->count_lock);
if (copy_from_user(&request, argp, sizeof(request)))
return -EFAULT;
for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
if (dma->bufs[i].buf_count)
++count;
@ -1379,13 +1343,13 @@ int drm_infobufs(struct inode *inode, struct file *filp,
DRM_DEBUG("count = %d\n", count);
if (request.count >= count) {
if (request->count >= count) {
for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
if (dma->bufs[i].buf_count) {
drm_buf_desc_t __user *to =
&request.list[count];
drm_buf_entry_t *from = &dma->bufs[i];
drm_freelist_t *list = &dma->bufs[i].freelist;
struct drm_buf_desc __user *to =
&request->list[count];
struct drm_buf_entry *from = &dma->bufs[i];
struct drm_freelist *list = &dma->bufs[i].freelist;
if (copy_to_user(&to->count,
&from->buf_count,
sizeof(from->buf_count)) ||
@ -1410,10 +1374,7 @@ int drm_infobufs(struct inode *inode, struct file *filp,
}
}
}
request.count = count;
if (copy_to_user(argp, &request, sizeof(request)))
return -EFAULT;
request->count = count;
return 0;
}
@ -1422,7 +1383,7 @@ int drm_infobufs(struct inode *inode, struct file *filp,
* Specifies a low and high water mark for buffer allocation
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg a pointer to a drm_buf_desc structure.
* \return zero on success or a negative number on failure.
@ -1432,15 +1393,13 @@ int drm_infobufs(struct inode *inode, struct file *filp,
*
* \note This ioctl is deprecated and mostly never used.
*/
int drm_markbufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_markbufs(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
drm_buf_desc_t request;
struct drm_device_dma *dma = dev->dma;
struct drm_buf_desc *request = data;
int order;
drm_buf_entry_t *entry;
struct drm_buf_entry *entry;
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
return -EINVAL;
@ -1448,24 +1407,20 @@ int drm_markbufs(struct inode *inode, struct file *filp,
if (!dma)
return -EINVAL;
if (copy_from_user(&request,
(drm_buf_desc_t __user *) arg, sizeof(request)))
return -EFAULT;
DRM_DEBUG("%d, %d, %d\n",
request.size, request.low_mark, request.high_mark);
order = drm_order(request.size);
request->size, request->low_mark, request->high_mark);
order = drm_order(request->size);
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
return -EINVAL;
entry = &dma->bufs[order];
if (request.low_mark < 0 || request.low_mark > entry->buf_count)
if (request->low_mark < 0 || request->low_mark > entry->buf_count)
return -EINVAL;
if (request.high_mark < 0 || request.high_mark > entry->buf_count)
if (request->high_mark < 0 || request->high_mark > entry->buf_count)
return -EINVAL;
entry->freelist.low_mark = request.low_mark;
entry->freelist.high_mark = request.high_mark;
entry->freelist.low_mark = request->low_mark;
entry->freelist.high_mark = request->high_mark;
return 0;
}
@ -1474,7 +1429,7 @@ int drm_markbufs(struct inode *inode, struct file *filp,
* Unreserve the buffers in list, previously reserved using drmDMA.
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg pointer to a drm_buf_free structure.
* \return zero on success or a negative number on failure.
@ -1482,16 +1437,14 @@ int drm_markbufs(struct inode *inode, struct file *filp,
* Calls free_buffer() for each used buffer.
* This function is primarily used for debugging.
*/
int drm_freebufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_freebufs(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
drm_buf_free_t request;
struct drm_device_dma *dma = dev->dma;
struct drm_buf_free *request = data;
int i;
int idx;
drm_buf_t *buf;
struct drm_buf *buf;
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
return -EINVAL;
@ -1499,13 +1452,9 @@ int drm_freebufs(struct inode *inode, struct file *filp,
if (!dma)
return -EINVAL;
if (copy_from_user(&request,
(drm_buf_free_t __user *) arg, sizeof(request)))
return -EFAULT;
DRM_DEBUG("%d\n", request.count);
for (i = 0; i < request.count; i++) {
if (copy_from_user(&idx, &request.list[i], sizeof(idx)))
DRM_DEBUG("%d\n", request->count);
for (i = 0; i < request->count; i++) {
if (copy_from_user(&idx, &request->list[i], sizeof(idx)))
return -EFAULT;
if (idx < 0 || idx >= dma->buf_count) {
DRM_ERROR("Index %d (of %d max)\n",
@ -1513,7 +1462,7 @@ int drm_freebufs(struct inode *inode, struct file *filp,
return -EINVAL;
}
buf = dma->buflist[idx];
if (buf->filp != filp) {
if (buf->file_priv != file_priv) {
DRM_ERROR("Process %d freeing buffer not owned\n",
current->pid);
return -EINVAL;
@ -1528,7 +1477,7 @@ int drm_freebufs(struct inode *inode, struct file *filp,
* Maps all of the DMA buffers into client-virtual space (ioctl).
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg pointer to a drm_buf_map structure.
* \return zero on success or a negative number on failure.
@ -1538,18 +1487,15 @@ int drm_freebufs(struct inode *inode, struct file *filp,
* offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
* drm_mmap_dma().
*/
int drm_mapbufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_mapbufs(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
drm_buf_map_t __user *argp = (void __user *)arg;
struct drm_device_dma *dma = dev->dma;
int retcode = 0;
const int zero = 0;
unsigned long virtual;
unsigned long address;
drm_buf_map_t request;
struct drm_buf_map *request = data;
int i;
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
@ -1566,16 +1512,13 @@ int drm_mapbufs(struct inode *inode, struct file *filp,
dev->buf_use++; /* Can't allocate more after this call */
spin_unlock(&dev->count_lock);
if (copy_from_user(&request, argp, sizeof(request)))
return -EFAULT;
if (request.count >= dma->buf_count) {
if (request->count >= dma->buf_count) {
if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP))
|| (drm_core_check_feature(dev, DRIVER_SG)
&& (dma->flags & _DRM_DMA_USE_SG))
|| (drm_core_check_feature(dev, DRIVER_FB_DMA)
&& (dma->flags & _DRM_DMA_USE_FB))) {
drm_map_t *map = dev->agp_buffer_map;
struct drm_map *map = dev->agp_buffer_map;
unsigned long token = dev->agp_buffer_token;
if (!map) {
@ -1583,14 +1526,14 @@ int drm_mapbufs(struct inode *inode, struct file *filp,
goto done;
}
down_write(&current->mm->mmap_sem);
virtual = do_mmap(filp, 0, map->size,
virtual = do_mmap(file_priv->filp, 0, map->size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
token);
up_write(&current->mm->mmap_sem);
} else {
down_write(&current->mm->mmap_sem);
virtual = do_mmap(filp, 0, dma->byte_count,
virtual = do_mmap(file_priv->filp, 0, dma->byte_count,
PROT_READ | PROT_WRITE,
MAP_SHARED, 0);
up_write(&current->mm->mmap_sem);
@ -1600,28 +1543,28 @@ int drm_mapbufs(struct inode *inode, struct file *filp,
retcode = (signed long)virtual;
goto done;
}
request.virtual = (void __user *)virtual;
request->virtual = (void __user *)virtual;
for (i = 0; i < dma->buf_count; i++) {
if (copy_to_user(&request.list[i].idx,
if (copy_to_user(&request->list[i].idx,
&dma->buflist[i]->idx,
sizeof(request.list[0].idx))) {
sizeof(request->list[0].idx))) {
retcode = -EFAULT;
goto done;
}
if (copy_to_user(&request.list[i].total,
if (copy_to_user(&request->list[i].total,
&dma->buflist[i]->total,
sizeof(request.list[0].total))) {
sizeof(request->list[0].total))) {
retcode = -EFAULT;
goto done;
}
if (copy_to_user(&request.list[i].used,
if (copy_to_user(&request->list[i].used,
&zero, sizeof(zero))) {
retcode = -EFAULT;
goto done;
}
address = virtual + dma->buflist[i]->offset; /* *** */
if (copy_to_user(&request.list[i].address,
if (copy_to_user(&request->list[i].address,
&address, sizeof(address))) {
retcode = -EFAULT;
goto done;
@ -1629,11 +1572,8 @@ int drm_mapbufs(struct inode *inode, struct file *filp,
}
}
done:
request.count = dma->buf_count;
DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
if (copy_to_user(argp, &request, sizeof(request)))
return -EFAULT;
request->count = dma->buf_count;
DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode);
return retcode;
}

View File

@ -196,21 +196,24 @@ static int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
return ret;
}
static struct page *drm_bo_vm_fault(struct vm_area_struct *vma,
struct fault_data *data)
{
unsigned long address = data->address;
drm_buffer_object_t *bo = (drm_buffer_object_t *) vma->vm_private_data;
struct drm_buffer_object *bo = (struct drm_buffer_object *) vma->vm_private_data;
unsigned long page_offset;
struct page *page = NULL;
drm_ttm_t *ttm;
drm_device_t *dev;
struct drm_ttm *ttm;
struct drm_device *dev;
unsigned long pfn;
int err;
unsigned long bus_base;
unsigned long bus_offset;
unsigned long bus_size;
dev = bo->dev;
while(drm_bo_read_lock(&dev->bm.bm_lock));
mutex_lock(&bo->mutex);
@ -261,7 +264,7 @@ static struct page *drm_bo_vm_fault(struct vm_area_struct *vma,
page_offset = (address - vma->vm_start) >> PAGE_SHIFT;
if (bus_size) {
drm_mem_type_manager_t *man = &dev->bm.man[bo->mem.mem_type];
struct drm_mem_type_manager *man = &dev->bm.man[bo->mem.mem_type];
pfn = ((bus_base + bus_offset) >> PAGE_SHIFT) + page_offset;
vma->vm_page_prot = drm_io_prot(man->drm_bus_maptype, vma);
@ -288,6 +291,7 @@ static struct page *drm_bo_vm_fault(struct vm_area_struct *vma,
data->type = VM_FAULT_OOM;
out_unlock:
mutex_unlock(&bo->mutex);
drm_bo_read_unlock(&dev->bm.bm_lock);
return NULL;
}
@ -350,11 +354,11 @@ struct page *drm_bo_vm_nopage(struct vm_area_struct *vma,
unsigned long address,
int *type)
{
drm_buffer_object_t *bo = (drm_buffer_object_t *) vma->vm_private_data;
struct drm_buffer_object *bo = (struct drm_buffer_object *) vma->vm_private_data;
unsigned long page_offset;
struct page *page;
drm_ttm_t *ttm;
drm_device_t *dev;
struct drm_ttm *ttm;
struct drm_device *dev;
mutex_lock(&bo->mutex);
@ -394,7 +398,7 @@ out_unlock:
int drm_bo_map_bound(struct vm_area_struct *vma)
{
drm_buffer_object_t *bo = (drm_buffer_object_t *)vma->vm_private_data;
struct drm_buffer_object *bo = (struct drm_buffer_object *)vma->vm_private_data;
int ret = 0;
unsigned long bus_base;
unsigned long bus_offset;
@ -405,7 +409,7 @@ int drm_bo_map_bound(struct vm_area_struct *vma)
BUG_ON(ret);
if (bus_size) {
drm_mem_type_manager_t *man = &bo->dev->bm.man[bo->mem.mem_type];
struct drm_mem_type_manager *man = &bo->dev->bm.man[bo->mem.mem_type];
unsigned long pfn = (bus_base + bus_offset) >> PAGE_SHIFT;
pgprot_t pgprot = drm_io_prot(man->drm_bus_maptype, vma);
ret = io_remap_pfn_range(vma, vma->vm_start, pfn,
@ -417,7 +421,7 @@ int drm_bo_map_bound(struct vm_area_struct *vma)
}
int drm_bo_add_vma(drm_buffer_object_t * bo, struct vm_area_struct *vma)
int drm_bo_add_vma(struct drm_buffer_object * bo, struct vm_area_struct *vma)
{
p_mm_entry_t *entry, *n_entry;
vma_entry_t *v_entry;
@ -453,7 +457,7 @@ int drm_bo_add_vma(drm_buffer_object_t * bo, struct vm_area_struct *vma)
return 0;
}
void drm_bo_delete_vma(drm_buffer_object_t * bo, struct vm_area_struct *vma)
void drm_bo_delete_vma(struct drm_buffer_object * bo, struct vm_area_struct *vma)
{
p_mm_entry_t *entry, *n;
vma_entry_t *v_entry, *v_n;
@ -485,7 +489,7 @@ void drm_bo_delete_vma(drm_buffer_object_t * bo, struct vm_area_struct *vma)
int drm_bo_lock_kmm(drm_buffer_object_t * bo)
int drm_bo_lock_kmm(struct drm_buffer_object * bo)
{
p_mm_entry_t *entry;
int lock_ok = 1;
@ -517,7 +521,7 @@ int drm_bo_lock_kmm(drm_buffer_object_t * bo)
return -EAGAIN;
}
void drm_bo_unlock_kmm(drm_buffer_object_t * bo)
void drm_bo_unlock_kmm(struct drm_buffer_object * bo)
{
p_mm_entry_t *entry;
@ -528,7 +532,7 @@ void drm_bo_unlock_kmm(drm_buffer_object_t * bo)
}
}
int drm_bo_remap_bound(drm_buffer_object_t *bo)
int drm_bo_remap_bound(struct drm_buffer_object *bo)
{
vma_entry_t *v_entry;
int ret = 0;
@ -544,7 +548,7 @@ int drm_bo_remap_bound(drm_buffer_object_t *bo)
return ret;
}
void drm_bo_finish_unmap(drm_buffer_object_t *bo)
void drm_bo_finish_unmap(struct drm_buffer_object *bo)
{
vma_entry_t *v_entry;
@ -677,4 +681,51 @@ void idr_remove_all(struct idr *idp)
idp->layers = 0;
}
EXPORT_SYMBOL(idr_remove_all);
#endif /* DRM_IDR_COMPAT_FN */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
/**
* idr_replace - replace pointer for given id
* @idp: idr handle
* @ptr: pointer you want associated with the id
* @id: lookup key
*
* Replace the pointer registered with an id and return the old value.
* A -ENOENT return indicates that @id was not found.
* A -EINVAL return indicates that @id was not within valid constraints.
*
* The caller must serialize vs idr_find(), idr_get_new(), and idr_remove().
*/
void *idr_replace(struct idr *idp, void *ptr, int id)
{
int n;
struct idr_layer *p, *old_p;
n = idp->layers * IDR_BITS;
p = idp->top;
id &= MAX_ID_MASK;
if (id >= (1 << n))
return ERR_PTR(-EINVAL);
n -= IDR_BITS;
while ((n > 0) && p) {
p = p->ary[(id >> n) & IDR_MASK];
n -= IDR_BITS;
}
n = id & IDR_MASK;
if (unlikely(p == NULL || !test_bit(n, &p->bitmap)))
return ERR_PTR(-ENOENT);
old_p = p->ary[n];
p->ary[n] = ptr;
return (void *)old_p;
}
EXPORT_SYMBOL(idr_replace);
#endif

View File

@ -193,7 +193,10 @@ extern void drm_clear_vma(struct vm_area_struct *vma,
extern pgprot_t vm_get_page_prot(unsigned long vm_flags);
#ifndef GFP_DMA32
#define GFP_DMA32 0
#define GFP_DMA32 GFP_KERNEL
#endif
#ifndef __GFP_DMA32
#define __GFP_DMA32 GFP_KERNEL
#endif
#if defined(CONFIG_X86) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
@ -306,12 +309,23 @@ extern int drm_bo_map_bound(struct vm_area_struct *vma);
#endif
/* fixme when functions are upstreamed */
/* fixme when functions are upstreamed - upstreamed for 2.6.23 */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23))
#define DRM_IDR_COMPAT_FN
#endif
#ifdef DRM_IDR_COMPAT_FN
int idr_for_each(struct idr *idp,
int (*fn)(int id, void *p, void *data), void *data);
void idr_remove_all(struct idr *idp);
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
void *idr_replace(struct idr *idp, void *ptr, int id);
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
typedef _Bool bool;
#endif
#endif

View File

@ -56,19 +56,11 @@
* in drm_device::ctx_idr, while holding the drm_device::struct_mutex
* lock.
*/
void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle)
{
struct drm_ctx_sarea_list *ctx;
mutex_lock(&dev->struct_mutex);
ctx = idr_find(&dev->ctx_idr, ctx_handle);
if (ctx) {
idr_remove(&dev->ctx_idr, ctx_handle);
drm_free(ctx, sizeof(struct drm_ctx_sarea_list), DRM_MEM_CTXLIST);
} else
DRM_ERROR("Attempt to free invalid context handle: %d\n", ctx_handle);
idr_remove(&dev->ctx_idr, ctx_handle);
mutex_unlock(&dev->struct_mutex);
return;
}
/**
@ -80,24 +72,19 @@ void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
* Allocate a new idr from drm_device::ctx_idr while holding the
* drm_device::struct_mutex lock.
*/
static int drm_ctxbitmap_next(drm_device_t * dev)
static int drm_ctxbitmap_next(struct drm_device *dev)
{
int new_id;
int ret;
struct drm_ctx_sarea_list *new_ctx;
new_ctx = drm_calloc(1, sizeof(struct drm_ctx_sarea_list), DRM_MEM_CTXLIST);
if (!new_ctx)
return -1;
again:
if (idr_pre_get(&dev->ctx_idr, GFP_KERNEL) == 0) {
DRM_ERROR("Out of memory expanding drawable idr\n");
drm_free(new_ctx, sizeof(struct drm_ctx_sarea_list), DRM_MEM_CTXLIST);
return -ENOMEM;
}
mutex_lock(&dev->struct_mutex);
ret = idr_get_new_above(&dev->ctx_idr, new_ctx, DRM_RESERVED_CONTEXTS, &new_id);
ret = idr_get_new_above(&dev->ctx_idr, NULL,
DRM_RESERVED_CONTEXTS, &new_id);
if (ret == -EAGAIN) {
mutex_unlock(&dev->struct_mutex);
goto again;
@ -114,21 +101,12 @@ again:
*
* Initialise the drm_device::ctx_idr
*/
int drm_ctxbitmap_init(drm_device_t * dev)
int drm_ctxbitmap_init(struct drm_device *dev)
{
idr_init(&dev->ctx_idr);
return 0;
}
static int drm_ctx_sarea_free(int id, void *p, void *data)
{
struct drm_ctx_sarea_list *ctx_entry = p;
drm_free(ctx_entry, sizeof(struct drm_ctx_sarea_list), DRM_MEM_CTXLIST);
return 0;
}
/**
* Context bitmap cleanup.
*
@ -137,10 +115,9 @@ static int drm_ctx_sarea_free(int id, void *p, void *data)
* Free all idr members using drm_ctx_sarea_free helper function
* while holding the drm_device::struct_mutex lock.
*/
void drm_ctxbitmap_cleanup(drm_device_t * dev)
void drm_ctxbitmap_cleanup(struct drm_device *dev)
{
mutex_lock(&dev->struct_mutex);
idr_for_each(&dev->ctx_idr, drm_ctx_sarea_free, NULL);
idr_remove_all(&dev->ctx_idr);
mutex_unlock(&dev->struct_mutex);
}
@ -155,7 +132,7 @@ void drm_ctxbitmap_cleanup(drm_device_t * dev)
* Get per-context SAREA.
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument pointing to a drm_ctx_priv_map structure.
* \return zero on success or a negative number on failure.
@ -163,44 +140,34 @@ void drm_ctxbitmap_cleanup(drm_device_t * dev)
* Gets the map from drm_device::ctx_idr with the handle specified and
* returns its handle.
*/
int drm_getsareactx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_getsareactx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_ctx_priv_map_t __user *argp = (void __user *)arg;
drm_ctx_priv_map_t request;
drm_map_t *map;
drm_map_list_t *_entry;
struct drm_ctx_sarea_list *ctx_sarea;
if (copy_from_user(&request, argp, sizeof(request)))
return -EFAULT;
struct drm_ctx_priv_map *request = data;
struct drm_map *map;
struct drm_map_list *_entry;
mutex_lock(&dev->struct_mutex);
ctx_sarea = idr_find(&dev->ctx_idr, request.ctx_id);
if (!ctx_sarea) {
map = idr_find(&dev->ctx_idr, request->ctx_id);
if (!map) {
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
map = ctx_sarea->map;
mutex_unlock(&dev->struct_mutex);
request.handle = NULL;
request->handle = NULL;
list_for_each_entry(_entry, &dev->maplist, head) {
if (_entry->map == map) {
request.handle =
request->handle =
(void *)(unsigned long)_entry->user_token;
break;
}
}
if (request.handle == NULL)
if (request->handle == NULL)
return -EINVAL;
if (copy_to_user(argp, &request, sizeof(request)))
return -EFAULT;
return 0;
}
@ -208,7 +175,7 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
* Set per-context SAREA.
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument pointing to a drm_ctx_priv_map structure.
* \return zero on success or a negative number on failure.
@ -216,24 +183,17 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
* Searches the mapping specified in \p arg and update the entry in
* drm_device::ctx_idr with it.
*/
int drm_setsareactx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_setsareactx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_ctx_priv_map_t request;
drm_map_t *map = NULL;
drm_map_list_t *r_list = NULL;
struct drm_ctx_sarea_list *ctx_sarea;
if (copy_from_user(&request,
(drm_ctx_priv_map_t __user *) arg, sizeof(request)))
return -EFAULT;
struct drm_ctx_priv_map *request = data;
struct drm_map *map = NULL;
struct drm_map_list *r_list = NULL;
mutex_lock(&dev->struct_mutex);
list_for_each_entry(r_list, &dev->maplist, head) {
if (r_list->map
&& r_list->user_token == (unsigned long) request.handle)
&& r_list->user_token == (unsigned long) request->handle)
goto found;
}
bad:
@ -245,14 +205,11 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
if (!map)
goto bad;
mutex_lock(&dev->struct_mutex);
ctx_sarea = idr_find(&dev->ctx_idr, request.ctx_id);
if (!ctx_sarea)
if (IS_ERR(idr_replace(&dev->ctx_idr, map, request->ctx_id)))
goto bad;
ctx_sarea->map = map;
mutex_unlock(&dev->struct_mutex);
return 0;
}
@ -272,7 +229,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
*
* Attempt to set drm_device::context_flag.
*/
static int drm_context_switch(drm_device_t * dev, int old, int new)
static int drm_context_switch(struct drm_device *dev, int old, int new)
{
if (test_and_set_bit(0, &dev->context_flag)) {
DRM_ERROR("Reentering -- FIXME\n");
@ -300,7 +257,7 @@ static int drm_context_switch(drm_device_t * dev, int old, int new)
* hardware lock is held, clears the drm_device::context_flag and wakes up
* drm_device::context_wait.
*/
static int drm_context_switch_complete(drm_device_t * dev, int new)
static int drm_context_switch_complete(struct drm_device *dev, int new)
{
dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
dev->last_switch = jiffies;
@ -322,34 +279,28 @@ static int drm_context_switch_complete(drm_device_t * dev, int new)
* Reserve contexts.
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument pointing to a drm_ctx_res structure.
* \return zero on success or a negative number on failure.
*/
int drm_resctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_resctx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_ctx_res_t res;
drm_ctx_t __user *argp = (void __user *)arg;
drm_ctx_t ctx;
struct drm_ctx_res *res = data;
struct drm_ctx ctx;
int i;
if (copy_from_user(&res, argp, sizeof(res)))
return -EFAULT;
if (res.count >= DRM_RESERVED_CONTEXTS) {
if (res->count >= DRM_RESERVED_CONTEXTS) {
memset(&ctx, 0, sizeof(ctx));
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
ctx.handle = i;
if (copy_to_user(&res.contexts[i], &ctx, sizeof(ctx)))
if (copy_to_user(&res->contexts[i], &ctx, sizeof(ctx)))
return -EFAULT;
}
}
res.count = DRM_RESERVED_CONTEXTS;
res->count = DRM_RESERVED_CONTEXTS;
if (copy_to_user(argp, &res, sizeof(res)))
return -EFAULT;
return 0;
}
@ -357,40 +308,34 @@ int drm_resctx(struct inode *inode, struct file *filp,
* Add context.
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument pointing to a drm_ctx structure.
* \return zero on success or a negative number on failure.
*
* Get a new handle for the context and copy to userspace.
*/
int drm_addctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_addctx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_ctx_list_t *ctx_entry;
drm_ctx_t __user *argp = (void __user *)arg;
drm_ctx_t ctx;
struct drm_ctx_list *ctx_entry;
struct drm_ctx *ctx = data;
if (copy_from_user(&ctx, argp, sizeof(ctx)))
return -EFAULT;
ctx.handle = drm_ctxbitmap_next(dev);
if (ctx.handle == DRM_KERNEL_CONTEXT) {
ctx->handle = drm_ctxbitmap_next(dev);
if (ctx->handle == DRM_KERNEL_CONTEXT) {
/* Skip kernel's context and get a new one. */
ctx.handle = drm_ctxbitmap_next(dev);
ctx->handle = drm_ctxbitmap_next(dev);
}
DRM_DEBUG("%d\n", ctx.handle);
if (ctx.handle == -1) {
DRM_DEBUG("%d\n", ctx->handle);
if (ctx->handle == -1) {
DRM_DEBUG("Not enough free contexts.\n");
/* Should this return -EBUSY instead? */
return -ENOMEM;
}
if (ctx.handle != DRM_KERNEL_CONTEXT) {
if (ctx->handle != DRM_KERNEL_CONTEXT) {
if (dev->driver->context_ctor)
if (!dev->driver->context_ctor(dev, ctx.handle)) {
if (!dev->driver->context_ctor(dev, ctx->handle)) {
DRM_DEBUG("Running out of ctxs or memory.\n");
return -ENOMEM;
}
@ -403,21 +348,18 @@ int drm_addctx(struct inode *inode, struct file *filp,
}
INIT_LIST_HEAD(&ctx_entry->head);
ctx_entry->handle = ctx.handle;
ctx_entry->tag = priv;
ctx_entry->handle = ctx->handle;
ctx_entry->tag = file_priv;
mutex_lock(&dev->ctxlist_mutex);
list_add(&ctx_entry->head, &dev->ctxlist);
++dev->ctx_count;
mutex_unlock(&dev->ctxlist_mutex);
if (copy_to_user(argp, &ctx, sizeof(ctx)))
return -EFAULT;
return 0;
}
int drm_modctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_modctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
/* This does nothing */
return 0;
@ -427,25 +369,18 @@ int drm_modctx(struct inode *inode, struct file *filp,
* Get context.
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument pointing to a drm_ctx structure.
* \return zero on success or a negative number on failure.
*/
int drm_getctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
drm_ctx_t __user *argp = (void __user *)arg;
drm_ctx_t ctx;
if (copy_from_user(&ctx, argp, sizeof(ctx)))
return -EFAULT;
struct drm_ctx *ctx = data;
/* This is 0, because we don't handle any context flags */
ctx.flags = 0;
ctx->flags = 0;
if (copy_to_user(argp, &ctx, sizeof(ctx)))
return -EFAULT;
return 0;
}
@ -453,50 +388,40 @@ int drm_getctx(struct inode *inode, struct file *filp,
* Switch context.
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument pointing to a drm_ctx structure.
* \return zero on success or a negative number on failure.
*
* Calls context_switch().
*/
int drm_switchctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_switchctx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_ctx_t ctx;
struct drm_ctx *ctx = data;
if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
return drm_context_switch(dev, dev->last_context, ctx.handle);
DRM_DEBUG("%d\n", ctx->handle);
return drm_context_switch(dev, dev->last_context, ctx->handle);
}
/**
* New context.
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument pointing to a drm_ctx structure.
* \return zero on success or a negative number on failure.
*
* Calls context_switch_complete().
*/
int drm_newctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_newctx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_ctx_t ctx;
struct drm_ctx *ctx = data;
if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
drm_context_switch_complete(dev, ctx.handle);
DRM_DEBUG("%d\n", ctx->handle);
drm_context_switch_complete(dev, ctx->handle);
return 0;
}
@ -505,39 +430,34 @@ int drm_newctx(struct inode *inode, struct file *filp,
* Remove context.
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument pointing to a drm_ctx structure.
* \return zero on success or a negative number on failure.
*
* If not the special kernel context, calls ctxbitmap_free() to free the specified context.
*/
int drm_rmctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
int drm_rmctx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_ctx_t ctx;
struct drm_ctx *ctx = data;
if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
if (ctx.handle == DRM_KERNEL_CONTEXT + 1) {
priv->remove_auth_on_close = 1;
DRM_DEBUG("%d\n", ctx->handle);
if (ctx->handle == DRM_KERNEL_CONTEXT + 1) {
file_priv->remove_auth_on_close = 1;
}
if (ctx.handle != DRM_KERNEL_CONTEXT) {
if (ctx->handle != DRM_KERNEL_CONTEXT) {
if (dev->driver->context_dtor)
dev->driver->context_dtor(dev, ctx.handle);
drm_ctxbitmap_free(dev, ctx.handle);
dev->driver->context_dtor(dev, ctx->handle);
drm_ctxbitmap_free(dev, ctx->handle);
}
mutex_lock(&dev->ctxlist_mutex);
if (!list_empty(&dev->ctxlist)) {
drm_ctx_list_t *pos, *n;
struct drm_ctx_list *pos, *n;
list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
if (pos->handle == ctx.handle) {
if (pos->handle == ctx->handle) {
list_del(&pos->head);
drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
--dev->ctx_count;

View File

@ -43,7 +43,7 @@
*
* Allocate and initialize a drm_device_dma structure.
*/
int drm_dma_setup(drm_device_t * dev)
int drm_dma_setup(struct drm_device * dev)
{
int i;
@ -67,9 +67,9 @@ int drm_dma_setup(drm_device_t * dev)
* Free all pages associated with DMA buffers, the buffers and pages lists, and
* finally the the drm_device::dma structure itself.
*/
void drm_dma_takedown(drm_device_t * dev)
void drm_dma_takedown(struct drm_device * dev)
{
drm_device_dma_t *dma = dev->dma;
struct drm_device_dma *dma = dev->dma;
int i, j;
if (!dma)
@ -129,14 +129,14 @@ void drm_dma_takedown(drm_device_t * dev)
*
* Resets the fields of \p buf.
*/
void drm_free_buffer(drm_device_t * dev, drm_buf_t * buf)
void drm_free_buffer(struct drm_device * dev, struct drm_buf * buf)
{
if (!buf)
return;
buf->waiting = 0;
buf->pending = 0;
buf->filp = NULL;
buf->file_priv = NULL;
buf->used = 0;
if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE)
@ -148,19 +148,20 @@ void drm_free_buffer(drm_device_t * dev, drm_buf_t * buf)
/**
* Reclaim the buffers.
*
* \param filp file pointer.
* \param file_priv DRM file private.
*
* Frees each buffer associated with \p filp not already on the hardware.
* Frees each buffer associated with \p file_priv not already on the hardware.
*/
void drm_core_reclaim_buffers(drm_device_t *dev, struct file *filp)
void drm_core_reclaim_buffers(struct drm_device *dev,
struct drm_file *file_priv)
{
drm_device_dma_t *dma = dev->dma;
struct drm_device_dma *dma = dev->dma;
int i;
if (!dma)
return;
for (i = 0; i < dma->buf_count; i++) {
if (dma->buflist[i]->filp == filp) {
if (dma->buflist[i]->file_priv == file_priv) {
switch (dma->buflist[i]->list) {
case DRM_LIST_NONE:
drm_free_buffer(dev, dma->buflist[i]);

View File

@ -40,28 +40,21 @@
/**
* Allocate drawable ID and memory to store information about it.
*/
int drm_adddraw(DRM_IOCTL_ARGS)
int drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
unsigned long irqflags;
struct drm_drawable_list *draw_info;
drm_draw_t draw;
struct drm_draw *draw = data;
int new_id = 0;
int ret;
draw_info = drm_calloc(1, sizeof(struct drm_drawable_list), DRM_MEM_BUFS);
if (!draw_info)
return -ENOMEM;
again:
if (idr_pre_get(&dev->drw_idr, GFP_KERNEL) == 0) {
DRM_ERROR("Out of memory expanding drawable idr\n");
drm_free(draw_info, sizeof(struct drm_drawable_list), DRM_MEM_BUFS);
return -ENOMEM;
}
spin_lock_irqsave(&dev->drw_lock, irqflags);
ret = idr_get_new_above(&dev->drw_idr, draw_info, 1, &new_id);
ret = idr_get_new_above(&dev->drw_idr, NULL, 1, &new_id);
if (ret == -EAGAIN) {
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
goto again;
@ -69,11 +62,9 @@ again:
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
draw.handle = new_id;
draw->handle = new_id;
DRM_DEBUG("%d\n", draw.handle);
DRM_COPY_TO_USER_IOCTL((drm_draw_t __user *)data, draw, sizeof(draw));
DRM_DEBUG("%d\n", draw->handle);
return 0;
}
@ -81,73 +72,64 @@ again:
/**
* Free drawable ID and memory to store information about it.
*/
int drm_rmdraw(DRM_IOCTL_ARGS)
int drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
drm_draw_t draw;
struct drm_draw *draw = data;
unsigned long irqflags;
struct drm_drawable_list *draw_info;
DRM_COPY_FROM_USER_IOCTL(draw, (drm_draw_t __user *) data,
sizeof(draw));
draw_info = idr_find(&dev->drw_idr, draw.handle);
if (!draw_info) {
DRM_DEBUG("No such drawable %d\n", draw.handle);
return -EINVAL;
}
spin_lock_irqsave(&dev->drw_lock, irqflags);
idr_remove(&dev->drw_idr, draw.handle);
drm_free(draw_info, sizeof(struct drm_drawable_list), DRM_MEM_BUFS);
drm_free(drm_get_drawable_info(dev, draw->handle),
sizeof(struct drm_drawable_info), DRM_MEM_BUFS);
idr_remove(&dev->drw_idr, draw->handle);
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
DRM_DEBUG("%d\n", draw.handle);
DRM_DEBUG("%d\n", draw->handle);
return 0;
}
int drm_update_drawable_info(DRM_IOCTL_ARGS) {
DRM_DEVICE;
drm_update_draw_t update;
int drm_update_drawable_info(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
struct drm_update_draw *update = data;
unsigned long irqflags;
drm_drawable_info_t *info;
drm_clip_rect_t *rects;
struct drm_drawable_list *draw_info;
struct drm_clip_rect *rects;
struct drm_drawable_info *info;
int err;
DRM_COPY_FROM_USER_IOCTL(update, (drm_update_draw_t __user *) data,
sizeof(update));
draw_info = idr_find(&dev->drw_idr, update.handle);
if (!draw_info) {
DRM_ERROR("No such drawable %d\n", update.handle);
return DRM_ERR(EINVAL);
info = idr_find(&dev->drw_idr, update->handle);
if (!info) {
info = drm_calloc(1, sizeof(*info), DRM_MEM_BUFS);
if (!info)
return -ENOMEM;
if (IS_ERR(idr_replace(&dev->drw_idr, info, update->handle))) {
DRM_ERROR("No such drawable %d\n", update->handle);
drm_free(info, sizeof(*info), DRM_MEM_BUFS);
return -EINVAL;
}
}
info = &draw_info->info;
switch (update.type) {
switch (update->type) {
case DRM_DRAWABLE_CLIPRECTS:
if (update.num != info->num_rects) {
rects = drm_alloc(update.num * sizeof(drm_clip_rect_t),
if (update->num != info->num_rects) {
rects = drm_alloc(update->num * sizeof(struct drm_clip_rect),
DRM_MEM_BUFS);
} else
rects = info->rects;
if (update.num && !rects) {
if (update->num && !rects) {
DRM_ERROR("Failed to allocate cliprect memory\n");
err = DRM_ERR(ENOMEM);
err = -ENOMEM;
goto error;
}
if (update.num && DRM_COPY_FROM_USER(rects,
(drm_clip_rect_t __user *)
(unsigned long)update.data,
update.num *
if (update->num && DRM_COPY_FROM_USER(rects,
(struct drm_clip_rect __user *)
(unsigned long)update->data,
update->num *
sizeof(*rects))) {
DRM_ERROR("Failed to copy cliprects from userspace\n");
err = DRM_ERR(EFAULT);
err = -EFAULT;
goto error;
}
@ -155,27 +137,27 @@ int drm_update_drawable_info(DRM_IOCTL_ARGS) {
if (rects != info->rects) {
drm_free(info->rects, info->num_rects *
sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
}
info->rects = rects;
info->num_rects = update.num;
info->num_rects = update->num;
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
DRM_DEBUG("Updated %d cliprects for drawable %d\n",
info->num_rects, update.handle);
info->num_rects, update->handle);
break;
default:
DRM_ERROR("Invalid update type %d\n", update.type);
return DRM_ERR(EINVAL);
DRM_ERROR("Invalid update type %d\n", update->type);
return -EINVAL;
}
return 0;
error:
if (rects != info->rects)
drm_free(rects, update.num * sizeof(drm_clip_rect_t),
drm_free(rects, update->num * sizeof(struct drm_clip_rect),
DRM_MEM_BUFS);
return err;
@ -184,28 +166,26 @@ error:
/**
* Caller must hold the drawable spinlock!
*/
drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, drm_drawable_t id) {
struct drm_drawable_list *draw_info;
draw_info = idr_find(&dev->drw_idr, id);
if (!draw_info) {
DRM_DEBUG("No such drawable %d\n", id);
return NULL;
}
return &draw_info->info;
struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, drm_drawable_t id)
{
return idr_find(&dev->drw_idr, id);
}
EXPORT_SYMBOL(drm_get_drawable_info);
static int drm_drawable_free(int idr, void *p, void *data)
{
struct drm_drawable_list *drw_entry = p;
drm_free(drw_entry->info.rects, drw_entry->info.num_rects *
sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
drm_free(drw_entry, sizeof(struct drm_drawable_list), DRM_MEM_BUFS);
struct drm_drawable_info *info = p;
if (info) {
drm_free(info->rects, info->num_rects *
sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
drm_free(info, sizeof(*info), DRM_MEM_BUFS);
}
return 0;
}
void drm_drawable_free_all(drm_device_t *dev)
void drm_drawable_free_all(struct drm_device *dev)
{
idr_for_each(&dev->drw_idr, drm_drawable_free, NULL);
idr_remove_all(&dev->drw_idr);

View File

@ -48,82 +48,106 @@
#include "drmP.h"
#include "drm_core.h"
static void drm_cleanup(drm_device_t * dev);
static void drm_cleanup(struct drm_device * dev);
int drm_fb_loaded = 0;
static int drm_version(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
static int drm_version(struct drm_device *dev, void *data,
struct drm_file *file_priv);
/** Ioctl table */
static drm_ioctl_desc_t drm_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = {drm_version, 0},
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = {drm_getunique, 0},
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = {drm_getmagic, 0},
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = {drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = {drm_getmap, 0},
[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = {drm_getclient, 0},
[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = {drm_getstats, 0},
[DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = {drm_setversion, DRM_MASTER|DRM_ROOT_ONLY},
static struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0),
DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER|DRM_ROOT_ONLY),
[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = {drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = {drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = {drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = {drm_rmmap_ioctl, DRM_AUTH},
DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
[DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, DRM_AUTH},
DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, DRM_AUTH},
[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = {drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = {drm_resctx, DRM_AUTH},
DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = {drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = {drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
[DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = {drm_lock, DRM_AUTH},
[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = {drm_unlock, DRM_AUTH},
DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = {drm_noop, DRM_AUTH},
DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = {drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = {drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = {drm_infobufs, DRM_AUTH},
[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = {drm_mapbufs, DRM_AUTH},
[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = {drm_freebufs, DRM_AUTH},
DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
/* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = {NULL, DRM_AUTH},
DRM_IOCTL_DEF(DRM_IOCTL_DMA, NULL, DRM_AUTH),
[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = {drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
#if __OS_HAS_AGP
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = {drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = {drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = {drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = {drm_agp_info_ioctl, DRM_AUTH},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = {drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = {drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = {drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = {drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
#endif
[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = {drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0},
[DRM_IOCTL_NR(DRM_IOCTL_FENCE)] = {drm_fence_ioctl, DRM_AUTH},
[DRM_IOCTL_NR(DRM_IOCTL_BUFOBJ)] = {drm_bo_ioctl, DRM_AUTH},
[DRM_IOCTL_NR(DRM_IOCTL_MM_INIT)] = {drm_mm_init_ioctl,
DRM_AUTH },
DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
[DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_MODESET_CTL)] = {drm_modeset_ctl, 0},
DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_MM_INIT, drm_mm_init_ioctl,
DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_MM_TAKEDOWN, drm_mm_takedown_ioctl,
DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_MM_LOCK, drm_mm_lock_ioctl,
DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_MM_UNLOCK, drm_mm_unlock_ioctl,
DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_FENCE_CREATE, drm_fence_create_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_FENCE_REFERENCE, drm_fence_reference_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_FENCE_UNREFERENCE, drm_fence_unreference_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_FENCE_SIGNALED, drm_fence_signaled_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_FENCE_FLUSH, drm_fence_flush_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_FENCE_WAIT, drm_fence_wait_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_FENCE_EMIT, drm_fence_emit_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_FENCE_BUFFERS, drm_fence_buffers_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_BO_CREATE, drm_bo_create_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_BO_MAP, drm_bo_map_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_BO_UNMAP, drm_bo_unmap_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_BO_REFERENCE, drm_bo_reference_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_BO_UNREFERENCE, drm_bo_unreference_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_BO_SETSTATUS, drm_bo_setstatus_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_BO_INFO, drm_bo_info_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_BO_WAIT_IDLE, drm_bo_wait_idle_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_BO_VERSION, drm_bo_version_ioctl, 0),
};
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
@ -138,11 +162,11 @@ static drm_ioctl_desc_t drm_ioctls[] = {
*
* \sa drm_device
*/
int drm_lastclose(drm_device_t * dev)
int drm_lastclose(struct drm_device * dev)
{
drm_magic_entry_t *pt, *next;
drm_map_list_t *r_list, *list_t;
drm_vma_entry_t *vma, *vma_temp;
struct drm_magic_entry *pt, *next;
struct drm_map_list *r_list, *list_t;
struct drm_vma_entry *vma, *vma_temp;
int i;
DRM_DEBUG("\n");
@ -190,7 +214,7 @@ int drm_lastclose(drm_device_t * dev)
/* Clear AGP information */
if (drm_core_has_AGP(dev) && dev->agp) {
drm_agp_mem_t *entry, *tempe;
struct drm_agp_mem *entry, *tempe;
/* Remove AGP resources, but leave dev->agp
intact until drv_cleanup is called. */
@ -246,7 +270,7 @@ int drm_lastclose(drm_device_t * dev)
if (dev->lock.hw_lock) {
dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
dev->lock.filp = NULL;
dev->lock.file_priv = NULL;
wake_up_interruptible(&dev->lock.lock_queue);
}
dev->dev_mapping = NULL;
@ -258,7 +282,7 @@ int drm_lastclose(drm_device_t * dev)
void drm_cleanup_pci(struct pci_dev *pdev)
{
drm_device_t *dev = pci_get_drvdata(pdev);
struct drm_device *dev = pci_get_drvdata(pdev);
pci_set_drvdata(pdev, NULL);
pci_release_regions(pdev);
@ -297,6 +321,11 @@ int drm_init(struct drm_driver *driver,
while ((pdev =
pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
pid->subdevice, pdev))) {
/* Are there device class requirements? */
if ((pid->class != 0)
&& ((pdev->class & pid->class_mask) != pid->class)) {
continue;
}
/* is there already a driver loaded, or (short circuit saves work) */
/* does something like VesaFB have control of the memory region? */
if (pci_dev_driver(pdev)
@ -312,7 +341,7 @@ int drm_init(struct drm_driver *driver,
}
if (!drm_fb_loaded)
pci_register_driver(&driver->pci_driver);
return pci_register_driver(&driver->pci_driver);
else {
for (i = 0; pciidlist[i].vendor != 0; i++) {
pid = &pciidlist[i];
@ -323,6 +352,11 @@ int drm_init(struct drm_driver *driver,
pci_get_subsys(pid->vendor, pid->device,
pid->subvendor, pid->subdevice,
pdev))) {
/* Are there device class requirements? */
if ((pid->class != 0)
&& ((pdev->class & pid->class_mask) != pid->class)) {
continue;
}
/* stealth mode requires a manual probe */
pci_dev_get(pdev);
if ((rc = drm_get_dev(pdev, &pciidlist[i], driver))) {
@ -344,7 +378,7 @@ EXPORT_SYMBOL(drm_init);
*
* \sa drm_init
*/
static void drm_cleanup(drm_device_t * dev)
static void drm_cleanup(struct drm_device * dev)
{
DRM_DEBUG("\n");
@ -389,8 +423,8 @@ static void drm_cleanup(drm_device_t * dev)
void drm_exit(struct drm_driver *driver)
{
int i;
drm_device_t *dev = NULL;
drm_head_t *head;
struct drm_device *dev = NULL;
struct drm_head *head;
DRM_DEBUG("\n");
if (drm_fb_loaded) {
@ -483,7 +517,7 @@ static int __init drm_core_init(void)
CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
return 0;
err_p3:
drm_sysfs_destroy(drm_class);
drm_sysfs_destroy();
err_p2:
unregister_chrdev(DRM_MAJOR, "drm");
drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
@ -494,7 +528,7 @@ err_p1:
static void __exit drm_core_exit(void)
{
remove_proc_entry("dri", NULL);
drm_sysfs_destroy(drm_class);
drm_sysfs_destroy();
unregister_chrdev(DRM_MAJOR, "drm");
@ -508,34 +542,26 @@ module_exit(drm_core_exit);
* Get version information
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument, pointing to a drm_version structure.
* \return zero on success or negative number on failure.
*
* Fills in the version information in \p arg.
*/
static int drm_version(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
static int drm_version(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_version_t __user *argp = (void __user *)arg;
drm_version_t version;
struct drm_version *version = data;
int len;
if (copy_from_user(&version, argp, sizeof(version)))
return -EFAULT;
version->version_major = dev->driver->major;
version->version_minor = dev->driver->minor;
version->version_patchlevel = dev->driver->patchlevel;
DRM_COPY(version->name, dev->driver->name);
DRM_COPY(version->date, dev->driver->date);
DRM_COPY(version->desc, dev->driver->desc);
version.version_major = dev->driver->major;
version.version_minor = dev->driver->minor;
version.version_patchlevel = dev->driver->patchlevel;
DRM_COPY(version.name, dev->driver->name);
DRM_COPY(version.date, dev->driver->date);
DRM_COPY(version.desc, dev->driver->desc);
if (copy_to_user(argp, &version, sizeof(version)))
return -EFAULT;
return 0;
}
@ -543,31 +569,43 @@ static int drm_version(struct inode *inode, struct file *filp,
* Called whenever a process performs an ioctl on /dev/drm.
*
* \param inode device inode.
* \param filp file pointer.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument.
* \return zero on success or negative number on failure.
*
* Looks up the ioctl function in the ::ioctls table, checking for root
* previleges if so required, and dispatches to the respective function.
*
* Copies data in and out according to the size and direction given in cmd,
* which must match the ioctl cmd known by the kernel. The kernel uses a 512
* byte stack buffer to store the ioctl arguments in kernel space. Should we
* ever need much larger ioctl arguments, we may need to allocate memory.
*/
int drm_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_ioctl_desc_t *ioctl;
return drm_unlocked_ioctl(filp, cmd, arg);
}
EXPORT_SYMBOL(drm_ioctl);
long drm_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct drm_file *file_priv = filp->private_data;
struct drm_device *dev = file_priv->head->dev;
struct drm_ioctl_desc *ioctl;
drm_ioctl_t *func;
unsigned int nr = DRM_IOCTL_NR(cmd);
int retcode = -EINVAL;
char kdata[512];
atomic_inc(&dev->ioctl_count);
atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
++priv->ioctl_count;
++file_priv->ioctl_count;
DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
current->pid, cmd, nr, (long)old_encode_dev(priv->head->device),
priv->authenticated);
current->pid, cmd, nr, (long)old_encode_dev(file_priv->head->device),
file_priv->authenticated);
if ((nr >= DRM_CORE_IOCTL_COUNT) &&
((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
@ -577,35 +615,63 @@ int drm_ioctl(struct inode *inode, struct file *filp,
ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE))
ioctl = &drm_ioctls[nr];
else
else {
retcode = -EINVAL;
goto err_i1;
}
#if 0
/*
* This check is disabled, because driver private ioctl->cmd
* are not the ioctl commands with size and direction bits but
* just the indices. The DRM core ioctl->cmd are the proper ioctl
* commands. The drivers' ioctl tables need to be fixed.
*/
if (ioctl->cmd != cmd) {
retcode = -EINVAL;
goto err_i1;
}
#endif
func = ioctl->func;
/* is there a local override? */
if ((nr == DRM_IOCTL_NR(DRM_IOCTL_DMA)) && dev->driver->dma_ioctl)
func = dev->driver->dma_ioctl;
if (cmd & IOC_IN) {
if (copy_from_user(kdata, (void __user *)arg,
_IOC_SIZE(cmd)) != 0) {
retcode = -EACCES;
goto err_i1;
}
}
if (!func) {
DRM_DEBUG("no function\n");
retcode = -EINVAL;
} else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) ||
((ioctl->flags & DRM_AUTH) && !priv->authenticated) ||
((ioctl->flags & DRM_MASTER) && !priv->master)) {
((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
((ioctl->flags & DRM_MASTER) && !file_priv->master)) {
retcode = -EACCES;
} else {
retcode = func(inode, filp, cmd, arg);
retcode = func(dev, kdata, file_priv);
}
if ((retcode == 0) && (cmd & IOC_OUT)) {
if (copy_to_user((void __user *)arg, kdata,
_IOC_SIZE(cmd)) != 0)
retcode = -EACCES;
}
err_i1:
atomic_dec(&dev->ioctl_count);
if (retcode)
DRM_DEBUG("ret = %x\n", retcode);
DRM_DEBUG("ret = %d\n", retcode);
return retcode;
}
EXPORT_SYMBOL(drm_ioctl);
EXPORT_SYMBOL(drm_unlocked_ioctl);
drm_local_map_t *drm_getsarea(struct drm_device *dev)
{
drm_map_list_t *entry;
struct drm_map_list *entry;
list_for_each_entry(entry, &dev->maplist, head) {
if (entry->map && entry->map->type == _DRM_SHM &&

View File

@ -34,21 +34,22 @@
* Typically called by the IRQ handler.
*/
void drm_fence_handler(drm_device_t * dev, uint32_t class,
uint32_t sequence, uint32_t type)
void drm_fence_handler(struct drm_device * dev, uint32_t fence_class,
uint32_t sequence, uint32_t type, uint32_t error)
{
int wake = 0;
uint32_t diff;
uint32_t relevant;
drm_fence_manager_t *fm = &dev->fm;
drm_fence_class_manager_t *fc = &fm->class[class];
drm_fence_driver_t *driver = dev->driver->fence_driver;
struct drm_fence_manager *fm = &dev->fm;
struct drm_fence_class_manager *fc = &fm->fence_class[fence_class];
struct drm_fence_driver *driver = dev->driver->fence_driver;
struct list_head *head;
drm_fence_object_t *fence, *next;
struct drm_fence_object *fence, *next;
int found = 0;
int is_exe = (type & DRM_FENCE_TYPE_EXE);
int ge_last_exe;
diff = (sequence - fc->exe_flush_sequence) & driver->sequence_mask;
if (fc->pending_exe_flush && is_exe && diff < driver->wrap_diff)
@ -57,9 +58,6 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class,
diff = (sequence - fc->last_exe_flush) & driver->sequence_mask;
ge_last_exe = diff < driver->wrap_diff;
if (ge_last_exe)
fc->pending_flush &= ~type;
if (is_exe && ge_last_exe) {
fc->last_exe_flush = sequence;
}
@ -75,36 +73,68 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class,
}
}
fc->pending_flush &= ~type;
head = (found) ? &fence->ring : &fc->ring;
list_for_each_entry_safe_reverse(fence, next, head, ring) {
if (&fence->ring == &fc->ring)
break;
type |= fence->native_type;
if (error) {
fence->error = error;
fence->signaled = fence->type;
fence->submitted_flush = fence->type;
fence->flush_mask = fence->type;
list_del_init(&fence->ring);
wake = 1;
break;
}
if (is_exe)
type |= fence->native_type;
relevant = type & fence->type;
if ((fence->signaled | relevant) != fence->signaled) {
fence->signaled |= relevant;
fence->flush_mask |= relevant;
fence->submitted_flush |= relevant;
DRM_DEBUG("Fence 0x%08lx signaled 0x%08x\n",
fence->base.hash.key, fence->signaled);
fence->submitted_flush |= relevant;
wake = 1;
}
relevant = fence->flush_mask &
~(fence->signaled | fence->submitted_flush);
~(fence->submitted_flush | fence->signaled);
if (relevant) {
fc->pending_flush |= relevant;
fence->submitted_flush = fence->flush_mask;
}
fc->pending_flush |= relevant;
fence->submitted_flush |= relevant;
if (!(fence->type & ~fence->signaled)) {
DRM_DEBUG("Fence completely signaled 0x%08lx\n",
fence->base.hash.key);
list_del_init(&fence->ring);
}
}
/*
* Reinstate lost flush flags.
*/
if ((fc->pending_flush & type) != type) {
head = head->prev;
list_for_each_entry(fence, head, ring) {
if (&fence->ring == &fc->ring)
break;
diff = (fc->last_exe_flush - fence->sequence) &
driver->sequence_mask;
if (diff > driver->wrap_diff)
break;
relevant = fence->submitted_flush & ~fence->signaled;
fc->pending_flush |= relevant;
}
}
if (wake) {
@ -114,9 +144,9 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class,
EXPORT_SYMBOL(drm_fence_handler);
static void drm_fence_unring(drm_device_t * dev, struct list_head *ring)
static void drm_fence_unring(struct drm_device * dev, struct list_head *ring)
{
drm_fence_manager_t *fm = &dev->fm;
struct drm_fence_manager *fm = &dev->fm;
unsigned long flags;
write_lock_irqsave(&fm->lock, flags);
@ -124,57 +154,83 @@ static void drm_fence_unring(drm_device_t * dev, struct list_head *ring)
write_unlock_irqrestore(&fm->lock, flags);
}
void drm_fence_usage_deref_locked(drm_device_t * dev,
drm_fence_object_t * fence)
void drm_fence_usage_deref_locked(struct drm_fence_object ** fence)
{
drm_fence_manager_t *fm = &dev->fm;
struct drm_fence_object *tmp_fence = *fence;
struct drm_device *dev = tmp_fence->dev;
struct drm_fence_manager *fm = &dev->fm;
if (atomic_dec_and_test(&fence->usage)) {
drm_fence_unring(dev, &fence->ring);
DRM_ASSERT_LOCKED(&dev->struct_mutex);
*fence = NULL;
if (atomic_dec_and_test(&tmp_fence->usage)) {
drm_fence_unring(dev, &tmp_fence->ring);
DRM_DEBUG("Destroyed a fence object 0x%08lx\n",
fence->base.hash.key);
tmp_fence->base.hash.key);
atomic_dec(&fm->count);
drm_ctl_free(fence, sizeof(*fence), DRM_MEM_FENCE);
BUG_ON(!list_empty(&tmp_fence->base.list));
drm_ctl_free(tmp_fence, sizeof(*tmp_fence), DRM_MEM_FENCE);
}
}
EXPORT_SYMBOL(drm_fence_usage_deref_locked);
void drm_fence_usage_deref_unlocked(drm_device_t * dev,
drm_fence_object_t * fence)
void drm_fence_usage_deref_unlocked(struct drm_fence_object ** fence)
{
drm_fence_manager_t *fm = &dev->fm;
struct drm_fence_object *tmp_fence = *fence;
struct drm_device *dev = tmp_fence->dev;
struct drm_fence_manager *fm = &dev->fm;
if (atomic_dec_and_test(&fence->usage)) {
*fence = NULL;
if (atomic_dec_and_test(&tmp_fence->usage)) {
mutex_lock(&dev->struct_mutex);
if (atomic_read(&fence->usage) == 0) {
drm_fence_unring(dev, &fence->ring);
if (atomic_read(&tmp_fence->usage) == 0) {
drm_fence_unring(dev, &tmp_fence->ring);
atomic_dec(&fm->count);
drm_ctl_free(fence, sizeof(*fence), DRM_MEM_FENCE);
BUG_ON(!list_empty(&tmp_fence->base.list));
drm_ctl_free(tmp_fence, sizeof(*tmp_fence), DRM_MEM_FENCE);
}
mutex_unlock(&dev->struct_mutex);
}
}
EXPORT_SYMBOL(drm_fence_usage_deref_unlocked);
static void drm_fence_object_destroy(drm_file_t * priv,
drm_user_object_t * base)
struct drm_fence_object
*drm_fence_reference_locked(struct drm_fence_object *src)
{
drm_device_t *dev = priv->head->dev;
drm_fence_object_t *fence =
drm_user_object_entry(base, drm_fence_object_t, base);
DRM_ASSERT_LOCKED(&src->dev->struct_mutex);
drm_fence_usage_deref_locked(dev, fence);
atomic_inc(&src->usage);
return src;
}
static int fence_signaled(drm_device_t * dev,
drm_fence_object_t * fence,
uint32_t mask, int poke_flush)
void drm_fence_reference_unlocked(struct drm_fence_object **dst,
struct drm_fence_object *src)
{
mutex_lock(&src->dev->struct_mutex);
*dst = src;
atomic_inc(&src->usage);
mutex_unlock(&src->dev->struct_mutex);
}
EXPORT_SYMBOL(drm_fence_reference_unlocked);
static void drm_fence_object_destroy(struct drm_file *priv, struct drm_user_object * base)
{
struct drm_fence_object *fence =
drm_user_object_entry(base, struct drm_fence_object, base);
drm_fence_usage_deref_locked(&fence);
}
int drm_fence_object_signaled(struct drm_fence_object * fence,
uint32_t mask, int poke_flush)
{
unsigned long flags;
int signaled;
drm_fence_manager_t *fm = &dev->fm;
drm_fence_driver_t *driver = dev->driver->fence_driver;
struct drm_device *dev = fence->dev;
struct drm_fence_manager *fm = &dev->fm;
struct drm_fence_driver *driver = dev->driver->fence_driver;
if (poke_flush)
driver->poke_flush(dev, fence->class);
driver->poke_flush(dev, fence->fence_class);
read_lock_irqsave(&fm->lock, flags);
signaled =
(fence->type & mask & fence->signaled) == (fence->type & mask);
@ -182,9 +238,10 @@ static int fence_signaled(drm_device_t * dev,
return signaled;
}
EXPORT_SYMBOL(drm_fence_object_signaled);
static void drm_fence_flush_exe(drm_fence_class_manager_t * fc,
drm_fence_driver_t * driver, uint32_t sequence)
static void drm_fence_flush_exe(struct drm_fence_class_manager * fc,
struct drm_fence_driver * driver, uint32_t sequence)
{
uint32_t diff;
@ -200,19 +257,13 @@ static void drm_fence_flush_exe(drm_fence_class_manager_t * fc,
}
}
int drm_fence_object_signaled(drm_fence_object_t * fence,
uint32_t type)
{
return ((fence->signaled & type) == type);
}
int drm_fence_object_flush(drm_device_t * dev,
drm_fence_object_t * fence,
int drm_fence_object_flush(struct drm_fence_object * fence,
uint32_t type)
{
drm_fence_manager_t *fm = &dev->fm;
drm_fence_class_manager_t *fc = &fm->class[fence->class];
drm_fence_driver_t *driver = dev->driver->fence_driver;
struct drm_device *dev = fence->dev;
struct drm_fence_manager *fm = &dev->fm;
struct drm_fence_class_manager *fc = &fm->fence_class[fence->fence_class];
struct drm_fence_driver *driver = dev->driver->fence_driver;
unsigned long flags;
if (type & ~fence->type) {
@ -223,7 +274,8 @@ int drm_fence_object_flush(drm_device_t * dev,
write_lock_irqsave(&fm->lock, flags);
fence->flush_mask |= type;
if (fence->submitted_flush == fence->signaled) {
if ((fence->submitted_flush & fence->signaled)
== fence->submitted_flush) {
if ((fence->type & DRM_FENCE_TYPE_EXE) &&
!(fence->submitted_flush & DRM_FENCE_TYPE_EXE)) {
drm_fence_flush_exe(fc, driver, fence->sequence);
@ -235,7 +287,7 @@ int drm_fence_object_flush(drm_device_t * dev,
}
}
write_unlock_irqrestore(&fm->lock, flags);
driver->poke_flush(dev, fence->class);
driver->poke_flush(dev, fence->fence_class);
return 0;
}
@ -244,14 +296,14 @@ int drm_fence_object_flush(drm_device_t * dev,
* wrapped around and reused.
*/
void drm_fence_flush_old(drm_device_t * dev, uint32_t class, uint32_t sequence)
void drm_fence_flush_old(struct drm_device * dev, uint32_t fence_class, uint32_t sequence)
{
drm_fence_manager_t *fm = &dev->fm;
drm_fence_class_manager_t *fc = &fm->class[class];
drm_fence_driver_t *driver = dev->driver->fence_driver;
struct drm_fence_manager *fm = &dev->fm;
struct drm_fence_class_manager *fc = &fm->fence_class[fence_class];
struct drm_fence_driver *driver = dev->driver->fence_driver;
uint32_t old_sequence;
unsigned long flags;
drm_fence_object_t *fence;
struct drm_fence_object *fence;
uint32_t diff;
write_lock_irqsave(&fm->lock, flags);
@ -272,39 +324,38 @@ void drm_fence_flush_old(drm_device_t * dev, uint32_t class, uint32_t sequence)
mutex_unlock(&dev->struct_mutex);
return;
}
fence = list_entry(fc->ring.next, drm_fence_object_t, ring);
atomic_inc(&fence->usage);
fence = drm_fence_reference_locked(list_entry(fc->ring.next, struct drm_fence_object, ring));
mutex_unlock(&dev->struct_mutex);
diff = (old_sequence - fence->sequence) & driver->sequence_mask;
read_unlock_irqrestore(&fm->lock, flags);
if (diff < driver->wrap_diff) {
drm_fence_object_flush(dev, fence, fence->type);
drm_fence_object_flush(fence, fence->type);
}
drm_fence_usage_deref_unlocked(dev, fence);
drm_fence_usage_deref_unlocked(&fence);
}
EXPORT_SYMBOL(drm_fence_flush_old);
static int drm_fence_lazy_wait(drm_device_t *dev,
drm_fence_object_t *fence,
static int drm_fence_lazy_wait(struct drm_fence_object *fence,
int ignore_signals,
uint32_t mask)
{
drm_fence_manager_t *fm = &dev->fm;
drm_fence_class_manager_t *fc = &fm->class[fence->class];
struct drm_device *dev = fence->dev;
struct drm_fence_manager *fm = &dev->fm;
struct drm_fence_class_manager *fc = &fm->fence_class[fence->fence_class];
int signaled;
unsigned long _end = jiffies + 3*DRM_HZ;
int ret = 0;
do {
DRM_WAIT_ON(ret, fc->fence_queue, 3 * DRM_HZ,
(signaled = fence_signaled(dev, fence, mask, 1)));
(signaled = drm_fence_object_signaled(fence, mask, 1)));
if (signaled)
return 0;
if (time_after_eq(jiffies, _end))
break;
} while (ret == -EINTR && ignore_signals);
if (fence_signaled(dev, fence, mask, 0))
if (drm_fence_object_signaled(fence, mask, 0))
return 0;
if (time_after_eq(jiffies, _end))
ret = -EBUSY;
@ -312,18 +363,26 @@ static int drm_fence_lazy_wait(drm_device_t *dev,
if (ret == -EBUSY) {
DRM_ERROR("Fence timeout. "
"GPU lockup or fence driver was "
"taken down.\n");
"taken down. %d 0x%08x 0x%02x 0x%02x 0x%02x\n",
fence->fence_class,
fence->sequence,
fence->type,
mask,
fence->signaled);
DRM_ERROR("Pending exe flush %d 0x%08x\n",
fc->pending_exe_flush,
fc->exe_flush_sequence);
}
return ((ret == -EINTR) ? -EAGAIN : ret);
}
return 0;
}
int drm_fence_object_wait(drm_device_t * dev,
drm_fence_object_t * fence,
int drm_fence_object_wait(struct drm_fence_object * fence,
int lazy, int ignore_signals, uint32_t mask)
{
drm_fence_driver_t *driver = dev->driver->fence_driver;
struct drm_device *dev = fence->dev;
struct drm_fence_driver *driver = dev->driver->fence_driver;
int ret = 0;
unsigned long _end;
int signaled;
@ -331,41 +390,42 @@ int drm_fence_object_wait(drm_device_t * dev,
if (mask & ~fence->type) {
DRM_ERROR("Wait trying to extend fence type"
" 0x%08x 0x%08x\n", mask, fence->type);
BUG();
return -EINVAL;
}
if (fence_signaled(dev, fence, mask, 0))
if (drm_fence_object_signaled(fence, mask, 0))
return 0;
_end = jiffies + 3 * DRM_HZ;
drm_fence_object_flush(dev, fence, mask);
drm_fence_object_flush(fence, mask);
if (lazy && driver->lazy_capable) {
ret = drm_fence_lazy_wait(dev, fence, ignore_signals, mask);
ret = drm_fence_lazy_wait(fence, ignore_signals, mask);
if (ret)
return ret;
} else {
if (driver->has_irq(dev, fence->class,
if (driver->has_irq(dev, fence->fence_class,
DRM_FENCE_TYPE_EXE)) {
ret = drm_fence_lazy_wait(dev, fence, ignore_signals,
ret = drm_fence_lazy_wait(fence, ignore_signals,
DRM_FENCE_TYPE_EXE);
if (ret)
return ret;
}
if (driver->has_irq(dev, fence->class,
if (driver->has_irq(dev, fence->fence_class,
mask & ~DRM_FENCE_TYPE_EXE)) {
ret = drm_fence_lazy_wait(dev, fence, ignore_signals,
ret = drm_fence_lazy_wait(fence, ignore_signals,
mask);
if (ret)
return ret;
}
}
if (drm_fence_object_signaled(fence, mask))
if (drm_fence_object_signaled(fence, mask, 0))
return 0;
/*
@ -377,7 +437,7 @@ int drm_fence_object_wait(drm_device_t * dev,
#endif
do {
schedule();
signaled = fence_signaled(dev, fence, mask, 1);
signaled = drm_fence_object_signaled(fence, mask, 1);
} while (!signaled && !time_after_eq(jiffies, _end));
if (!signaled)
@ -385,25 +445,28 @@ int drm_fence_object_wait(drm_device_t * dev,
return 0;
}
EXPORT_SYMBOL(drm_fence_object_wait);
int drm_fence_object_emit(drm_device_t * dev, drm_fence_object_t * fence,
uint32_t fence_flags, uint32_t class, uint32_t type)
int drm_fence_object_emit(struct drm_fence_object * fence,
uint32_t fence_flags, uint32_t fence_class, uint32_t type)
{
drm_fence_manager_t *fm = &dev->fm;
drm_fence_driver_t *driver = dev->driver->fence_driver;
drm_fence_class_manager_t *fc = &fm->class[fence->class];
struct drm_device *dev = fence->dev;
struct drm_fence_manager *fm = &dev->fm;
struct drm_fence_driver *driver = dev->driver->fence_driver;
struct drm_fence_class_manager *fc = &fm->fence_class[fence->fence_class];
unsigned long flags;
uint32_t sequence;
uint32_t native_type;
int ret;
drm_fence_unring(dev, &fence->ring);
ret = driver->emit(dev, class, fence_flags, &sequence, &native_type);
ret = driver->emit(dev, fence_class, fence_flags, &sequence, &native_type);
if (ret)
return ret;
write_lock_irqsave(&fm->lock, flags);
fence->class = class;
fence->fence_class = fence_class;
fence->type = type;
fence->flush_mask = 0x00;
fence->submitted_flush = 0x00;
@ -416,15 +479,16 @@ int drm_fence_object_emit(drm_device_t * dev, drm_fence_object_t * fence,
write_unlock_irqrestore(&fm->lock, flags);
return 0;
}
EXPORT_SYMBOL(drm_fence_object_emit);
static int drm_fence_object_init(drm_device_t * dev, uint32_t class,
static int drm_fence_object_init(struct drm_device * dev, uint32_t fence_class,
uint32_t type,
uint32_t fence_flags,
drm_fence_object_t * fence)
struct drm_fence_object * fence)
{
int ret = 0;
unsigned long flags;
drm_fence_manager_t *fm = &dev->fm;
struct drm_fence_manager *fm = &dev->fm;
mutex_lock(&dev->struct_mutex);
atomic_set(&fence->usage, 1);
@ -432,52 +496,60 @@ static int drm_fence_object_init(drm_device_t * dev, uint32_t class,
write_lock_irqsave(&fm->lock, flags);
INIT_LIST_HEAD(&fence->ring);
fence->class = class;
/*
* Avoid hitting BUG() for kernel-only fence objects.
*/
INIT_LIST_HEAD(&fence->base.list);
fence->fence_class = fence_class;
fence->type = type;
fence->flush_mask = 0;
fence->submitted_flush = 0;
fence->signaled = 0;
fence->sequence = 0;
fence->dev = dev;
write_unlock_irqrestore(&fm->lock, flags);
if (fence_flags & DRM_FENCE_FLAG_EMIT) {
ret = drm_fence_object_emit(dev, fence, fence_flags,
fence->class, type);
ret = drm_fence_object_emit(fence, fence_flags,
fence->fence_class, type);
}
return ret;
}
int drm_fence_add_user_object(drm_file_t * priv, drm_fence_object_t * fence,
int drm_fence_add_user_object(struct drm_file * priv, struct drm_fence_object * fence,
int shareable)
{
drm_device_t *dev = priv->head->dev;
struct drm_device *dev = priv->head->dev;
int ret;
mutex_lock(&dev->struct_mutex);
ret = drm_add_user_object(priv, &fence->base, shareable);
mutex_unlock(&dev->struct_mutex);
if (ret)
return ret;
goto out;
atomic_inc(&fence->usage);
fence->base.type = drm_fence_type;
fence->base.remove = &drm_fence_object_destroy;
DRM_DEBUG("Fence 0x%08lx created\n", fence->base.hash.key);
return 0;
out:
mutex_unlock(&dev->struct_mutex);
return ret;
}
EXPORT_SYMBOL(drm_fence_add_user_object);
int drm_fence_object_create(drm_device_t * dev, uint32_t class, uint32_t type,
unsigned flags, drm_fence_object_t ** c_fence)
int drm_fence_object_create(struct drm_device * dev, uint32_t fence_class, uint32_t type,
unsigned flags, struct drm_fence_object ** c_fence)
{
drm_fence_object_t *fence;
struct drm_fence_object *fence;
int ret;
drm_fence_manager_t *fm = &dev->fm;
struct drm_fence_manager *fm = &dev->fm;
fence = drm_ctl_alloc(sizeof(*fence), DRM_MEM_FENCE);
fence = drm_ctl_calloc(1, sizeof(*fence), DRM_MEM_FENCE);
if (!fence)
return -ENOMEM;
ret = drm_fence_object_init(dev, class, type, flags, fence);
ret = drm_fence_object_init(dev, fence_class, type, flags, fence);
if (ret) {
drm_fence_usage_deref_unlocked(dev, fence);
drm_fence_usage_deref_unlocked(&fence);
return ret;
}
*c_fence = fence;
@ -488,15 +560,16 @@ int drm_fence_object_create(drm_device_t * dev, uint32_t class, uint32_t type,
EXPORT_SYMBOL(drm_fence_object_create);
void drm_fence_manager_init(drm_device_t * dev)
void drm_fence_manager_init(struct drm_device * dev)
{
drm_fence_manager_t *fm = &dev->fm;
drm_fence_class_manager_t *class;
drm_fence_driver_t *fed = dev->driver->fence_driver;
struct drm_fence_manager *fm = &dev->fm;
struct drm_fence_class_manager *fence_class;
struct drm_fence_driver *fed = dev->driver->fence_driver;
int i;
unsigned long flags;
rwlock_init(&fm->lock);
write_lock(&fm->lock);
write_lock_irqsave(&fm->lock, flags);
fm->initialized = 0;
if (!fed)
goto out_unlock;
@ -506,27 +579,45 @@ void drm_fence_manager_init(drm_device_t * dev)
BUG_ON(fm->num_classes > _DRM_FENCE_CLASSES);
for (i=0; i<fm->num_classes; ++i) {
class = &fm->class[i];
fence_class = &fm->fence_class[i];
INIT_LIST_HEAD(&class->ring);
class->pending_flush = 0;
DRM_INIT_WAITQUEUE(&class->fence_queue);
INIT_LIST_HEAD(&fence_class->ring);
fence_class->pending_flush = 0;
DRM_INIT_WAITQUEUE(&fence_class->fence_queue);
}
atomic_set(&fm->count, 0);
out_unlock:
write_unlock(&fm->lock);
write_unlock_irqrestore(&fm->lock, flags);
}
void drm_fence_manager_takedown(drm_device_t * dev)
void drm_fence_fill_arg(struct drm_fence_object *fence, struct drm_fence_arg *arg)
{
struct drm_device *dev = fence->dev;
struct drm_fence_manager *fm = &dev->fm;
unsigned long irq_flags;
read_lock_irqsave(&fm->lock, irq_flags);
arg->handle = fence->base.hash.key;
arg->fence_class = fence->fence_class;
arg->type = fence->type;
arg->signaled = fence->signaled;
arg->error = fence->error;
arg->sequence = fence->sequence;
read_unlock_irqrestore(&fm->lock, irq_flags);
}
EXPORT_SYMBOL(drm_fence_fill_arg);
void drm_fence_manager_takedown(struct drm_device * dev)
{
}
drm_fence_object_t *drm_lookup_fence_object(drm_file_t * priv, uint32_t handle)
struct drm_fence_object *drm_lookup_fence_object(struct drm_file * priv, uint32_t handle)
{
drm_device_t *dev = priv->head->dev;
drm_user_object_t *uo;
drm_fence_object_t *fence;
struct drm_device *dev = priv->head->dev;
struct drm_user_object *uo;
struct drm_fence_object *fence;
mutex_lock(&dev->struct_mutex);
uo = drm_lookup_user_object(priv, handle);
@ -534,21 +625,17 @@ drm_fence_object_t *drm_lookup_fence_object(drm_file_t * priv, uint32_t handle)
mutex_unlock(&dev->struct_mutex);
return NULL;
}
fence = drm_user_object_entry(uo, drm_fence_object_t, base);
atomic_inc(&fence->usage);
fence = drm_fence_reference_locked(drm_user_object_entry(uo, struct drm_fence_object, base));
mutex_unlock(&dev->struct_mutex);
return fence;
}
int drm_fence_ioctl(DRM_IOCTL_ARGS)
int drm_fence_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
DRM_DEVICE;
int ret;
drm_fence_manager_t *fm = &dev->fm;
drm_fence_arg_t arg;
drm_fence_object_t *fence;
drm_user_object_t *uo;
unsigned long flags;
struct drm_fence_manager *fm = &dev->fm;
struct drm_fence_arg *arg = data;
struct drm_fence_object *fence;
ret = 0;
if (!fm->initialized) {
@ -556,106 +643,209 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS)
return -EINVAL;
}
DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg));
switch (arg.op) {
case drm_fence_create:
if (arg.flags & DRM_FENCE_FLAG_EMIT)
LOCK_TEST_WITH_RETURN(dev, filp);
ret = drm_fence_object_create(dev, arg.class,
arg.type, arg.flags, &fence);
if (ret)
return ret;
ret = drm_fence_add_user_object(priv, fence,
arg.flags &
DRM_FENCE_FLAG_SHAREABLE);
if (ret) {
drm_fence_usage_deref_unlocked(dev, fence);
return ret;
}
/*
* usage > 0. No need to lock dev->struct_mutex;
*/
atomic_inc(&fence->usage);
arg.handle = fence->base.hash.key;
break;
case drm_fence_destroy:
mutex_lock(&dev->struct_mutex);
uo = drm_lookup_user_object(priv, arg.handle);
if (!uo || (uo->type != drm_fence_type) || uo->owner != priv) {
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
ret = drm_remove_user_object(priv, uo);
mutex_unlock(&dev->struct_mutex);
if (arg->flags & DRM_FENCE_FLAG_EMIT)
LOCK_TEST_WITH_RETURN(dev, file_priv);
ret = drm_fence_object_create(dev, arg->fence_class,
arg->type, arg->flags, &fence);
if (ret)
return ret;
case drm_fence_reference:
ret =
drm_user_object_ref(priv, arg.handle, drm_fence_type, &uo);
if (ret)
return ret;
fence = drm_lookup_fence_object(priv, arg.handle);
break;
case drm_fence_unreference:
ret = drm_user_object_unref(priv, arg.handle, drm_fence_type);
ret = drm_fence_add_user_object(file_priv, fence,
arg->flags &
DRM_FENCE_FLAG_SHAREABLE);
if (ret) {
drm_fence_usage_deref_unlocked(&fence);
return ret;
case drm_fence_signaled:
fence = drm_lookup_fence_object(priv, arg.handle);
if (!fence)
return -EINVAL;
break;
case drm_fence_flush:
fence = drm_lookup_fence_object(priv, arg.handle);
if (!fence)
return -EINVAL;
ret = drm_fence_object_flush(dev, fence, arg.type);
break;
case drm_fence_wait:
fence = drm_lookup_fence_object(priv, arg.handle);
if (!fence)
return -EINVAL;
ret =
drm_fence_object_wait(dev, fence,
arg.flags & DRM_FENCE_FLAG_WAIT_LAZY,
0, arg.type);
break;
case drm_fence_emit:
LOCK_TEST_WITH_RETURN(dev, filp);
fence = drm_lookup_fence_object(priv, arg.handle);
if (!fence)
return -EINVAL;
ret = drm_fence_object_emit(dev, fence, arg.flags, arg.class,
arg.type);
break;
case drm_fence_buffers:
if (!dev->bm.initialized) {
DRM_ERROR("Buffer object manager is not initialized\n");
return -EINVAL;
}
LOCK_TEST_WITH_RETURN(dev, filp);
ret = drm_fence_buffer_objects(priv, NULL, arg.flags,
NULL, &fence);
if (ret)
return ret;
ret = drm_fence_add_user_object(priv, fence,
arg.flags &
DRM_FENCE_FLAG_SHAREABLE);
if (ret)
return ret;
atomic_inc(&fence->usage);
arg.handle = fence->base.hash.key;
break;
default:
return -EINVAL;
}
read_lock_irqsave(&fm->lock, flags);
arg.class = fence->class;
arg.type = fence->type;
arg.signaled = fence->signaled;
read_unlock_irqrestore(&fm->lock, flags);
drm_fence_usage_deref_unlocked(dev, fence);
DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg));
/*
* usage > 0. No need to lock dev->struct_mutex;
*/
arg->handle = fence->base.hash.key;
drm_fence_fill_arg(fence, arg);
drm_fence_usage_deref_unlocked(&fence);
return ret;
}
int drm_fence_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
int ret;
struct drm_fence_manager *fm = &dev->fm;
struct drm_fence_arg *arg = data;
struct drm_fence_object *fence;
struct drm_user_object *uo;
ret = 0;
if (!fm->initialized) {
DRM_ERROR("The DRM driver does not support fencing.\n");
return -EINVAL;
}
ret = drm_user_object_ref(file_priv, arg->handle, drm_fence_type, &uo);
if (ret)
return ret;
fence = drm_lookup_fence_object(file_priv, arg->handle);
drm_fence_fill_arg(fence, arg);
drm_fence_usage_deref_unlocked(&fence);
return ret;
}
int drm_fence_unreference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
int ret;
struct drm_fence_manager *fm = &dev->fm;
struct drm_fence_arg *arg = data;
ret = 0;
if (!fm->initialized) {
DRM_ERROR("The DRM driver does not support fencing.\n");
return -EINVAL;
}
return drm_user_object_unref(file_priv, arg->handle, drm_fence_type);
}
int drm_fence_signaled_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
int ret;
struct drm_fence_manager *fm = &dev->fm;
struct drm_fence_arg *arg = data;
struct drm_fence_object *fence;
ret = 0;
if (!fm->initialized) {
DRM_ERROR("The DRM driver does not support fencing.\n");
return -EINVAL;
}
fence = drm_lookup_fence_object(file_priv, arg->handle);
if (!fence)
return -EINVAL;
drm_fence_fill_arg(fence, arg);
drm_fence_usage_deref_unlocked(&fence);
return ret;
}
int drm_fence_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
int ret;
struct drm_fence_manager *fm = &dev->fm;
struct drm_fence_arg *arg = data;
struct drm_fence_object *fence;
ret = 0;
if (!fm->initialized) {
DRM_ERROR("The DRM driver does not support fencing.\n");
return -EINVAL;
}
fence = drm_lookup_fence_object(file_priv, arg->handle);
if (!fence)
return -EINVAL;
ret = drm_fence_object_flush(fence, arg->type);
drm_fence_fill_arg(fence, arg);
drm_fence_usage_deref_unlocked(&fence);
return ret;
}
int drm_fence_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
int ret;
struct drm_fence_manager *fm = &dev->fm;
struct drm_fence_arg *arg = data;
struct drm_fence_object *fence;
ret = 0;
if (!fm->initialized) {
DRM_ERROR("The DRM driver does not support fencing.\n");
return -EINVAL;
}
fence = drm_lookup_fence_object(file_priv, arg->handle);
if (!fence)
return -EINVAL;
ret = drm_fence_object_wait(fence,
arg->flags & DRM_FENCE_FLAG_WAIT_LAZY,
0, arg->type);
drm_fence_fill_arg(fence, arg);
drm_fence_usage_deref_unlocked(&fence);
return ret;
}
int drm_fence_emit_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
int ret;
struct drm_fence_manager *fm = &dev->fm;
struct drm_fence_arg *arg = data;
struct drm_fence_object *fence;
ret = 0;
if (!fm->initialized) {
DRM_ERROR("The DRM driver does not support fencing.\n");
return -EINVAL;
}
LOCK_TEST_WITH_RETURN(dev, file_priv);
fence = drm_lookup_fence_object(file_priv, arg->handle);
if (!fence)
return -EINVAL;
ret = drm_fence_object_emit(fence, arg->flags, arg->fence_class,
arg->type);
drm_fence_fill_arg(fence, arg);
drm_fence_usage_deref_unlocked(&fence);
return ret;
}
int drm_fence_buffers_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
int ret;
struct drm_fence_manager *fm = &dev->fm;
struct drm_fence_arg *arg = data;
struct drm_fence_object *fence;
ret = 0;
if (!fm->initialized) {
DRM_ERROR("The DRM driver does not support fencing.\n");
return -EINVAL;
}
if (!dev->bm.initialized) {
DRM_ERROR("Buffer object manager is not initialized\n");
return -EINVAL;
}
LOCK_TEST_WITH_RETURN(dev, file_priv);
ret = drm_fence_buffer_objects(dev, NULL, arg->flags,
NULL, &fence);
if (ret)
return ret;
if (!(arg->flags & DRM_FENCE_FLAG_NO_USER)) {
ret = drm_fence_add_user_object(file_priv, fence,
arg->flags &
DRM_FENCE_FLAG_SHAREABLE);
if (ret)
return ret;
}
arg->handle = fence->base.hash.key;
drm_fence_fill_arg(fence, arg);
drm_fence_usage_deref_unlocked(&fence);
return ret;
}

Some files were not shown because too many files have changed in this diff Show More