diff options
Diffstat (limited to 'bsd-core')
| -rw-r--r-- | bsd-core/drmP.h | 26 | ||||
| -rw-r--r-- | bsd-core/drm_dma.c | 4 | ||||
| -rw-r--r-- | bsd-core/drm_drawable.c | 109 | ||||
| -rw-r--r-- | bsd-core/drm_drv.c | 13 | ||||
| -rw-r--r-- | bsd-core/drm_ioctl.c | 4 | ||||
| -rw-r--r-- | bsd-core/drm_irq.c | 51 | ||||
| -rw-r--r-- | bsd-core/drm_scatter.c | 4 | 
7 files changed, 194 insertions, 17 deletions
| diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h index 6e05b58f..fd8f4a27 100644 --- a/bsd-core/drmP.h +++ b/bsd-core/drmP.h @@ -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) @@ -732,6 +740,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 +790,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 +807,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; @@ -958,6 +976,8 @@ int	drm_getsareactx(DRM_IOCTL_ARGS);  /* Drawable IOCTL support (drm_drawable.c) */  int	drm_adddraw(DRM_IOCTL_ARGS);  int	drm_rmdraw(DRM_IOCTL_ARGS); +int	drm_update_draw(DRM_IOCTL_ARGS); +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); diff --git a/bsd-core/drm_dma.c b/bsd-core/drm_dma.c index 67b3fe2d..086a9fa2 100644 --- a/bsd-core/drm_dma.c +++ b/bsd-core/drm_dma.c @@ -40,7 +40,7 @@ int drm_dma_setup(drm_device_t *dev)  	if (dev->dma == NULL)  		return DRM_ERR(ENOMEM); -	DRM_SPININIT(dev->dma_lock, "drmdma"); +	DRM_SPININIT(&dev->dma_lock, "drmdma");  	return 0;  } @@ -80,7 +80,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);  } diff --git a/bsd-core/drm_drawable.c b/bsd-core/drm_drawable.c index 379e0aa7..ad25a6df 100644 --- a/bsd-core/drm_drawable.c +++ b/bsd-core/drm_drawable.c @@ -33,19 +33,120 @@  #include "drmP.h" +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) +{ +	if (a->handle > b->handle) +		return 1; +	if (a->handle > b->handle) +		return -1; +	return 0; +} + +RB_GENERATE_STATIC(drawable_tree, bsd_drm_drawable_info, tree, +    drm_drawable_compare); + +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_IOCTL_ARGS)  { +	DRM_DEVICE;  	drm_draw_t draw; +	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); -	draw.handle = 0;	/* NOOP */  	DRM_DEBUG("%d\n", draw.handle); -	 -	DRM_COPY_TO_USER_IOCTL( (drm_draw_t *)data, draw, sizeof(draw) ); + +	DRM_COPY_TO_USER_IOCTL((drm_draw_t *)data, draw, sizeof(draw));  	return 0;  }  int drm_rmdraw(DRM_IOCTL_ARGS)  { -	return 0;		/* NOOP */ +	DRM_DEVICE; +	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); +	} else { +		DRM_SPINUNLOCK(&dev->drw_lock); +		return EINVAL; +	} +} + +int drm_update_draw(DRM_IOCTL_ARGS) +{ +	DRM_DEVICE; +	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; +	}  } diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c index 069774c1..75866b1b 100644 --- a/bsd-core/drm_drv.c +++ b/bsd-core/drm_drv.c @@ -31,6 +31,7 @@   *   */ +#include <sys/limits.h>  #include "drmP.h"  #include "drm.h"  #include "drm_sarea.h" @@ -121,6 +122,7 @@ static drm_ioctl_desc_t		  drm_ioctls[256] = {  	[DRM_IOCTL_NR(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_NR(DRM_IOCTL_UPDATE_DRAW)]   = { drm_update_draw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },  };  #ifdef __FreeBSD__ @@ -198,6 +200,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), @@ -556,7 +559,13 @@ static int drm_load(drm_device_t *dev)  		DRM_ERROR("Cannot allocate memory for context bitmap.\n");  		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 +637,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); diff --git a/bsd-core/drm_ioctl.c b/bsd-core/drm_ioctl.c index e22faa83..b5b5cf58 100644 --- a/bsd-core/drm_ioctl.c +++ b/bsd-core/drm_ioctl.c @@ -213,9 +213,7 @@ int drm_getclient(DRM_IOCTL_ARGS)  	}  	DRM_UNLOCK(); -	DRM_COPY_TO_USER_IOCTL( (drm_client_t *)data, client, sizeof(client) ); - -	return 0; +	return EINVAL;  }  int drm_getstats(DRM_IOCTL_ARGS) diff --git a/bsd-core/drm_irq.c b/bsd-core/drm_irq.c index f7da5ed7..2a69e014 100644 --- a/bsd-core/drm_irq.c +++ b/bsd-core/drm_irq.c @@ -31,6 +31,8 @@  #include "drmP.h"  #include "drm.h" +static void drm_locked_task(void *context, int pending __unused); +  int drm_irq_by_busid(DRM_IOCTL_ARGS)  {  	DRM_DEVICE; @@ -87,7 +89,7 @@ int drm_irq_install(drm_device_t *dev)  	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 +133,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 +145,7 @@ err:  		dev->irqrid = 0;  	}  #endif -	DRM_SPINUNINIT(dev->irq_lock); +	DRM_SPINUNINIT(&dev->irq_lock);  	DRM_UNLOCK();  	return retcode;  } @@ -174,7 +177,7 @@ 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;  } @@ -291,3 +294,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.filp = (void *)(uintptr_t)DRM_CURRENTPID; +			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); +} diff --git a/bsd-core/drm_scatter.c b/bsd-core/drm_scatter.c index 46222f18..3c0be4a0 100644 --- a/bsd-core/drm_scatter.c +++ b/bsd-core/drm_scatter.c @@ -44,6 +44,7 @@ int drm_sg_alloc(drm_device_t * dev, drm_scatter_gather_t * request)  {  	drm_sg_mem_t *entry;  	unsigned long pages; +	int i;  	if ( dev->sg )  		return EINVAL; @@ -52,7 +53,7 @@ int drm_sg_alloc(drm_device_t * dev, drm_scatter_gather_t * request)  	if ( !entry )  		return ENOMEM; -	pages = round_page(request.size) / PAGE_SIZE; +	pages = round_page(request->size) / PAGE_SIZE;  	DRM_DEBUG( "sg size=%ld pages=%ld\n", request->size, pages );  	entry->pages = pages; @@ -89,6 +90,7 @@ int drm_sg_alloc(drm_device_t * dev, drm_scatter_gather_t * request)  	dev->sg = entry;  	DRM_UNLOCK(); +	return 0;  }  int drm_sg_alloc_ioctl(DRM_IOCTL_ARGS) | 
