[intel-gem] throttle based on frames rather than time. Reduces jitter.
authorKeith Packard <keithp@keithp.com>
Fri, 13 Jun 2008 19:06:13 +0000 (12:06 -0700)
committerKeith Packard <keithp@keithp.com>
Fri, 13 Jun 2008 21:29:46 +0000 (14:29 -0700)
Record the last execbuffer sequence for each client.
Record that sequence in the throttle ioctl as the 'throttle sequence'.
Wait for the last throttle sequence in the throttle ioctl.

linux-core/i915_drv.c
linux-core/i915_gem.c
shared-core/i915_dma.c
shared-core/i915_drv.h

index 89f089b..012ca82 100644 (file)
@@ -561,6 +561,7 @@ static int i915_resume(struct drm_device *dev)
 
 static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
 static void remove(struct pci_dev *pdev);
+
 static struct drm_driver driver = {
        /* don't use mtrr's here, the Xserver or user space app should
         * deal with them for intel hardware.
@@ -571,8 +572,10 @@ static struct drm_driver driver = {
        .load = i915_driver_load,
        .unload = i915_driver_unload,
        .firstopen = i915_driver_firstopen,
+       .open = i915_driver_open,
        .lastclose = i915_driver_lastclose,
        .preclose = i915_driver_preclose,
+       .postclose = i915_driver_postclose,
        .suspend = i915_suspend,
        .resume = i915_resume,
        .device_is_agp = i915_driver_device_is_agp,
index b114192..c2d1fab 100644 (file)
@@ -1548,33 +1548,17 @@ i915_dispatch_gem_execbuffer(struct drm_device *dev,
  * relatively low latency when blocking on a particular request to finish.
  */
 static int
-i915_gem_ring_throttle(struct drm_device *dev)
+i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
        int ret = 0;
+       uint32_t seqno;
 
        mutex_lock(&dev->struct_mutex);
-       while (!list_empty(&dev_priv->mm.request_list)) {
-               struct drm_i915_gem_request *request;
-
-               request = list_first_entry(&dev_priv->mm.request_list,
-                                          struct drm_i915_gem_request,
-                                          list);
-
-               /* Break out if we're close enough. */
-               if ((long) (jiffies - request->emitted_jiffies) <=
-                   (20 * HZ) / 1000) {
-                       mutex_unlock(&dev->struct_mutex);
-                       return 0;
-               }
-
-               /* Wait on the last request if not. */
-               ret = i915_wait_request(dev, request->seqno);
-               if (ret != 0) {
-                       mutex_unlock(&dev->struct_mutex);
-                       return ret;
-               }
-       }
+       seqno = i915_file_priv->mm.last_gem_throttle_seqno;
+       i915_file_priv->mm.last_gem_throttle_seqno = i915_file_priv->mm.last_gem_seqno;
+       if (seqno)
+               ret = i915_wait_request(dev, seqno);
        mutex_unlock(&dev->struct_mutex);
        return ret;
 }
@@ -1584,6 +1568,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
                    struct drm_file *file_priv)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
        struct drm_i915_gem_execbuffer *args = data;
        struct drm_i915_gem_exec_object *exec_list = NULL;
        struct drm_gem_object **object_list = NULL;
@@ -1724,6 +1709,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
         */
        seqno = i915_add_request(dev, flush_domains);
        BUG_ON(seqno == 0);
+       i915_file_priv->mm.last_gem_seqno = seqno;
        for (i = 0; i < args->buffer_count; i++) {
                struct drm_gem_object *obj = object_list[i];
                struct drm_i915_gem_object *obj_priv = obj->driver_private;
@@ -1881,7 +1867,7 @@ int
 i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
                        struct drm_file *file_priv)
 {
-    return i915_gem_ring_throttle(dev);
+    return i915_gem_ring_throttle(dev, file_priv);
 }
 
 int i915_gem_init_object(struct drm_gem_object *obj)
index 669f1e4..2157c59 100644 (file)
@@ -1149,12 +1149,38 @@ void i915_driver_lastclose(struct drm_device * dev)
        i915_dma_cleanup(dev);
 }
 
+int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
+{
+       struct drm_i915_file_private *i915_file_priv;
+
+       DRM_DEBUG("\n");
+       i915_file_priv = (struct drm_i915_file_private *)
+           drm_alloc(sizeof(*i915_file_priv), DRM_MEM_FILES);
+
+       if (!i915_file_priv)
+               return -ENOMEM;
+
+       file_priv->driver_priv = i915_file_priv;
+
+       i915_file_priv->mm.last_gem_seqno = 0;
+       i915_file_priv->mm.last_gem_throttle_seqno = 0;
+
+       return 0;
+}
+
 void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        i915_mem_release(dev, file_priv, dev_priv->agp_heap);
 }
 
+void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
+{
+       struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
+
+       drm_free(i915_file_priv, sizeof(*i915_file_priv), DRM_MEM_FILES);
+}
+
 struct drm_ioctl_desc i915_ioctls[] = {
        DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
index 5cc6e68..334bc43 100644 (file)
@@ -301,6 +301,13 @@ typedef struct drm_i915_private {
        } mm;
 } drm_i915_private_t;
 
+struct drm_i915_file_private {
+       struct {
+               uint32_t last_gem_seqno;
+               uint32_t last_gem_throttle_seqno;
+       } mm;
+};
+
 enum intel_chip_family {
        CHIP_I8XX = 0x01,
        CHIP_I9XX = 0x02,
@@ -378,8 +385,11 @@ extern void i915_kernel_lost_context(struct drm_device * dev);
 extern int i915_driver_load(struct drm_device *, unsigned long flags);
 extern int i915_driver_unload(struct drm_device *);
 extern void i915_driver_lastclose(struct drm_device * dev);
+extern int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv);
 extern void i915_driver_preclose(struct drm_device *dev,
                                 struct drm_file *file_priv);
+extern void i915_driver_postclose(struct drm_device *dev,
+                                 struct drm_file *file_priv);
 extern int i915_driver_device_is_agp(struct drm_device * dev);
 extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
                              unsigned long arg);