diff options
Diffstat (limited to 'drivers/char/drm')
-rw-r--r-- | drivers/char/drm/agpsupport.c | 6 | ||||
-rw-r--r-- | drivers/char/drm/auth.c | 4 | ||||
-rw-r--r-- | drivers/char/drm/drmP.h | 9 | ||||
-rw-r--r-- | drivers/char/drm/ffb_drv.c | 43 | ||||
-rw-r--r-- | drivers/char/drm/lists.c | 41 | ||||
-rw-r--r-- | drivers/char/drm/lock.c | 32 | ||||
-rw-r--r-- | drivers/char/drm/mga_dma.c | 2 | ||||
-rw-r--r-- | drivers/char/drm/r128_drv.c | 10 | ||||
-rw-r--r-- | drivers/char/drm/vm.c | 5 |
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 */ } |