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-13 16:23:56.000000000 +0200 @@ -546,37 +546,25 @@ 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 verify_ret = 0; + int done = 0; /* last cliprect in the current set of cliprects */ 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 = - copy_and_verify_from_user(GETBUFPTR(copy_buf), buf, - used)) == 0) { + /* FIXME: I dropped copy_and_verify_from_user() test. + * FIXME: Do we need to keep it to check register values ? + */ - copy_buf->used = used; - - DMASETPTR(copy_buf); + DMASETPTR(buf); if (sarea_priv->dirty & ~MACH64_UPLOAD_CLIPRECTS) { ret = mach64_emit_state(filp, dev_priv); @@ -584,7 +572,20 @@ 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 (i.e. and "discard"). + */ do { +#if 0 + DRM_INFO("idx=%3d pending=%d used=%5d discard=%d nbox=%d, i=%d\n", + buf->idx, buf->pending, buf->used, discard, sarea_priv->nbox, i); +#endif + /* Emit the next cliprect */ if (i < sarea_priv->nbox) { ret = @@ -599,29 +600,37 @@ 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) { +#if 0 + DRM_INFO("discard && !done && pending\n"); +#endif DMADISCARDBUF(); - } else if (!done) { + } else { /* This buffer wasn't used (no cliprects or verify failed), so place it back * on the free list */ struct list_head *ptr; drm_mach64_freelist_t *entry; +#if 0 + DRM_INFO("discard && !done\n"); +#endif #if MACH64_EXTRA_CHECKING list_for_each(ptr, &dev_priv->pending) { 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 +640,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); @@ -643,7 +652,7 @@ static int mach64_dma_dispatch_vertex(DR sarea_priv->dirty &= ~MACH64_UPLOAD_CLIPRECTS; sarea_priv->nbox = 0; - return verify_ret; + return 0; } static int mach64_dma_dispatch_blit(DRMFILE filp, drm_device_t * dev, @@ -811,6 +820,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 +835,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 +855,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)