[intel-gem] throttle based on frames rather than time. Reduces jitter.

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.
main
Keith Packard 2008-06-13 12:06:13 -07:00
parent 6b2cba1ecc
commit ced9ebf645
4 changed files with 49 additions and 24 deletions

View 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 int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
static void remove(struct pci_dev *pdev); static void remove(struct pci_dev *pdev);
static struct drm_driver driver = { static struct drm_driver driver = {
/* don't use mtrr's here, the Xserver or user space app should /* don't use mtrr's here, the Xserver or user space app should
* deal with them for intel hardware. * deal with them for intel hardware.
@ -571,8 +572,10 @@ static struct drm_driver driver = {
.load = i915_driver_load, .load = i915_driver_load,
.unload = i915_driver_unload, .unload = i915_driver_unload,
.firstopen = i915_driver_firstopen, .firstopen = i915_driver_firstopen,
.open = i915_driver_open,
.lastclose = i915_driver_lastclose, .lastclose = i915_driver_lastclose,
.preclose = i915_driver_preclose, .preclose = i915_driver_preclose,
.postclose = i915_driver_postclose,
.suspend = i915_suspend, .suspend = i915_suspend,
.resume = i915_resume, .resume = i915_resume,
.device_is_agp = i915_driver_device_is_agp, .device_is_agp = i915_driver_device_is_agp,

View File

@ -1548,33 +1548,17 @@ i915_dispatch_gem_execbuffer(struct drm_device *dev,
* relatively low latency when blocking on a particular request to finish. * relatively low latency when blocking on a particular request to finish.
*/ */
static int 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; int ret = 0;
uint32_t seqno;
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
while (!list_empty(&dev_priv->mm.request_list)) { seqno = i915_file_priv->mm.last_gem_throttle_seqno;
struct drm_i915_gem_request *request; i915_file_priv->mm.last_gem_throttle_seqno = i915_file_priv->mm.last_gem_seqno;
if (seqno)
request = list_first_entry(&dev_priv->mm.request_list, ret = i915_wait_request(dev, seqno);
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;
}
}
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return ret; return ret;
} }
@ -1584,6 +1568,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; 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_execbuffer *args = data;
struct drm_i915_gem_exec_object *exec_list = NULL; struct drm_i915_gem_exec_object *exec_list = NULL;
struct drm_gem_object **object_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); seqno = i915_add_request(dev, flush_domains);
BUG_ON(seqno == 0); BUG_ON(seqno == 0);
i915_file_priv->mm.last_gem_seqno = seqno;
for (i = 0; i < args->buffer_count; i++) { for (i = 0; i < args->buffer_count; i++) {
struct drm_gem_object *obj = object_list[i]; struct drm_gem_object *obj = object_list[i];
struct drm_i915_gem_object *obj_priv = obj->driver_private; 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, i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv) 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) int i915_gem_init_object(struct drm_gem_object *obj)

View File

@ -1149,12 +1149,38 @@ void i915_driver_lastclose(struct drm_device * dev)
i915_dma_cleanup(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) void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
i915_mem_release(dev, file_priv, dev_priv->agp_heap); 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[] = { 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_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH),

View File

@ -301,6 +301,13 @@ typedef struct drm_i915_private {
} mm; } mm;
} drm_i915_private_t; } 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 { enum intel_chip_family {
CHIP_I8XX = 0x01, CHIP_I8XX = 0x01,
CHIP_I9XX = 0x02, 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_load(struct drm_device *, unsigned long flags);
extern int i915_driver_unload(struct drm_device *); extern int i915_driver_unload(struct drm_device *);
extern void i915_driver_lastclose(struct drm_device * dev); 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, extern void i915_driver_preclose(struct drm_device *dev,
struct drm_file *file_priv); 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 int i915_driver_device_is_agp(struct drm_device * dev);
extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg); unsigned long arg);