Hello Vladimir,

I've attached a patch which implements the RADOEN_CMD_DMA_DISCARD ioctl from
the radeon/r200 drm. I thought I'd post here before commiting to cvs in case I've
done something bad.


Without this, eventually r300AllocDmaRegion will get stuck in a loop continually calling
drmDMA (r300_ioctl.c::r300RefillCurrentDmaRegion).


It seems that the drm buffer management code depends on having a scratch register
containing the "age" of a buffer. I'm not sure of the details, I just know that it stops
the infinite drmDMA loop.


Is this the correct way of fixing this? Or have I completely missed something?

Regards,
Ben Skeggs.

diff -Nur drm.old/shared-core/r300_cmdbuf.c drm/shared-core/r300_cmdbuf.c
--- drm.old/shared-core/r300_cmdbuf.c   2005-01-08 13:46:34.000000000 +1100
+++ drm/shared-core/r300_cmdbuf.c       2005-02-06 20:20:06.910617312 +1100
@@ -354,16 +354,37 @@
        return 0;
 }
 
+static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
+{
+    drm_radeon_private_t *dev_priv = dev->dev_private;
+    drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+    RING_LOCALS;
+
+    buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
+
+    /* Emit the vertex buffer age */
+    BEGIN_RING(2);
+    RADEON_DISPATCH_AGE(buf_priv->age);
+    ADVANCE_RING();
+
+    buf->pending = 1;
+    buf->used = 0;
+}
+
+
 /**
  * Parses and validates a user-supplied command buffer and emits appropriate
  * commands on the DMA ring buffer.
  * Called by the ioctl handler function radeon_cp_cmdbuf.
  */
 int r300_do_cp_cmdbuf(drm_device_t* dev,
+                         DRMFILE filp,
                      drm_file_t* filp_priv,
                      drm_radeon_cmd_buffer_t* cmdbuf)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
+    drm_device_dma_t *dma = dev->dma;
+    drm_buf_t *buf = NULL;
        int ret;
 
        DRM_DEBUG("\n");
@@ -375,6 +396,7 @@
        }
 
        while(cmdbuf->bufsz >= sizeof(drm_r300_cmd_header_t)) {
+               int idx;
                drm_r300_cmd_header_t header;
 
                if (DRM_GET_USER_UNCHECKED(header.u, (int __user*)cmdbuf->buf)) 
{
@@ -431,6 +453,26 @@
                                ADVANCE_RING();
                        }
                        return 0;
+
+               case R300_CMD_DMA_DISCARD:
+                       DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
+            idx = header.dma.buf_idx;
+            if (idx < 0 || idx >= dma->buf_count) {
+                DRM_ERROR("buffer index %d (of %d max)\n",
+                      idx, dma->buf_count - 1);
+                return DRM_ERR(EINVAL);
+            }
+               
+            buf = dma->buflist[idx];
+            if (buf->filp != filp || buf->pending) {
+                DRM_ERROR("bad buffer %p %p %d\n",
+                      buf->filp, filp, buf->pending);
+                return DRM_ERR(EINVAL);
+            }
+
+            r300_discard_buffer(dev, buf);
+            break;
+
                default:
                        DRM_ERROR("bad cmd_type %i at %p\n",
                                  header.header.cmd_type,
diff -Nur drm.old/shared-core/radeon_drm.h drm/shared-core/radeon_drm.h
--- drm.old/shared-core/radeon_drm.h    2005-01-02 05:32:52.000000000 +1100
+++ drm/shared-core/radeon_drm.h        2005-02-06 20:20:06.910617312 +1100
@@ -199,6 +199,7 @@
 #define R300_CMD_PACKET3               3 /* emit a packet3 */
 #define R300_CMD_END3D                 4 /* emit sequence ending 3d rendering 
*/
 #define R300_CMD_CP_DELAY              5
+#define R300_CMD_DMA_DISCARD   6
 
 typedef union {
        unsigned int u;
@@ -218,6 +219,9 @@
                unsigned char cmd_type, packet;
                unsigned short count; /* amount of packet2 to emit */
        } delay;
+       struct {
+               unsigned char cmd_type, buf_idx, pad0, pad1;
+       } dma;
 } drm_r300_cmd_header_t;
 
 #define RADEON_FRONT                   0x1
diff -Nur drm.old/shared-core/radeon_drv.h drm/shared-core/radeon_drv.h
--- drm.old/shared-core/radeon_drv.h    2004-12-28 07:44:39.000000000 +1100
+++ drm/shared-core/radeon_drv.h        2005-02-06 20:20:06.910617312 +1100
@@ -310,6 +310,7 @@
 
 /* r300_cmdbuf.c */
 extern int r300_do_cp_cmdbuf( drm_device_t* dev,
+                                 DRMFILE filp,
                              drm_file_t* filp_priv,
                              drm_radeon_cmd_buffer_t* cmdbuf );
 
diff -Nur drm.old/shared-core/radeon_state.c drm/shared-core/radeon_state.c
--- drm.old/shared-core/radeon_state.c  2005-01-31 13:33:24.000000000 +1100
+++ drm/shared-core/radeon_state.c      2005-02-06 20:20:06.909617464 +1100
@@ -2469,7 +2469,7 @@
                return DRM_ERR(EFAULT);
 
        if ( IS_FAMILY_R300(dev_priv) )
-               return r300_do_cp_cmdbuf(dev, filp_priv, &cmdbuf);
+               return r300_do_cp_cmdbuf(dev, filp, filp_priv, &cmdbuf);
        else
                return radeon_do_cp_cmdbuf(dev, filp, filp_priv, &cmdbuf);
 }

Reply via email to