Fix i915 since last commit.
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)
{
struct drm_mm_type_arg arg;
int ret;
memset(&arg, 0, sizeof(arg));
arg.mem_type = memType;
+ arg.lock_unlock_bm = lock_bm;
do{
ret = ioctl(fd, DRM_IOCTL_MM_LOCK, &arg);
return (ret) ? -errno : 0;
}
-int drmMMUnlock(int fd, unsigned memType)
+int drmMMUnlock(int fd, unsigned memType, int unlockBM)
{
struct drm_mm_type_arg arg;
int ret;
memset(&arg, 0, sizeof(arg));
arg.mem_type = memType;
+ arg.lock_unlock_bm = unlockBM;
do{
ret = ioctl(fd, DRM_IOCTL_MM_UNLOCK, &arg);
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_lock2.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
struct drm_bo_info_req *req = &arg->d.req;
struct drm_bo_info_rep *rep = &arg->d.rep;
int ret;
+
if (!dev->bm.initialized) {
DRM_ERROR("Buffer object manager is not initialized.\n");
return -EINVAL;
}
+ ret = drm_bo_read_lock(&dev->bm.bm_lock);
+ if (ret)
+ return ret;
+
ret = drm_bo_handle_validate(file_priv, req->handle, req->fence_class,
req->flags,
req->mask,
1,
rep, NULL);
+ (void) drm_bo_read_unlock(&dev->bm.bm_lock);
if (ret)
return ret;
static int drm_bo_leave_list(struct drm_buffer_object * bo,
uint32_t mem_type,
- int free_pinned, int allow_errors)
+ int free_pinned,
+ int allow_errors)
{
struct drm_device *dev = bo->dev;
int ret = 0;
unsigned i = DRM_BO_MEM_TYPES;
struct drm_mem_type_manager *man;
- mutex_lock(&dev->bm.init_mutex);
mutex_lock(&dev->struct_mutex);
if (!bm->initialized)
}
out:
mutex_unlock(&dev->struct_mutex);
- mutex_unlock(&dev->bm.init_mutex);
return ret;
}
struct drm_buffer_manager *bm = &dev->bm;
int ret = -EINVAL;
- mutex_lock(&dev->bm.init_mutex);
+ drm_bo_init_lock(&bm->bm_lock);
mutex_lock(&dev->struct_mutex);
if (!driver)
goto out_unlock;
INIT_LIST_HEAD(&bm->ddestroy);
out_unlock:
mutex_unlock(&dev->struct_mutex);
- mutex_unlock(&dev->bm.init_mutex);
return ret;
}
}
ret = -EINVAL;
+ ret = drm_bo_write_lock(&bm->bm_lock, file_priv);
+ if (ret)
+ return ret;
+
if (arg->magic != DRM_BO_INIT_MAGIC) {
DRM_ERROR("You are using an old libdrm that is not compatible with\n"
"\tthe kernel DRM module. Please upgrade your libdrm.\n");
return -EINVAL;
}
- mutex_lock(&dev->bm.init_mutex);
mutex_lock(&dev->struct_mutex);
if (!bm->initialized) {
DRM_ERROR("DRM memory manager was not initialized.\n");
out:
mutex_unlock(&dev->struct_mutex);
- mutex_unlock(&dev->bm.init_mutex);
+ (void) drm_bo_write_unlock(&bm->bm_lock, file_priv);
+
if (ret)
return ret;
return -EINVAL;
}
- LOCK_TEST_WITH_RETURN(dev, file_priv);
- mutex_lock(&dev->bm.init_mutex);
+ ret = drm_bo_write_lock(&bm->bm_lock, file_priv);
+ if (ret)
+ return ret;
+
mutex_lock(&dev->struct_mutex);
ret = -EINVAL;
if (!bm->initialized) {
}
out:
mutex_unlock(&dev->struct_mutex);
- mutex_unlock(&dev->bm.init_mutex);
+ (void) drm_bo_write_unlock(&bm->bm_lock, file_priv);
+
if (ret)
return ret;
return -EINVAL;
}
- LOCK_TEST_WITH_RETURN(dev, file_priv);
- mutex_lock(&dev->bm.init_mutex);
+ if (arg->lock_unlock_bm) {
+ ret = drm_bo_write_lock(&dev->bm.bm_lock, file_priv);
+ if (ret)
+ return ret;
+ }
+
mutex_lock(&dev->struct_mutex);
ret = drm_bo_lock_mm(dev, arg->mem_type);
mutex_unlock(&dev->struct_mutex);
- mutex_unlock(&dev->bm.init_mutex);
- if (ret)
+ if (ret) {
+ (void) drm_bo_write_unlock(&dev->bm.bm_lock, file_priv);
return ret;
+ }
return 0;
}
-int drm_mm_unlock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+int drm_mm_unlock_ioctl(struct drm_device *dev,
+ void *data,
+ struct drm_file *file_priv)
{
+ struct drm_mm_type_arg *arg = data;
struct drm_bo_driver *driver = dev->driver->bo_driver;
int ret;
return -EINVAL;
}
- LOCK_TEST_WITH_RETURN(dev, file_priv);
- mutex_lock(&dev->bm.init_mutex);
- mutex_lock(&dev->struct_mutex);
- ret = 0;
-
- mutex_unlock(&dev->struct_mutex);
- mutex_unlock(&dev->bm.init_mutex);
- if (ret)
- return ret;
-
+ if (arg->lock_unlock_bm) {
+ ret = drm_bo_write_unlock(&dev->bm.bm_lock, file_priv);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
--- /dev/null
+#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) == 0))
+ BUG();
+ if (atomic_read(&lock->readers) == 0)
+ wake_up_interruptible(&lock->queue);
+}
+
+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;
+}
+
+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;
+ }
+ }
+
+ 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)
+{
+ return drm_user_object_unref(file_priv, lock->base.hash.key,
+ drm_lock_type);
+}
enum drm_object_type {
drm_fence_type,
drm_buffer_type,
+ drm_lock_type,
/*
* Add other user space object types here.
*/
void *io_addr;
};
+struct drm_bo_lock {
+ struct drm_user_object base;
+ wait_queue_head_t queue;
+ atomic_t write_lock_pending;
+ atomic_t readers;
+};
+
#define _DRM_FLAG_MEMTYPE_FIXED 0x00000001 /* Fixed (on-card) PCI memory */
#define _DRM_FLAG_MEMTYPE_MAPPABLE 0x00000002 /* Memory mappable */
#define _DRM_FLAG_MEMTYPE_CACHED 0x00000004 /* Cached binding */
#define _DRM_FLAG_MEMTYPE_CSELECT 0x00000020 /* Select caching */
struct drm_buffer_manager {
- struct mutex init_mutex;
- struct mutex evict_mutex;
+ struct drm_bo_lock bm_lock;
+ struct mutex evict_mutex;
int nice_mode;
int initialized;
struct drm_file *last_to_validate;
const void *),
void (*reg_destroy)(struct drm_reg *));
+/*
+ * drm_bo_lock.c
+ * Simple replacement for the hardware lock on buffer manager init and clean.
+ */
+
+
+extern void drm_bo_init_lock(struct drm_bo_lock *lock);
+extern void drm_bo_read_unlock(struct drm_bo_lock *lock);
+extern int drm_bo_read_lock(struct drm_bo_lock *lock);
+extern int drm_bo_write_lock(struct drm_bo_lock *lock,
+ struct drm_file *file_priv);
+
+extern int drm_bo_write_unlock(struct drm_bo_lock *lock,
+ struct drm_file *file_priv);
+
#ifdef CONFIG_DEBUG_MUTEXES
#define DRM_ASSERT_LOCKED(_mutex) \
BUG_ON(!mutex_is_locked(_mutex) || \
init_timer(&dev->timer);
mutex_init(&dev->struct_mutex);
mutex_init(&dev->ctxlist_mutex);
- mutex_init(&dev->bm.init_mutex);
mutex_init(&dev->bm.evict_mutex);
idr_init(&dev->drw_idr);
struct drm_mm_type_arg {
unsigned int mem_type;
+ int lock_unlock_bm;
};
struct drm_mm_init_arg {
req->bo_req.flags,
req->bo_req.mask,
req->bo_req.hint,
+ 0,
&rep.bo_info,
&buffers[buf_count]);