summaryrefslogtreecommitdiffstats
path: root/drivers/char/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/drm')
-rw-r--r--drivers/char/drm/agpsupport.c6
-rw-r--r--drivers/char/drm/auth.c4
-rw-r--r--drivers/char/drm/drmP.h9
-rw-r--r--drivers/char/drm/ffb_drv.c43
-rw-r--r--drivers/char/drm/lists.c41
-rw-r--r--drivers/char/drm/lock.c32
-rw-r--r--drivers/char/drm/mga_dma.c2
-rw-r--r--drivers/char/drm/r128_drv.c10
-rw-r--r--drivers/char/drm/vm.c5
9 files changed, 97 insertions, 55 deletions
diff --git a/drivers/char/drm/agpsupport.c b/drivers/char/drm/agpsupport.c
index 7ed234e15..42a1bc2f6 100644
--- a/drivers/char/drm/agpsupport.c
+++ b/drivers/char/drm/agpsupport.c
@@ -309,7 +309,9 @@ drm_agp_head_t *drm_agp_init(void)
#if LINUX_VERSION_CODE >= 0x020400
case VIA_MVP4: head->chipset = "VIA MVP4"; break;
- case VIA_APOLLO_SUPER: head->chipset = "VIA Apollo Super";
+ case VIA_APOLLO_KX133: head->chipset = "VIA Apollo KX133";
+ break;
+ case VIA_APOLLO_KT133: head->chipset = "VIA Apollo KT133";
break;
#endif
@@ -322,7 +324,7 @@ drm_agp_head_t *drm_agp_init(void)
case ALI_M1541: head->chipset = "ALi M1541"; break;
default: head->chipset = "Unknown"; break;
}
- DRM_INFO("AGP %d.%d on %s @ 0x%08lx %dMB\n",
+ DRM_INFO("AGP %d.%d on %s @ 0x%08lx %ZuMB\n",
head->agp_info.version.major,
head->agp_info.version.minor,
head->chipset,
diff --git a/drivers/char/drm/auth.c b/drivers/char/drm/auth.c
index 9f81c5391..4556bd966 100644
--- a/drivers/char/drm/auth.c
+++ b/drivers/char/drm/auth.c
@@ -126,12 +126,12 @@ int drm_getmagic(struct inode *inode, struct file *filp, unsigned int cmd,
if (priv->magic) {
auth.magic = priv->magic;
} else {
- spin_lock(&lock);
do {
+ spin_lock(&lock);
if (!sequence) ++sequence; /* reserve 0 */
auth.magic = sequence++;
+ spin_unlock(&lock);
} while (drm_find_file(dev, auth.magic));
- spin_unlock(&lock);
priv->magic = auth.magic;
drm_add_magic(dev, priv, auth.magic);
}
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 0fa205717..e8ec9bdbc 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -328,6 +328,7 @@ typedef struct drm_freelist {
int low_mark; /* Low water mark */
int high_mark; /* High water mark */
atomic_t wfh; /* If waiting for high mark */
+ spinlock_t lock;
} drm_freelist_t;
typedef struct drm_buf_entry {
@@ -450,6 +451,11 @@ typedef struct {
extern drm_agp_func_t drm_agp;
#endif
+typedef struct drm_sigdata {
+ int context;
+ drm_hw_lock_t *lock;
+} drm_sigdata_t;
+
typedef struct drm_device {
const char *name; /* Simple driver name */
char *unique; /* Unique identifier: e.g., busid */
@@ -534,6 +540,8 @@ typedef struct drm_device {
#endif
unsigned long *ctx_bitmap;
void *dev_private;
+ drm_sigdata_t sigdata; /* For block_all_signals */
+ sigset_t sigmask;
} drm_device_t;
@@ -728,6 +736,7 @@ extern int drm_flush_unblock(drm_device_t *dev, int context,
drm_lock_flags_t flags);
extern int drm_flush_block_and_flush(drm_device_t *dev, int context,
drm_lock_flags_t flags);
+extern int drm_notifier(void *priv);
/* Context Bitmap support (ctxbitmap.c) */
extern int drm_ctxbitmap_init(drm_device_t *dev);
diff --git a/drivers/char/drm/ffb_drv.c b/drivers/char/drm/ffb_drv.c
index d81685230..84c7f0644 100644
--- a/drivers/char/drm/ffb_drv.c
+++ b/drivers/char/drm/ffb_drv.c
@@ -1,4 +1,4 @@
-/* $Id: ffb_drv.c,v 1.5 2000/07/26 01:03:57 davem Exp $
+/* $Id: ffb_drv.c,v 1.6 2000/08/10 05:26:23 davem Exp $
* ffb_drv.c: Creator/Creator3D direct rendering driver.
*
* Copyright (C) 2000 David S. Miller (davem@redhat.com)
@@ -754,6 +754,7 @@ static void align_shm_mapping(struct vm_area_struct *vma, unsigned long kvirt)
extern struct vm_operations_struct drm_vm_ops;
extern struct vm_operations_struct drm_vm_shm_ops;
+extern struct vm_operations_struct drm_vm_shm_lock_ops;
static int ffb_mmap(struct file *filp, struct vm_area_struct *vma)
{
@@ -766,7 +767,6 @@ static int ffb_mmap(struct file *filp, struct vm_area_struct *vma)
DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
vma->vm_start, vma->vm_end, VM_OFFSET(vma));
- lock_kernel();
minor = MINOR(filp->f_dentry->d_inode->i_rdev);
ffb_priv = NULL;
for (i = 0; i < ffb_dev_table_size; i++) {
@@ -774,15 +774,13 @@ static int ffb_mmap(struct file *filp, struct vm_area_struct *vma)
if (ffb_priv->miscdev.minor == minor)
break;
}
- if (i >= ffb_dev_table_size) {
- unlock_kernel();
+ if (i >= ffb_dev_table_size)
return -EINVAL;
- }
+
/* We don't support/need dma mappings, so... */
- if (!VM_OFFSET(vma)) {
- unlock_kernel();
+ if (!VM_OFFSET(vma))
return -EINVAL;
- }
+
for (i = 0; i < dev->map_count; i++) {
unsigned long off;
@@ -794,19 +792,16 @@ static int ffb_mmap(struct file *filp, struct vm_area_struct *vma)
break;
}
- if (i >= dev->map_count) {
- unlock_kernel();
+ if (i >= dev->map_count)
return -EINVAL;
- }
+
if (!map ||
- ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) {
- unlock_kernel();
+ ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
return -EPERM;
- }
- if (map->size != (vma->vm_end - vma->vm_start)) {
- unlock_kernel();
+
+ if (map->size != (vma->vm_end - vma->vm_start))
return -EINVAL;
- }
+
/* Set read-only attribute before mappings are created
* so it works for fb/reg maps too.
*/
@@ -829,15 +824,19 @@ static int ffb_mmap(struct file *filp, struct vm_area_struct *vma)
if (io_remap_page_range(vma->vm_start,
ffb_priv->card_phys_base + VM_OFFSET(vma),
vma->vm_end - vma->vm_start,
- vma->vm_page_prot, 0)) {
- unlock_kernel();
+ vma->vm_page_prot, 0))
return -EAGAIN;
- }
+
vma->vm_ops = &drm_vm_ops;
break;
case _DRM_SHM:
align_shm_mapping(vma, (unsigned long)dev->lock.hw_lock);
- vma->vm_ops = &drm_vm_shm_ops;
+ if (map->flags & _DRM_CONTAINS_LOCK)
+ vma->vm_ops = &drm_vm_shm_lock_ops;
+ else {
+ vma->vm_ops = &drm_vm_shm_ops;
+ vma->vm_private_data = (void *) map;
+ }
/* Don't let this area swap. Change when
* DRM_KERNEL advisory is supported.
@@ -845,10 +844,8 @@ static int ffb_mmap(struct file *filp, struct vm_area_struct *vma)
vma->vm_flags |= VM_LOCKED;
break;
default:
- unlock_kernel();
return -EINVAL; /* This should never happen. */
};
- unlock_kernel();
vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
diff --git a/drivers/char/drm/lists.c b/drivers/char/drm/lists.c
index f62495aa2..5da7cc6c5 100644
--- a/drivers/char/drm/lists.c
+++ b/drivers/char/drm/lists.c
@@ -116,6 +116,7 @@ int drm_freelist_create(drm_freelist_t *bl, int count)
bl->low_mark = 0;
bl->high_mark = 0;
atomic_set(&bl->wfh, 0);
+ bl->lock = SPIN_LOCK_UNLOCKED;
++bl->initialized;
return 0;
}
@@ -130,8 +131,6 @@ int drm_freelist_destroy(drm_freelist_t *bl)
int drm_freelist_put(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf)
{
- drm_buf_t *old, *prev;
- int count = 0;
drm_device_dma_t *dma = dev->dma;
if (!dma) {
@@ -152,15 +151,12 @@ int drm_freelist_put(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf)
drm_histogram_compute(dev, buf);
#endif
buf->list = DRM_LIST_FREE;
- do {
- old = bl->next;
- buf->next = old;
- prev = cmpxchg(&bl->next, old, buf);
- if (++count > DRM_LOOPING_LIMIT) {
- DRM_ERROR("Looping\n");
- return 1;
- }
- } while (prev != old);
+
+ spin_lock(&bl->lock);
+ buf->next = bl->next;
+ bl->next = buf;
+ spin_unlock(&bl->lock);
+
atomic_inc(&bl->count);
if (atomic_read(&bl->count) > dma->buf_count) {
DRM_ERROR("%d of %d buffers free after addition of %d\n",
@@ -177,26 +173,21 @@ int drm_freelist_put(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf)
static drm_buf_t *drm_freelist_try(drm_freelist_t *bl)
{
- drm_buf_t *old, *new, *prev;
drm_buf_t *buf;
- int count = 0;
if (!bl) return NULL;
/* Get buffer */
- do {
- old = bl->next;
- if (!old) return NULL;
- new = bl->next->next;
- prev = cmpxchg(&bl->next, old, new);
- if (++count > DRM_LOOPING_LIMIT) {
- DRM_ERROR("Looping\n");
- return NULL;
- }
- } while (prev != old);
- atomic_dec(&bl->count);
+ spin_lock(&bl->lock);
+ if (!bl->next) {
+ spin_unlock(&bl->lock);
+ return NULL;
+ }
+ buf = bl->next;
+ bl->next = bl->next->next;
+ spin_unlock(&bl->lock);
- buf = old;
+ atomic_dec(&bl->count);
buf->next = NULL;
buf->list = DRM_LIST_NONE;
DRM_DEBUG("%d, count = %d, wfh = %d, w%d, p%d\n",
diff --git a/drivers/char/drm/lock.c b/drivers/char/drm/lock.c
index 550827278..33b2cc03f 100644
--- a/drivers/char/drm/lock.c
+++ b/drivers/char/drm/lock.c
@@ -223,3 +223,35 @@ int drm_finish(struct inode *inode, struct file *filp, unsigned int cmd,
drm_flush_unblock(dev, lock.context, lock.flags);
return ret;
}
+
+/* If we get here, it means that the process has called DRM_IOCTL_LOCK
+ without calling DRM_IOCTL_UNLOCK.
+
+ If the lock is not held, then let the signal proceed as usual.
+
+ If the lock is held, then set the contended flag and keep the signal
+ blocked.
+
+
+ Return 1 if the signal should be delivered normally.
+ Return 0 if the signal should be blocked. */
+
+int drm_notifier(void *priv)
+{
+ drm_sigdata_t *s = (drm_sigdata_t *)priv;
+ unsigned int old, new, prev;
+
+
+ /* Allow signal delivery if lock isn't held */
+ if (!_DRM_LOCK_IS_HELD(s->lock->lock)
+ || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context) return 1;
+
+ /* Otherwise, set flag to force call to
+ drmUnlock */
+ do {
+ old = s->lock->lock;
+ new = old | _DRM_LOCK_CONT;
+ prev = cmpxchg(&s->lock->lock, old, new);
+ } while (prev != old);
+ return 0;
+}
diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
index d02c3b581..0df0906e5 100644
--- a/drivers/char/drm/mga_dma.c
+++ b/drivers/char/drm/mga_dma.c
@@ -765,7 +765,7 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
dev_priv->mAccess = init->mAccess;
init_waitqueue_head(&dev_priv->flush_queue);
init_waitqueue_head(&dev_priv->buf_queue);
- dev_priv->WarpPipe = -1;
+ dev_priv->WarpPipe = 0xff000000;
DRM_DEBUG("chipset: %d ucode_size: %d backOffset: %x depthOffset: %x\n",
dev_priv->chipset, dev_priv->warp_ucode_size,
diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
index fac882471..e0080e595 100644
--- a/drivers/char/drm/r128_drv.c
+++ b/drivers/char/drm/r128_drv.c
@@ -656,6 +656,14 @@ int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd,
#endif
if (!ret) {
+ sigemptyset(&dev->sigmask);
+ sigaddset(&dev->sigmask, SIGSTOP);
+ sigaddset(&dev->sigmask, SIGTSTP);
+ sigaddset(&dev->sigmask, SIGTTIN);
+ sigaddset(&dev->sigmask, SIGTTOU);
+ dev->sigdata.context = lock.context;
+ dev->sigdata.lock = dev->lock.hw_lock;
+ block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
if (lock.flags & _DRM_LOCK_READY) {
/* Wait for space in DMA/FIFO */
}
@@ -719,6 +727,6 @@ int r128_unlock(struct inode *inode, struct file *filp, unsigned int cmd,
current->priority = DEF_PRIORITY;
}
#endif
-
+ unblock_all_signals();
return 0;
}
diff --git a/drivers/char/drm/vm.c b/drivers/char/drm/vm.c
index d295529ba..7c5a24bc9 100644
--- a/drivers/char/drm/vm.c
+++ b/drivers/char/drm/vm.c
@@ -250,7 +250,7 @@ int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
vma->vm_start, vma->vm_end, VM_OFFSET(vma));
/* Length must match exact page count */
- if ((length >> PAGE_SHIFT) != dma->page_count) {
+ if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
unlock_kernel();
return -EINVAL;
}
@@ -323,6 +323,9 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
}
+#elif defined(__ia64__)
+ if (map->type != _DRM_AGP)
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
#endif
vma->vm_flags |= VM_IO; /* not in core dump */
}