mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-01-01 11:50:24 +01:00
[intel-gem] Use timers to retire requests periodically.
Without the user IRQ running constantly, there's no wakeup when the ring empties to go retire requests and free buffers. Use a 1 second timer to make that happen more often.
This commit is contained in:
parent
a708106c77
commit
9f46c6935d
4 changed files with 47 additions and 0 deletions
|
|
@ -124,6 +124,7 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
|
|||
|
||||
setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
|
||||
(unsigned long)dev);
|
||||
init_timer_deferrable(&dev->vblank_disable_timer);
|
||||
spin_lock_init(&dev->vbl_lock);
|
||||
atomic_set(&dev->vbl_signal_pending, 0);
|
||||
dev->num_crtcs = num_crtcs;
|
||||
|
|
|
|||
|
|
@ -162,6 +162,9 @@ i915_add_request(struct drm_device *dev, uint32_t flush_domains)
|
|||
request->seqno = seqno;
|
||||
request->emitted_jiffies = jiffies;
|
||||
request->flush_domains = flush_domains;
|
||||
if (list_empty(&dev_priv->mm.request_list))
|
||||
mod_timer(&dev_priv->mm.retire_timer, jiffies + HZ);
|
||||
|
||||
list_add_tail(&request->list, &dev_priv->mm.request_list);
|
||||
|
||||
return seqno;
|
||||
|
|
@ -300,6 +303,32 @@ i915_gem_retire_requests(struct drm_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
i915_gem_retire_timeout(unsigned long data)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *) data;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
schedule_work(&dev_priv->mm.retire_task);
|
||||
}
|
||||
|
||||
void
|
||||
i915_gem_retire_handler(struct work_struct *work)
|
||||
{
|
||||
drm_i915_private_t *dev_priv;
|
||||
struct drm_device *dev;
|
||||
|
||||
dev_priv = container_of(work, drm_i915_private_t,
|
||||
mm.retire_task);
|
||||
dev = dev_priv->dev;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
i915_gem_retire_requests(dev);
|
||||
if (!list_empty(&dev_priv->mm.request_list))
|
||||
mod_timer(&dev_priv->mm.retire_timer, jiffies + HZ);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a sequence number to be signaled, and cleans up the
|
||||
* request and object lists appropriately for that event.
|
||||
|
|
|
|||
|
|
@ -1078,6 +1078,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
|
||||
INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
|
||||
INIT_LIST_HEAD(&dev_priv->mm.request_list);
|
||||
dev_priv->mm.retire_timer.function = i915_gem_retire_timeout;
|
||||
dev_priv->mm.retire_timer.data = (unsigned long) dev;
|
||||
init_timer_deferrable (&dev_priv->mm.retire_timer);
|
||||
INIT_WORK(&dev_priv->mm.retire_task,
|
||||
i915_gem_retire_handler);
|
||||
INIT_WORK(&dev_priv->user_interrupt_task,
|
||||
i915_user_interrupt_handler);
|
||||
dev_priv->mm.next_gem_seqno = 1;
|
||||
|
|
|
|||
|
|
@ -280,6 +280,16 @@ typedef struct drm_i915_private {
|
|||
*/
|
||||
struct list_head request_list;
|
||||
|
||||
/**
|
||||
* We leave the user IRQ off as much as possible,
|
||||
* but this means that requests will finish and never
|
||||
* be retired once the system goes idle. Set a timer to
|
||||
* fire periodically while the ring is running. When it
|
||||
* fires, go retire requests.
|
||||
*/
|
||||
struct timer_list retire_timer;
|
||||
struct work_struct retire_task;
|
||||
|
||||
uint32_t next_gem_seqno;
|
||||
} mm;
|
||||
|
||||
|
|
@ -463,6 +473,8 @@ int i915_gem_flush_pwrite(struct drm_gem_object *obj,
|
|||
uint64_t offset, uint64_t size);
|
||||
void i915_gem_lastclose(struct drm_device *dev);
|
||||
void i915_gem_retire_requests(struct drm_device *dev);
|
||||
void i915_gem_retire_timeout(unsigned long data);
|
||||
void i915_gem_retire_handler(struct work_struct *work);
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue