summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/drm/drmP.h44
-rw-r--r--sys/dev/pci/drm/drm_agpsupport.c60
-rw-r--r--sys/dev/pci/drm/drm_auth.c2
-rw-r--r--sys/dev/pci/drm/drm_bufs.c56
-rw-r--r--sys/dev/pci/drm/drm_context.c10
-rw-r--r--sys/dev/pci/drm/drm_dma.c2
-rw-r--r--sys/dev/pci/drm/drm_drawable.c10
-rw-r--r--sys/dev/pci/drm/drm_drv.c127
-rw-r--r--sys/dev/pci/drm/drm_fops.c51
-rw-r--r--sys/dev/pci/drm/drm_irq.c74
-rw-r--r--sys/dev/pci/drm/drm_lock.c35
-rw-r--r--sys/dev/pci/drm/i915_dma.c2
-rw-r--r--sys/dev/pci/drm/radeon_cp.c3
13 files changed, 200 insertions, 276 deletions
diff --git a/sys/dev/pci/drm/drmP.h b/sys/dev/pci/drm/drmP.h
index 9dfd0941fdb..5afddd92726 100644
--- a/sys/dev/pci/drm/drmP.h
+++ b/sys/dev/pci/drm/drmP.h
@@ -113,7 +113,6 @@
#define wait_queue_head_t atomic_t
#define DRM_WAKEUP(w) wakeup((void *)w)
-#define DRM_WAKEUP_INT(w) wakeup(w)
#define DRM_INIT_WAITQUEUE(queue) do {(void)(queue);} while (0)
#define DRM_CURPROC curproc
@@ -130,8 +129,8 @@
} while (0)
#define DRM_SPINUNLOCK_IRQRESTORE(u, irqflags) DRM_SPINUNLOCK(u)
#define DRM_SPINLOCK_ASSERT(l) DRM_NOOP
-#define DRM_LOCK() DRM_SPINLOCK(&dev->dev_lock)
-#define DRM_UNLOCK() DRM_SPINUNLOCK(&dev->dev_lock)
+#define DRM_LOCK() rw_enter_write(&dev->dev_lock)
+#define DRM_UNLOCK() rw_exit_write(&dev->dev_lock)
#define DRM_MAXUNITS 8
extern struct drm_device *drm_units[];
@@ -239,20 +238,15 @@ do { \
} while (0)
/* Returns -errno to shared code */
-#define DRM_WAIT_ON( ret, queue, timeout, condition ) \
-ret = 0; \
-while ( ret == 0 ) { \
- DRM_UNLOCK(); \
- DRM_SPINLOCK(&dev->irq_lock); \
- if (condition) { \
- DRM_SPINUNLOCK(&dev->irq_lock); \
- break; \
- } \
- ret = -msleep(&(queue), &dev->irq_lock, \
- PZERO | PCATCH, "drmwtq", (timeout)); \
- DRM_SPINUNLOCK(&dev->irq_lock); \
- DRM_LOCK(); \
-}
+#define DRM_WAIT_ON( ret, queue, timeout, condition ) \
+DRM_SPINLOCK(&dev->irq_lock); \
+while ( ret == 0 ) { \
+ if (condition) \
+ break; \
+ ret = -msleep(&(queue), &dev->irq_lock, \
+ PZERO | PCATCH, "drmwtq", (timeout)); \
+} \
+DRM_SPINUNLOCK(&dev->irq_lock)
#define DRM_ERROR(fmt, arg...) \
printf("error: [" DRM_NAME ":pid%d:%s] *ERROR* " fmt, \
@@ -344,8 +338,8 @@ struct drm_lock_data {
struct drm_hw_lock *hw_lock; /* Hardware lock */
/* Unique identifier of holding process (NULL is kernel) */
struct drm_file *file_priv;
- int lock_queue; /* Queue of blocked processes */
unsigned long lock_time; /* Time of last lock */
+ struct mutex spinlock;
};
/* This structure, in the struct drm_device, is always initialized while
@@ -428,7 +422,6 @@ typedef struct drm_local_map {
struct drm_vblank {
u_int32_t last_vblank; /* Last vblank we recieved */
atomic_t vbl_count; /* Number of interrupts */
- int vbl_queue; /* sleep on this when waiting */
atomic_t vbl_refcount; /* Number of users */
int vbl_enabled; /* Enabled? */
int vbl_inmodeset; /* is the DDX currently modesetting */
@@ -538,7 +531,7 @@ struct drm_device {
/* Locks */
DRM_SPINTYPE dma_lock; /* protects dev->dma */
DRM_SPINTYPE irq_lock; /* protects irq condition checks */
- DRM_SPINTYPE dev_lock; /* protects everything else */
+ struct rwlock dev_lock; /* protects everything else */
DRM_SPINTYPE drw_lock;
DRM_SPINTYPE tsk_lock;
@@ -616,8 +609,6 @@ dev_type_mmap(drmmmap);
extern drm_local_map_t *drm_getsarea(struct drm_device *);
/* File operations helpers (drm_fops.c) */
-int drm_open_helper(dev_t, int, int, struct proc *,
- struct drm_device *);
struct drm_file *drm_find_file_by_minor(struct drm_device *, int);
/* Memory management support (drm_memory.c) */
@@ -645,13 +636,13 @@ void drm_write32(drm_local_map_t *, unsigned long, u_int32_t);
/* Locking IOCTL support (drm_lock.c) */
int drm_lock_take(struct drm_lock_data *, unsigned int);
-int drm_lock_transfer(struct drm_lock_data *, unsigned int);
int drm_lock_free(struct drm_lock_data *, unsigned int);
/* Buffer management support (drm_bufs.c) */
unsigned long drm_get_resource_start(struct drm_device *, unsigned int);
unsigned long drm_get_resource_len(struct drm_device *, unsigned int);
void drm_rmmap(struct drm_device *, drm_local_map_t *);
+void drm_rmmap_locked(struct drm_device *, drm_local_map_t *);
int drm_order(unsigned long);
drm_local_map_t
*drm_find_matching_map(struct drm_device *, drm_local_map_t *);
@@ -797,12 +788,13 @@ static __inline__ struct drm_local_map *drm_core_findmap(struct drm_device *dev,
{
drm_local_map_t *map;
- DRM_SPINLOCK_ASSERT(&dev->dev_lock);
+ DRM_LOCK();
TAILQ_FOREACH(map, &dev->maplist, link) {
if (offset == map->ext)
- return map;
+ break;
}
- return NULL;
+ DRM_UNLOCK();
+ return (map);
}
#endif /* __KERNEL__ */
diff --git a/sys/dev/pci/drm/drm_agpsupport.c b/sys/dev/pci/drm/drm_agpsupport.c
index be3f368c4c8..c8ea97384eb 100644
--- a/sys/dev/pci/drm/drm_agpsupport.c
+++ b/sys/dev/pci/drm/drm_agpsupport.c
@@ -186,10 +186,8 @@ drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
type = (u_int32_t)request->type;
- DRM_UNLOCK();
handle = agp_alloc_memory(dev->agp->agpdev, type,
pages << AGP_PAGE_SHIFT);
- DRM_LOCK();
if (handle == NULL) {
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
return (ENOMEM);
@@ -198,12 +196,14 @@ drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
entry->handle = handle;
entry->bound = 0;
entry->pages = pages;
- TAILQ_INSERT_HEAD(&dev->agp->memory, entry, link);
agp_memory_info(dev->agp->agpdev, entry->handle, &info);
request->handle = (unsigned long)entry->handle;
request->physical = info.ami_physical;
+ DRM_LOCK();
+ TAILQ_INSERT_HEAD(&dev->agp->memory, entry, link);
+ DRM_UNLOCK();
#endif
return (0);
@@ -214,14 +214,13 @@ drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_agp_buffer *request = data;
- int retcode;
- DRM_LOCK();
- retcode = drm_agp_alloc(dev, request);
- DRM_UNLOCK();
- return (retcode);
+ return (drm_agp_alloc(dev, request));
}
+/*
+ * find entry on agp list. Must be called with dev_lock locked.
+ */
struct drm_agp_mem *
drm_agp_lookup_entry(struct drm_device *dev, void *handle)
{
@@ -243,16 +242,18 @@ drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
if (dev->agp == NULL || !dev->agp->acquired)
return (EINVAL);
+ DRM_LOCK();
entry = drm_agp_lookup_entry(dev, (void *)request->handle);
- if (entry == NULL || !entry->bound)
+ if (entry == NULL || !entry->bound) {
+ DRM_UNLOCK();
return (EINVAL);
+ }
- DRM_UNLOCK();
retcode = agp_unbind_memory(dev->agp->agpdev, entry->handle);
- DRM_LOCK();
if (retcode == 0)
entry->bound = 0;
+ DRM_UNLOCK();
return (retcode);
}
@@ -262,13 +263,8 @@ drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_agp_binding *request = data;
- int retcode;
- DRM_LOCK();
- retcode = drm_agp_unbind(dev, request);
- DRM_UNLOCK();
-
- return (retcode);
+ return (drm_agp_unbind(dev, request));
}
int
@@ -282,18 +278,20 @@ drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
DRM_DEBUG("agp_bind, page_size=%x\n", PAGE_SIZE);
+ DRM_LOCK();
entry = drm_agp_lookup_entry(dev, (void *)request->handle);
- if (entry == NULL || entry->bound)
+ if (entry == NULL || entry->bound) {
+ DRM_UNLOCK();
return (EINVAL);
+ }
page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE;
- DRM_UNLOCK();
retcode = agp_bind_memory(dev->agp->agpdev, entry->handle,
page * PAGE_SIZE);
- DRM_LOCK();
if (retcode == 0)
entry->bound = dev->agp->base + (page << PAGE_SHIFT);
+ DRM_UNLOCK();
return (retcode);
}
@@ -303,13 +301,8 @@ drm_agp_bind_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_agp_binding *request = data;
- int retcode;
- DRM_LOCK();
- retcode = drm_agp_bind(dev, request);
- DRM_UNLOCK();
-
- return (retcode);
+ return (drm_agp_bind(dev, request));
}
/*
@@ -320,12 +313,10 @@ drm_agp_remove_entry(struct drm_device *dev, struct drm_agp_mem *entry)
{
TAILQ_REMOVE(&dev->agp->memory, entry, link);
- DRM_UNLOCK();
if (entry->bound)
agp_unbind_memory(dev->agp->agpdev, entry->handle);
agp_free_memory(dev->agp->agpdev, entry->handle);
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
- DRM_LOCK();
}
void
@@ -357,11 +348,15 @@ drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
if (dev->agp == NULL || !dev->agp->acquired)
return (EINVAL);
+ DRM_LOCK();
entry = drm_agp_lookup_entry(dev, (void*)request->handle);
- if (entry == NULL)
+ if (entry == NULL) {
+ DRM_UNLOCK();
return (EINVAL);
+ }
drm_agp_remove_entry(dev, entry);
+ DRM_UNLOCK();
return (0);
}
@@ -371,13 +366,8 @@ drm_agp_free_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_agp_buffer *request = data;
- int retcode;
- DRM_LOCK();
- retcode = drm_agp_free(dev, request);
- DRM_UNLOCK();
-
- return (retcode);
+ return (drm_agp_free(dev, request));
}
struct drm_agp_head *
diff --git a/sys/dev/pci/drm/drm_auth.c b/sys/dev/pci/drm/drm_auth.c
index 83f7bf64c1d..3a7e4af340e 100644
--- a/sys/dev/pci/drm/drm_auth.c
+++ b/sys/dev/pci/drm/drm_auth.c
@@ -61,8 +61,8 @@ drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
entry->priv = file_priv;
SPLAY_INSERT(drm_magic_tree, &dev->magiclist, entry);
- DRM_DEBUG("%d\n", auth->magic);
DRM_UNLOCK();
+ DRM_DEBUG("%d\n", auth->magic);
}
DRM_DEBUG("%u\n", auth->magic);
diff --git a/sys/dev/pci/drm/drm_bufs.c b/sys/dev/pci/drm/drm_bufs.c
index ce2987a3901..1ddb0efd5ef 100644
--- a/sys/dev/pci/drm/drm_bufs.c
+++ b/sys/dev/pci/drm/drm_bufs.c
@@ -72,14 +72,10 @@ drm_alloc_resource(struct drm_device *dev, int resource)
return 1;
}
- DRM_UNLOCK();
- if (dev->pcir[resource] != NULL) {
- DRM_LOCK();
+ if (dev->pcir[resource] != NULL)
return 0;
- }
dev->pcir[resource] = vga_pci_bar_info(dev->vga_softc, resource);
- DRM_LOCK();
if (dev->pcir[resource] == NULL) {
DRM_ERROR("Can't get bar info for resource 0x%x\n", resource);
return 1;
@@ -144,6 +140,7 @@ drm_addmap(struct drm_device * dev, unsigned long offset, unsigned long size,
* Check if this is just another version of a kernel-allocated map, and
* just hand that back if so.
*/
+ DRM_LOCK();
if (type == _DRM_REGISTERS || type == _DRM_FRAME_BUFFER ||
type == _DRM_SHM) {
TAILQ_FOREACH(map, &dev->maplist, link) {
@@ -179,18 +176,15 @@ drm_addmap(struct drm_device * dev, unsigned long offset, unsigned long size,
DRM_ERROR("can't find free offset\n");
DRM_UNLOCK();
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
- DRM_LOCK();
- return ret;
+ return (ret);
}
DRM_UNLOCK();
switch (map->type) {
case _DRM_REGISTERS:
map->handle = drm_ioremap(dev, map);
- if (map->handle == NULL) {
- DRM_LOCK();
- return EINVAL;
- }
+ if (map->handle == NULL)
+ return (EINVAL);
if (!(map->flags & _DRM_WRITE_COMBINING))
break;
/* FALLTHROUGH */
@@ -217,6 +211,7 @@ drm_addmap(struct drm_device * dev, unsigned long offset, unsigned long size,
* If agp is in control of userspace (some intel drivers for
* example. In which case ignore this loop.
*/
+ DRM_LOCK();
TAILQ_FOREACH(entry, &dev->agp->memory, link) {
DRM_DEBUG("bound = %p, pages = %p, %p\n",
entry->bound, entry->pages,
@@ -229,18 +224,18 @@ drm_addmap(struct drm_device * dev, unsigned long offset, unsigned long size,
}
}
if (!TAILQ_EMPTY(&dev->agp->memory) && !valid) {
+ DRM_UNLOCK();
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
- DRM_LOCK();
DRM_ERROR("invalid agp map requested\n");
- return EACCES;
+ return (EACCES);
}
+ DRM_UNLOCK();
#endif
break;
case _DRM_SCATTER_GATHER:
if (dev->sg == NULL) {
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
- DRM_LOCK();
- return EINVAL;
+ return (EINVAL);
}
map->offset = map->offset + dev->sg->handle;
break;
@@ -258,8 +253,7 @@ drm_addmap(struct drm_device * dev, unsigned long offset, unsigned long size,
map->dmah = drm_pci_alloc(dev, map->size, align, 0xfffffffful);
if (map->dmah == NULL) {
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
- DRM_LOCK();
- return ENOMEM;
+ return (ENOMEM);
}
map->handle = map->dmah->vaddr;
map->offset = map->dmah->busaddr;
@@ -270,8 +264,7 @@ drm_addmap(struct drm_device * dev, unsigned long offset, unsigned long size,
DRM_UNLOCK();
drm_pci_free(dev, map->dmah);
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
- DRM_LOCK();
- return EBUSY;
+ return (EBUSY);
}
dev->lock.hw_lock = map->handle;
DRM_UNLOCK();
@@ -280,15 +273,13 @@ drm_addmap(struct drm_device * dev, unsigned long offset, unsigned long size,
default:
DRM_ERROR("Bad map type %d\n", map->type);
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
- DRM_LOCK();
return EINVAL;
}
DRM_LOCK();
TAILQ_INSERT_TAIL(&dev->maplist, map, link);
-
done:
- /* Jumped to, with lock held, when a kernel map is found. */
+ DRM_UNLOCK();
DRM_DEBUG("Added map %d 0x%lx/0x%lx\n", map->type, map->offset,
map->size);
@@ -308,10 +299,8 @@ drm_addmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
if (!(file_priv->flags & (FREAD|FWRITE)))
return EACCES; /* Require read/write */
- DRM_LOCK();
err = drm_addmap(dev, request->offset, request->size, request->type,
request->flags, &map);
- DRM_UNLOCK();
if (err != 0)
return err;
@@ -330,8 +319,15 @@ drm_addmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
void
drm_rmmap(struct drm_device *dev, drm_local_map_t *map)
{
- DRM_SPINLOCK_ASSERT(&dev->dev_lock);
+ DRM_LOCK();
+ drm_rmmap_locked(dev, map);
+ DRM_UNLOCK();
+}
+
+void
+drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)
+{
TAILQ_REMOVE(&dev->maplist, map, link);
switch (map->type) {
@@ -362,7 +358,6 @@ drm_rmmap(struct drm_device *dev, drm_local_map_t *map)
/* NOCOALESCE set, can't fail */
extent_free(dev->handle_ext, map->ext, map->size, EX_NOWAIT);
-
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
}
@@ -386,10 +381,10 @@ drm_rmmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
/* No match found. */
if (map == NULL) {
DRM_UNLOCK();
- return EINVAL;
+ return (EINVAL);
}
- drm_rmmap(dev, map);
+ drm_rmmap_locked(dev, map);
DRM_UNLOCK();
@@ -448,6 +443,7 @@ drm_do_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *request)
*/
#if 0 /* disabled for now */
valid = 0;
+ DRM_LOCK();
TAILQ_FOREACH(agp_entry, &dev->agp->memory, link) {
if ((agp_offset >= agp_entry->bound) &&
(agp_offset + total * count <=
@@ -458,8 +454,10 @@ drm_do_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *request)
}
if (!TAILQ_EMPTY(&dev->agp->memory) && !valid) {
DRM_DEBUG("zone invalid\n");
- return EINVAL;
+ DRM_UNLOCK();
+ return (EINVAL);
}
+ DRM_UNLOCK();
#endif
entry = &dma->bufs[order];
diff --git a/sys/dev/pci/drm/drm_context.c b/sys/dev/pci/drm/drm_context.c
index 3647f1f9c4a..70edfbdd6fe 100644
--- a/sys/dev/pci/drm/drm_context.c
+++ b/sys/dev/pci/drm/drm_context.c
@@ -147,11 +147,8 @@ drm_addctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
return ENOMEM;
}
- if (dev->driver.context_ctor && ctx->handle != DRM_KERNEL_CONTEXT) {
- DRM_LOCK();
+ if (dev->driver.context_ctor && ctx->handle != DRM_KERNEL_CONTEXT)
dev->driver.context_ctor(dev, ctx->handle);
- DRM_UNLOCK();
- }
return 0;
}
@@ -174,11 +171,8 @@ drm_rmctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
DRM_DEBUG("%d\n", ctx->handle);
if (ctx->handle != DRM_KERNEL_CONTEXT) {
- if (dev->driver.context_dtor) {
- DRM_LOCK();
+ if (dev->driver.context_dtor)
dev->driver.context_dtor(dev, ctx->handle);
- DRM_UNLOCK();
- }
drm_ctxbitmap_free(dev, ctx->handle);
}
diff --git a/sys/dev/pci/drm/drm_dma.c b/sys/dev/pci/drm/drm_dma.c
index 2059abcf7a6..c4012cc96c2 100644
--- a/sys/dev/pci/drm/drm_dma.c
+++ b/sys/dev/pci/drm/drm_dma.c
@@ -46,6 +46,8 @@ drm_dma_setup(struct drm_device *dev)
if (dev->dma == NULL)
return ENOMEM;
+ dev->buf_use = 0;
+
DRM_SPININIT(&dev->dma_lock, "drmdma");
return 0;
diff --git a/sys/dev/pci/drm/drm_drawable.c b/sys/dev/pci/drm/drm_drawable.c
index 563de03b064..4188c3190af 100644
--- a/sys/dev/pci/drm/drm_drawable.c
+++ b/sys/dev/pci/drm/drm_drawable.c
@@ -94,10 +94,9 @@ drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
if (info == NULL)
return (ENOMEM);
- info->handle = ++dev->drw_no;
DRM_SPINLOCK(&dev->drw_lock);
+ draw->handle = info->handle = ++dev->drw_no;
RB_INSERT(drawable_tree, &dev->drw_head, info);
- draw->handle = info->handle;
DRM_SPINUNLOCK(&dev->drw_lock);
DRM_DEBUG("%d\n", draw->handle);
@@ -197,13 +196,10 @@ drm_drawable_free(struct drm_device *dev, struct bsd_drm_drawable_info *draw)
void
drm_drawable_free_all(struct drm_device *dev)
{
- struct bsd_drm_drawable_info *draw, *nxt;
+ struct bsd_drm_drawable_info *draw;
DRM_SPINLOCK(&dev->drw_lock);
- for (draw = RB_MIN(drawable_tree, &dev->drw_head); draw != NULL;
- draw = nxt) {
- nxt = RB_NEXT(drawable_tree, &dev->drw_head, draw);
+ while ((draw = RB_ROOT(&dev->drw_head)) != NULL)
drm_drawable_free(dev, draw);
- }
DRM_SPINUNLOCK(&dev->drw_lock);
}
diff --git a/sys/dev/pci/drm/drm_drv.c b/sys/dev/pci/drm/drm_drv.c
index 7a39ee79b51..4b5755823fb 100644
--- a/sys/dev/pci/drm/drm_drv.c
+++ b/sys/dev/pci/drm/drm_drv.c
@@ -201,9 +201,10 @@ drm_attach(struct device *parent, struct device *kdev,
dev->pci_vendor = PCI_VENDOR(dev->pa.pa_id);
dev->pci_device = PCI_PRODUCT(dev->pa.pa_id);
- DRM_SPININIT(&dev->dev_lock, "drm device");
+ rw_init(&dev->dev_lock, "drmdevlk");
mtx_init(&dev->drw_lock, IPL_BIO);
mtx_init(&dev->tsk_lock, IPL_BIO);
+ mtx_init(&dev->lock.spinlock, IPL_NONE);
id_entry = drm_find_description(PCI_VENDOR(pa->pa_id),
PCI_PRODUCT(pa->pa_id), idlist);
@@ -230,11 +231,9 @@ drm_attach(struct device *parent, struct device *kdev,
if (dev->driver.load != NULL) {
int retcode;
- DRM_LOCK();
/* Shared code returns -errno. */
retcode = -dev->driver.load(dev,
dev->id_entry->driver_private);
- DRM_UNLOCK();
if (retcode != 0)
goto error;
}
@@ -263,10 +262,7 @@ drm_attach(struct device *parent, struct device *kdev,
return;
error:
- DRM_LOCK();
drm_lastclose(dev);
- DRM_UNLOCK();
- DRM_SPINUNINIT(&dev->dev_lock);
}
int
@@ -286,9 +282,7 @@ drm_detach(struct device *self, int flags)
DRM_DEBUG("mtrr_del = %d", retcode);
}
- DRM_LOCK();
drm_lastclose(dev);
- DRM_UNLOCK();
if (dev->agp != NULL) {
drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
@@ -299,7 +293,6 @@ drm_detach(struct device *self, int flags)
dev->driver.unload(dev);
drm_mem_uninit();
- DRM_SPINUNINIT(&dev->dev_lock);
return 0;
}
@@ -337,8 +330,6 @@ drm_firstopen(struct drm_device *dev)
drm_local_map_t *map;
int i;
- DRM_SPINLOCK_ASSERT(&dev->dev_lock);
-
/* prebuild the SAREA */
i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM,
_DRM_CONTAINS_LOCK, &map);
@@ -348,8 +339,6 @@ drm_firstopen(struct drm_device *dev)
if (dev->driver.firstopen)
dev->driver.firstopen(dev);
- dev->buf_use = 0;
-
if (dev->driver.use_dma) {
i = drm_dma_setup(dev);
if (i != 0)
@@ -359,7 +348,6 @@ drm_firstopen(struct drm_device *dev)
dev->magicid = 1;
SPLAY_INIT(&dev->magiclist);
- dev->lock.lock_queue = 0;
dev->irq_enabled = 0;
dev->if_version = 0;
@@ -376,8 +364,6 @@ drm_lastclose(struct drm_device *dev)
struct drm_magic_entry *pt;
drm_local_map_t *map, *mapsave;
- DRM_SPINLOCK_ASSERT(&dev->dev_lock);
-
DRM_DEBUG("\n");
if (dev->driver.lastclose != NULL)
@@ -386,6 +372,11 @@ drm_lastclose(struct drm_device *dev)
if (dev->irq_enabled)
drm_irq_uninstall(dev);
+ drm_agp_takedown(dev);
+ drm_drawable_free_all(dev);
+ drm_dma_takedown(dev);
+
+ DRM_LOCK();
if (dev->unique != NULL) {
drm_free(dev->unique, dev->unique_len + 1, DRM_MEM_DRIVER);
dev->unique = NULL;
@@ -398,12 +389,6 @@ drm_lastclose(struct drm_device *dev)
drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
}
- DRM_UNLOCK();
- drm_agp_takedown(dev);
- drm_drawable_free_all(dev);
- drm_dma_takedown(dev);
- DRM_LOCK();
-
if (dev->sg != NULL) {
drm_sg_mem_t *sg = dev->sg;
dev->sg = NULL;
@@ -417,14 +402,15 @@ drm_lastclose(struct drm_device *dev)
map = mapsave) {
mapsave = TAILQ_NEXT(map, link);
if (!(map->flags & _DRM_DRIVER))
- drm_rmmap(dev, map);
+ drm_rmmap_locked(dev, map);
}
if (dev->lock.hw_lock != NULL) {
dev->lock.hw_lock = NULL; /* SHM removed */
dev->lock.file_priv = NULL;
- DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
+ wakeup(&dev->lock); /* there should be nothing sleeping on it */
}
+ DRM_UNLOCK();
return 0;
}
@@ -458,8 +444,9 @@ drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv)
int
drmopen(dev_t kdev, int flags, int fmt, struct proc *p)
{
- struct drm_device *dev = NULL;
- int retcode = 0;
+ struct drm_device *dev = NULL;
+ struct drm_file *priv;
+ int ret = 0;
dev = drm_get_device_from_kdev(kdev);
if (dev == NULL)
@@ -467,16 +454,63 @@ drmopen(dev_t kdev, int flags, int fmt, struct proc *p)
DRM_DEBUG("open_count = %d\n", dev->open_count);
- retcode = drm_open_helper(kdev, flags, fmt, p, dev);
+ if (flags & O_EXCL)
+ return (EBUSY); /* No exclusive opens */
- if (retcode == 0) {
- DRM_LOCK();
- if (dev->open_count++ == 0)
- retcode = drm_firstopen(dev);
+ DRM_LOCK();
+ if (dev->open_count++ == 0) {
+ DRM_UNLOCK();
+ if ((ret = drm_firstopen(dev)) != 0)
+ goto err;
+ } else {
DRM_UNLOCK();
}
- return retcode;
+
+ priv = drm_calloc(1, sizeof(*priv), DRM_MEM_FILES);
+ if (priv == NULL) {
+ ret = ENOMEM;
+ goto err;
+ }
+
+ priv->kdev = kdev;
+ priv->flags = flags;
+ priv->minor = minor(kdev);
+ DRM_DEBUG("minor = %d\n", DRM_CURRENTPID, priv->minor);
+
+ /* for compatibility root is always authenticated */
+ priv->authenticated = DRM_SUSER(p);
+
+ if (dev->driver.open) {
+ /* shared code returns -errno */
+ ret = -dev->driver.open(dev, priv);
+ if (ret != 0) {
+ goto free_priv;
+ }
+ }
+
+ DRM_LOCK();
+ /* first opener automatically becomes master if root */
+ if (TAILQ_EMPTY(&dev->files) && !DRM_SUSER(p)) {
+ DRM_UNLOCK();
+ ret = EPERM;
+ goto free_priv;
+ }
+
+ priv->master = TAILQ_EMPTY(&dev->files);
+
+ TAILQ_INSERT_TAIL(&dev->files, priv, link);
+ DRM_UNLOCK();
+
+ return (0);
+
+free_priv:
+ drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
+err:
+ DRM_LOCK();
+ --dev->open_count;
+ DRM_UNLOCK();
+ return (ret);
}
int
@@ -489,7 +523,6 @@ drmclose(dev_t kdev, int flags, int fmt, struct proc *p)
DRM_DEBUG("open_count = %d\n", dev->open_count);
DRM_LOCK();
-
file_priv = drm_find_file_by_minor(dev, minor(kdev));
if (!file_priv) {
DRM_UNLOCK();
@@ -497,14 +530,11 @@ drmclose(dev_t kdev, int flags, int fmt, struct proc *p)
retcode = EINVAL;
goto done;
}
+ DRM_UNLOCK();
if (dev->driver.preclose != NULL)
dev->driver.preclose(dev, file_priv);
- /* ========================================================
- * Begin inline drm_release
- */
-
DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
DRM_CURRENTPID, (long)&dev->device, dev->open_count);
@@ -520,6 +550,7 @@ drmclose(dev_t kdev, int flags, int fmt, struct proc *p)
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
} else if (dev->driver.reclaim_buffers_locked != NULL &&
dev->lock.hw_lock != NULL) {
+ mtx_enter(&dev->lock.spinlock);
/* The lock is required to reclaim buffers */
for (;;) {
if (dev->lock.hw_lock == NULL) {
@@ -533,11 +564,12 @@ drmclose(dev_t kdev, int flags, int fmt, struct proc *p)
break; /* Got lock */
}
/* Contention */
- retcode = msleep((void *)&dev->lock.lock_queue,
- &dev->dev_lock, PZERO | PCATCH, "drmlk2", 0);
+ retcode = msleep(&dev->lock,
+ &dev->lock.spinlock, PZERO | PCATCH, "drmlk2", 0);
if (retcode)
break;
}
+ mtx_leave(&dev->lock.spinlock);
if (retcode == 0) {
dev->driver.reclaim_buffers_locked(dev, file_priv);
drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT);
@@ -551,15 +583,14 @@ drmclose(dev_t kdev, int flags, int fmt, struct proc *p)
if (dev->driver.postclose != NULL)
dev->driver.postclose(dev, file_priv);
+
+ DRM_LOCK();
TAILQ_REMOVE(&dev->files, file_priv, link);
drm_free(file_priv, sizeof(*file_priv), DRM_MEM_FILES);
- /* ========================================================
- * End inline drm_release
- */
-
done:
if (--dev->open_count == 0) {
+ DRM_UNLOCK();
retcode = drm_lastclose(dev);
}
@@ -647,10 +678,8 @@ drmioctl(dev_t kdev, u_long cmd, caddr_t data, int flags,
return EACCES;
if (is_driver_ioctl) {
- DRM_LOCK();
/* shared code returns -errno */
retcode = -func(dev, data, file_priv);
- DRM_UNLOCK();
} else {
retcode = func(dev, data, file_priv);
}
@@ -666,11 +695,11 @@ drm_getsarea(struct drm_device *dev)
{
drm_local_map_t *map;
- DRM_SPINLOCK_ASSERT(&dev->dev_lock);
+ DRM_LOCK();
TAILQ_FOREACH(map, &dev->maplist, link) {
if (map->type == _DRM_SHM && (map->flags & _DRM_CONTAINS_LOCK))
- return map;
+ break;
}
-
- return NULL;
+ DRM_UNLOCK();
+ return (map);
}
diff --git a/sys/dev/pci/drm/drm_fops.c b/sys/dev/pci/drm/drm_fops.c
index 2f0b007def5..ebf4989bf25 100644
--- a/sys/dev/pci/drm/drm_fops.c
+++ b/sys/dev/pci/drm/drm_fops.c
@@ -49,57 +49,6 @@ drm_find_file_by_minor(struct drm_device *dev, int minor)
return (NULL);
}
-/* drm_open_helper is called whenever a process opens /dev/drm. */
-int
-drm_open_helper(dev_t kdev, int flags, int fmt, struct proc *p,
- struct drm_device *dev)
-{
- struct drm_file *priv;
- int m, retcode;
-
- m = minor(kdev);
- if (flags & O_EXCL)
- return (EBUSY); /* No exclusive opens */
-
- DRM_DEBUG("minor = %d\n", DRM_CURRENTPID, m);
-
- priv = drm_calloc(1, sizeof(*priv), DRM_MEM_FILES);
- if (priv == NULL)
- return (ENOMEM);
-
- priv->kdev = kdev;
- priv->flags = flags;
- priv->minor = m;
-
- /* for compatibility root is always authenticated */
- priv->authenticated = DRM_SUSER(p);
-
- DRM_LOCK();
- if (dev->driver.open) {
- /* shared code returns -errno */
- retcode = -dev->driver.open(dev, priv);
- if (retcode != 0) {
- DRM_UNLOCK();
- drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
- return (retcode);
- }
- }
-
- /* first opener automatically becomes master if root */
- if (TAILQ_EMPTY(&dev->files) && !DRM_SUSER(p)) {
- DRM_UNLOCK();
- drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
- return (EPERM);
- }
-
- priv->master = TAILQ_EMPTY(&dev->files);
-
- TAILQ_INSERT_TAIL(&dev->files, priv, link);
- DRM_UNLOCK();
- return (0);
-}
-
-
/* The drm_read and drm_poll are stubs to prevent spurious errors
* on older X Servers (4.3.0 and earlier) */
diff --git a/sys/dev/pci/drm/drm_irq.c b/sys/dev/pci/drm/drm_irq.c
index 866455ddc03..d3ab01c6df9 100644
--- a/sys/dev/pci/drm/drm_irq.c
+++ b/sys/dev/pci/drm/drm_irq.c
@@ -80,22 +80,22 @@ drm_irq_install(struct drm_device *dev)
const char *istr;
if (dev->irq == 0 || dev->dev_private == NULL)
- return EINVAL;
+ return (EINVAL);
DRM_DEBUG("irq=%d\n", dev->irq);
DRM_LOCK();
if (dev->irq_enabled) {
DRM_UNLOCK();
- return EBUSY;
+ return (EBUSY);
}
dev->irq_enabled = 1;
+ DRM_UNLOCK();
mtx_init(&dev->irq_lock, IPL_BIO);
/* Before installing handler */
dev->driver.irq_preinstall(dev);
- DRM_UNLOCK();
/* Install handler */
if (pci_intr_map(&dev->pa, &ih) != 0) {
@@ -112,9 +112,7 @@ drm_irq_install(struct drm_device *dev)
DRM_DEBUG("%s: interrupting at %s\n", dev->device.dv_xname, istr);
/* After installing handler */
- DRM_LOCK();
dev->driver.irq_postinstall(dev);
- DRM_UNLOCK();
return 0;
err:
@@ -129,10 +127,14 @@ int
drm_irq_uninstall(struct drm_device *dev)
{
- if (!dev->irq_enabled)
- return EINVAL;
+ DRM_LOCK();
+ if (!dev->irq_enabled) {
+ DRM_UNLOCK();
+ return (EINVAL);
+ }
dev->irq_enabled = 0;
+ DRM_UNLOCK();
DRM_DEBUG("irq=%d\n", dev->irq);
@@ -150,28 +152,21 @@ int
drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
struct drm_control *ctl = data;
- int err;
+
+ /* Handle drivers who used to require IRQ setup no longer does. */
+ if (!dev->driver.use_irq)
+ return (0);
switch (ctl->func) {
case DRM_INST_HANDLER:
- /* Handle drivers whose DRM used to require IRQ setup but the
- * no longer does.
- */
- if (!dev->driver.use_irq)
- return 0;
if (dev->if_version < DRM_IF_VERSION(1, 2) &&
ctl->irq != dev->irq)
- return EINVAL;
- return drm_irq_install(dev);
+ return (EINVAL);
+ return (drm_irq_install(dev));
case DRM_UNINST_HANDLER:
- if (!dev->driver.use_irq)
- return 0;
- DRM_LOCK();
- err = drm_irq_uninstall(dev);
- DRM_UNLOCK();
- return err;
+ return (drm_irq_uninstall(dev));
default:
- return EINVAL;
+ return (EINVAL);
}
}
@@ -181,11 +176,11 @@ vblank_disable(void *arg)
struct drm_device *dev = (struct drm_device*)arg;
int i;
+ DRM_SPINLOCK(&dev->vbl_lock);
if (!dev->vblank_disable_allowed)
- return;
+ goto out;
for (i=0; i < dev->num_crtcs; i++){
- DRM_SPINLOCK(&dev->vbl_lock);
if (atomic_read(&dev->vblank[i].vbl_refcount) == 0 &&
dev->vblank[i].vbl_enabled) {
dev->vblank[i].last_vblank =
@@ -193,8 +188,9 @@ vblank_disable(void *arg)
dev->driver.disable_vblank(dev, i);
dev->vblank[i].vbl_enabled = 0;
}
- DRM_SPINUNLOCK(&dev->vbl_lock);
}
+out:
+ DRM_SPINUNLOCK(&dev->vbl_lock);
}
void
@@ -375,18 +371,18 @@ drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
if (flags & _DRM_VBLANK_SIGNAL) {
ret = EINVAL;
} else {
+ DRM_SPINLOCK(&dev->vbl_lock);
while (ret == 0) {
- DRM_SPINLOCK(&dev->vbl_lock);
if ((drm_vblank_count(dev, crtc)
- vblwait->request.sequence) <= (1 << 23)) {
DRM_SPINUNLOCK(&dev->vbl_lock);
break;
}
- ret = msleep(&dev->vblank[crtc].vbl_queue,
+ ret = msleep(&dev->vblank[crtc],
&dev->vbl_lock, PZERO | PCATCH,
"drmvblq", 3 * DRM_HZ);
- DRM_SPINUNLOCK(&dev->vbl_lock);
}
+ DRM_SPINUNLOCK(&dev->vbl_lock);
if (ret != EINTR) {
struct timeval now;
@@ -406,36 +402,34 @@ void
drm_handle_vblank(struct drm_device *dev, int crtc)
{
atomic_inc(&dev->vblank[crtc].vbl_count);
- DRM_WAKEUP(&dev->vblank[crtc].vbl_queue);
+ wakeup(&dev->vblank[crtc]);
}
void
drm_locked_task(void *context, void *pending)
{
struct drm_device *dev = context;
+ void (*func)(struct drm_device *);
DRM_SPINLOCK(&dev->tsk_lock);
-
- DRM_LOCK(); /* XXX drm_lock_take() should do its own locking */
- if (dev->locked_task_call == NULL ||
+ mtx_enter(&dev->lock.spinlock);
+ func = dev->locked_task_call;
+ if (func == NULL ||
drm_lock_take(&dev->lock, DRM_KERNEL_CONTEXT) == 0) {
- DRM_UNLOCK();
+ mtx_leave(&dev->lock.spinlock);
DRM_SPINUNLOCK(&dev->tsk_lock);
return;
}
dev->lock.file_priv = NULL; /* kernel owned */
dev->lock.lock_time = jiffies;
+ mtx_leave(&dev->lock.spinlock);
+ dev->locked_task_call = NULL;
+ DRM_SPINUNLOCK(&dev->tsk_lock);
- DRM_UNLOCK();
-
- dev->locked_task_call(dev);
+ (*func)(dev);
drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT);
-
- dev->locked_task_call = NULL;
-
- DRM_SPINUNLOCK(&dev->tsk_lock);
}
void
diff --git a/sys/dev/pci/drm/drm_lock.c b/sys/dev/pci/drm/drm_lock.c
index e38316dc1ab..9519cb137eb 100644
--- a/sys/dev/pci/drm/drm_lock.c
+++ b/sys/dev/pci/drm/drm_lock.c
@@ -79,41 +79,26 @@ drm_lock_take(struct drm_lock_data *lock_data, unsigned int context)
return 0;
}
-/* This takes a lock forcibly and hands it to context. Should ONLY be used
- inside *_unlock to give lock to kernel before calling *_dma_schedule. */
-int
-drm_lock_transfer(struct drm_lock_data *lock_data, unsigned int context)
-{
- volatile unsigned int *lock = &lock_data->hw_lock->lock;
- unsigned int old, new;
-
- lock_data->file_priv = NULL;
- do {
- old = *lock;
- new = context | _DRM_LOCK_HELD;
- } while (!atomic_cmpset_int(lock, old, new));
-
- return 1;
-}
-
int
drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
{
volatile unsigned int *lock = &lock_data->hw_lock->lock;
unsigned int old, new;
+ mtx_enter(&lock_data->spinlock);
lock_data->file_priv = NULL;
do {
old = *lock;
new = 0;
} while (!atomic_cmpset_int(lock, old, new));
+ mtx_leave(&lock_data->spinlock);
if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
DRM_ERROR("%d freed heavyweight lock held by %d\n",
context, _DRM_LOCKING_CONTEXT(old));
return 1;
}
- DRM_WAKEUP_INT((void *)&lock_data->lock_queue);
+ wakeup(lock_data);
return 0;
}
@@ -136,7 +121,7 @@ drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
if (dev->driver.use_dma_queue && lock->context < 0)
return EINVAL;
- DRM_LOCK();
+ mtx_enter(&dev->lock.spinlock);
for (;;) {
if (drm_lock_take(&dev->lock, lock->context)) {
dev->lock.file_priv = file_priv;
@@ -145,12 +130,12 @@ drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
}
/* Contention */
- ret = msleep((void *)&dev->lock.lock_queue,
- &dev->dev_lock, PZERO | PCATCH, "drmlkq", 0);
+ ret = msleep(&dev->lock, &dev->lock.spinlock,
+ PZERO | PCATCH, "drmlkq", 0);
if (ret != 0)
break;
}
- DRM_UNLOCK();
+ mtx_leave(&dev->lock.spinlock);
DRM_DEBUG("%d %s\n", lock->context, ret ? "interrupted" : "has lock");
if (ret != 0)
@@ -189,13 +174,9 @@ drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
}
DRM_SPINUNLOCK(&dev->tsk_lock);
- DRM_LOCK();
- drm_lock_transfer(&dev->lock, DRM_KERNEL_CONTEXT);
-
- if (drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT)) {
+ if (drm_lock_free(&dev->lock, lock->context)) {
DRM_ERROR("\n");
}
- DRM_UNLOCK();
return 0;
}
diff --git a/sys/dev/pci/drm/i915_dma.c b/sys/dev/pci/drm/i915_dma.c
index b0c8d3b63ac..55ca786db74 100644
--- a/sys/dev/pci/drm/i915_dma.c
+++ b/sys/dev/pci/drm/i915_dma.c
@@ -65,7 +65,7 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
last_head = ring->head;
last_acthd = acthd;
- msleep(dev_priv, &dev->dev_lock, PZERO | PCATCH, "i915wt",
+ tsleep(dev_priv, PZERO | PCATCH, "i915wt",
hz / 100);
}
diff --git a/sys/dev/pci/drm/radeon_cp.c b/sys/dev/pci/drm/radeon_cp.c
index bb6fdb635e5..5c9da607c7c 100644
--- a/sys/dev/pci/drm/radeon_cp.c
+++ b/sys/dev/pci/drm/radeon_cp.c
@@ -1390,8 +1390,7 @@ void radeon_do_release(struct drm_device * dev)
mtx_sleep(&ret, &dev->dev_lock, PZERO, "rdnrel",
1);
#else
- msleep(&ret, &dev->dev_lock, PZERO,
- "rdnrel", 1);
+ tsleep(&ret, PZERO, "rdnrel", 1);
#endif
#endif
}