diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/drm/drmP.h | 44 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_agpsupport.c | 60 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_auth.c | 2 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_bufs.c | 56 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_context.c | 10 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_dma.c | 2 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_drawable.c | 10 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_drv.c | 127 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_fops.c | 51 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_irq.c | 74 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_lock.c | 35 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915_dma.c | 2 | ||||
-rw-r--r-- | sys/dev/pci/drm/radeon_cp.c | 3 |
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 } |