Common subdirectories: drm/linux-core/linux and drm-vtx/linux-core/linux diff -aup -x '.*' -x CVS -x '*.mod.c' -x '*.o' -x '*.ko' drm/linux-core/mach64_drm.h drm-vtx/linux-core/mach64_drm.h --- drm/linux-core/mach64_drm.h 2005-11-29 02:32:00.000000000 +0200 +++ drm-vtx/linux-core/mach64_drm.h 2006-03-13 01:37:19.000000000 +0200 @@ -231,7 +231,7 @@ typedef struct drm_mach64_clear { typedef struct drm_mach64_vertex { int prim; - void *buf; /* Address of vertex buffer */ + int idx; /* Index of vertex buffer */ unsigned long used; /* Number of bytes in buffer */ int discard; /* Client finished with buffer? */ } drm_mach64_vertex_t; diff -aup -x '.*' -x CVS -x '*.mod.c' -x '*.o' -x '*.ko' drm/linux-core/mach64_state.c drm-vtx/linux-core/mach64_state.c --- drm/linux-core/mach64_state.c 2006-03-13 01:48:55.000000000 +0200 +++ drm-vtx/linux-core/mach64_state.c 2006-03-29 21:23:58.000000000 +0300 @@ -480,30 +480,14 @@ static int mach64_do_get_frames_queued(d /* Copy and verify a client submited buffer. * FIXME: Make an assembly optimized version */ -static __inline__ int copy_and_verify_from_user(u32 *to, - const u32 __user *ufrom, - unsigned long bytes) +static __inline__ int verify_from_user(const u32 *from, unsigned long bytes) { - unsigned long n = bytes; /* dwords remaining in buffer */ - u32 *from, *orig_from; - - from = drm_alloc(bytes, DRM_MEM_DRIVER); - if (from == NULL) - return ENOMEM; - - if (DRM_COPY_FROM_USER(from, ufrom, bytes)) { - drm_free(from, bytes, DRM_MEM_DRIVER); - return DRM_ERR(EFAULT); - } - orig_from = from; /* we'll be modifying the "from" ptr, so save it */ - - n >>= 2; + unsigned long n = bytes >> 2; /* dwords remaining in buffer */ while (n > 1) { u32 data, reg, count; data = *from++; - n--; reg = le32_to_cpu(data); @@ -513,30 +497,24 @@ static __inline__ int copy_and_verify_fr reg &= 0xffff; /* This is an exact match of Mach64's Setup Engine registers, - * excluding SETUP_CNTL (1_C1). + * excluding SETUP_CNTL (1_C1), i.e. of VERTEX_k_XXX registers. */ - if ((reg >= 0x0190 && reg < 0x01c1) || + if ((reg >= 0x0190 && reg <= 0x01c0) || (reg >= 0x01ca && reg <= 0x01cf)) { - *to++ = data; - memcpy(to, from, count << 2); from += count; - to += count; } else { DRM_ERROR("%s: Got bad command: 0x%04x\n", __FUNCTION__, reg); - drm_free(orig_from, bytes, DRM_MEM_DRIVER); return DRM_ERR(EACCES); } } else { DRM_ERROR ("%s: Got bad command count(=%u) dwords remaining=%lu\n", __FUNCTION__, count, n); - drm_free(orig_from, bytes, DRM_MEM_DRIVER); return DRM_ERR(EINVAL); } } - drm_free(orig_from, bytes, DRM_MEM_DRIVER); if (n == 0) return 0; else { @@ -546,37 +524,24 @@ static __inline__ int copy_and_verify_fr } static int mach64_dma_dispatch_vertex(DRMFILE filp, drm_device_t * dev, - int prim, void *buf, unsigned long used, - int discard) + drm_buf_t * buf, int prim, int discard) { drm_mach64_private_t *dev_priv = dev->dev_private; drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_buf_t *copy_buf; - int done = 0; + int done = 0; /* last cliprect in the current set of cliprects */ int verify_ret = 0; DMALOCALS; - DRM_DEBUG("%s: buf=%p used=%lu nbox=%d\n", - __FUNCTION__, buf, used, sarea_priv->nbox); + DRM_DEBUG("%s: idx=%d used=%d nbox=%d\n", + __FUNCTION__, buf->idx, buf->used, sarea_priv->nbox); - if (used) { + if (buf->used) { int ret = 0; int i = 0; - copy_buf = mach64_freelist_get(dev_priv); - if (copy_buf == NULL) { - DRM_ERROR("%s: couldn't get buffer in DMAGETPTR\n", - __FUNCTION__); - return DRM_ERR(EAGAIN); - } + if ((verify_ret = verify_from_user(GETBUFPTR(buf), buf->used)) == 0) { - if ((verify_ret = - copy_and_verify_from_user(GETBUFPTR(copy_buf), buf, - used)) == 0) { - - copy_buf->used = used; - - DMASETPTR(copy_buf); + DMASETPTR(buf); if (sarea_priv->dirty & ~MACH64_UPLOAD_CLIPRECTS) { ret = mach64_emit_state(filp, dev_priv); @@ -584,6 +549,14 @@ static int mach64_dma_dispatch_vertex(DR return ret; } + /* The DRI sends the cliprects in sets of size up to + * MACH64_NR_SAREA_CLIPRECTS through an array in the + * SAREA, "discard" is set only for the last set. + * + * We set the discard flag of the DMA buffer only for + * the last cliprect (i.e. when "done") of the last + * set of cliprects (i.e. and "discard"). + */ do { /* Emit the next cliprect */ if (i < sarea_priv->nbox) { @@ -599,18 +572,21 @@ static int mach64_dma_dispatch_vertex(DR continue; } } - if ((i >= sarea_priv->nbox - 1)) + /* cast in order to set done when nbox is zero */ + if (i >= (int)(sarea_priv->nbox) - 1) done = 1; /* Add the buffer to the DMA queue */ - DMAADVANCE(dev_priv, done); - + DMAADVANCE(dev_priv, discard && done); + } while (++i < sarea_priv->nbox); } + } - if (copy_buf->pending && !done) { + if (discard && !done) { + if (buf->pending) { DMADISCARDBUF(); - } else if (!done) { + } else { /* This buffer wasn't used (no cliprects or verify failed), so place it back * on the free list */ @@ -621,7 +597,7 @@ static int mach64_dma_dispatch_vertex(DR entry = list_entry(ptr, drm_mach64_freelist_t, list); - if (copy_buf == entry->buf) { + if (buf == entry->buf) { DRM_ERROR ("%s: Trying to release a pending buf\n", __FUNCTION__); @@ -631,9 +607,9 @@ static int mach64_dma_dispatch_vertex(DR #endif ptr = dev_priv->placeholders.next; entry = list_entry(ptr, drm_mach64_freelist_t, list); - copy_buf->pending = 0; - copy_buf->used = 0; - entry->buf = copy_buf; + buf->pending = 0; + buf->used = 0; + entry->buf = buf; entry->discard = 1; list_del(ptr); list_add_tail(ptr, &dev_priv->free_list); @@ -811,6 +787,8 @@ int mach64_dma_vertex(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mach64_private_t *dev_priv = dev->dev_private; + drm_device_dma_t *dma = dev->dma; + drm_buf_t *buf; drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mach64_vertex_t vertex; @@ -824,10 +802,15 @@ int mach64_dma_vertex(DRM_IOCTL_ARGS) DRM_COPY_FROM_USER_IOCTL(vertex, (drm_mach64_vertex_t *) data, sizeof(vertex)); - DRM_DEBUG("%s: pid=%d buf=%p used=%lu discard=%d\n", + DRM_DEBUG("%s: pid=%d index=%d used=%lu discard=%d\n", __FUNCTION__, DRM_CURRENTPID, - vertex.buf, vertex.used, vertex.discard); + vertex.idx, vertex.used, vertex.discard); + if (vertex.idx < 0 || vertex.idx >= dma->buf_count) { + DRM_ERROR("buffer index %d (of %d max)\n", + vertex.idx, dma->buf_count - 1); + return DRM_ERR(EINVAL); + } if (vertex.prim < 0 || vertex.prim > MACH64_PRIM_POLYGON) { DRM_ERROR("buffer prim %d\n", vertex.prim); return DRM_ERR(EINVAL); @@ -839,11 +822,21 @@ int mach64_dma_vertex(DRM_IOCTL_ARGS) return DRM_ERR(EINVAL); } + buf = dma->buflist[vertex.idx]; + + if (buf->filp != filp) { + DRM_ERROR("process %d (filp %p) using buffer with filp %p\n", + DRM_CURRENTPID, filp, buf->filp); + return DRM_ERR(EINVAL); + } + if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS) sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS; - return mach64_dma_dispatch_vertex(filp, dev, vertex.prim, vertex.buf, - vertex.used, vertex.discard); + buf->used = vertex.used; + + return mach64_dma_dispatch_vertex(filp, dev, buf, vertex.prim, + vertex.discard); } int mach64_dma_blit(DRM_IOCTL_ARGS)