From: Ben Widawsky <ben@bwidawsk.net>
To: Chris Wilson <chris@chris-wilson.co.uk>
Cc: intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH 1/3] drm/i915: Introduce for_each_ring() macro
Date: Fri, 11 May 2012 12:46:23 -0700 [thread overview]
Message-ID: <20120511124623.30cc3b73@bwidawsk.net> (raw)
In-Reply-To: <1336742972-12713-1-git-send-email-chris@chris-wilson.co.uk>
On Fri, 11 May 2012 14:29:30 +0100
Chris Wilson <chris@chris-wilson.co.uk> wrote:
> In many places we wish to iterate over the rings associated with the
> GPU, so refactor them to use a common macro.
>
> Along the way, there are a few code removals that should be side-effect
> free and some rearrangement which should only have a cosmetic impact,
> such as error-state.
>
> v2: Pull in a couple of suggestions from Ben and Daniel for
> intel_ring_initialized() and not removing the warning (just moving them
> to a new home, closer to the error).
I would have liked the commit message update explaining the new behavior
of hangcheck_elapsed, and hangcheck_ring_idle just in case this ends up
the result of a bisection. I can live without it though.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Ben Widawsky <ben@bwidawsk.net>
> ---
> drivers/gpu/drm/i915/i915_debugfs.c | 9 ++--
> drivers/gpu/drm/i915/i915_drv.c | 10 ++---
> drivers/gpu/drm/i915/i915_drv.h | 9 ++--
> drivers/gpu/drm/i915/i915_gem.c | 39 ++++++++---------
> drivers/gpu/drm/i915/i915_gem_evict.c | 14 +++----
> drivers/gpu/drm/i915/i915_irq.c | 69 +++++++++++++------------------
> drivers/gpu/drm/i915/intel_pm.c | 5 ++-
> drivers/gpu/drm/i915/intel_ringbuffer.h | 6 +++
> 8 files changed, 76 insertions(+), 85 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 950f72a..eb2b3c2 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -699,6 +699,7 @@ static int i915_error_state(struct seq_file *m, void *unused)
> struct drm_device *dev = error_priv->dev;
> drm_i915_private_t *dev_priv = dev->dev_private;
> struct drm_i915_error_state *error = error_priv->error;
> + struct intel_ring_buffer *ring;
> int i, j, page, offset, elt;
>
> if (!error) {
> @@ -706,7 +707,6 @@ static int i915_error_state(struct seq_file *m, void *unused)
> return 0;
> }
>
> -
> seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
> error->time.tv_usec);
> seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
> @@ -722,11 +722,8 @@ static int i915_error_state(struct seq_file *m, void *unused)
> seq_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
> }
>
> - i915_ring_error_state(m, dev, error, RCS);
> - if (HAS_BLT(dev))
> - i915_ring_error_state(m, dev, error, BCS);
> - if (HAS_BSD(dev))
> - i915_ring_error_state(m, dev, error, VCS);
> + for_each_ring(ring, dev_priv, i)
> + i915_ring_error_state(m, dev, error, i);
>
> if (error->active_bo)
> print_error_buffers(m, "Active",
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 5898be9..3947804 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -893,15 +893,15 @@ int i915_reset(struct drm_device *dev)
> */
> if (drm_core_check_feature(dev, DRIVER_MODESET) ||
> !dev_priv->mm.suspended) {
> + struct intel_ring_buffer *ring;
> + int i;
> +
> dev_priv->mm.suspended = 0;
>
> i915_gem_init_swizzling(dev);
>
> - dev_priv->ring[RCS].init(&dev_priv->ring[RCS]);
> - if (HAS_BSD(dev))
> - dev_priv->ring[VCS].init(&dev_priv->ring[VCS]);
> - if (HAS_BLT(dev))
> - dev_priv->ring[BCS].init(&dev_priv->ring[BCS]);
> + for_each_ring(ring, dev_priv, i)
> + ring->init(ring);
>
> i915_gem_init_ppgtt(dev);
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 83a557c..11c7a6a 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -410,9 +410,7 @@ typedef struct drm_i915_private {
> #define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
> struct timer_list hangcheck_timer;
> int hangcheck_count;
> - uint32_t last_acthd;
> - uint32_t last_acthd_bsd;
> - uint32_t last_acthd_blt;
> + uint32_t last_acthd[I915_NUM_RINGS];
> uint32_t last_instdone;
> uint32_t last_instdone1;
>
> @@ -820,6 +818,11 @@ typedef struct drm_i915_private {
> struct drm_property *force_audio_property;
> } drm_i915_private_t;
>
> +/* Iterate over initialised rings */
> +#define for_each_ring(ring__, dev_priv__, i__) \
> + for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
> + if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
> +
> enum hdmi_force_audio {
> HDMI_AUDIO_OFF_DVI = -2, /* no aux data for HDMI-DVI converter */
> HDMI_AUDIO_OFF, /* force turn off HDMI audio */
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 44a5f24..6d2180c 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -1655,10 +1655,11 @@ void i915_gem_reset(struct drm_device *dev)
> {
> struct drm_i915_private *dev_priv = dev->dev_private;
> struct drm_i915_gem_object *obj;
> + struct intel_ring_buffer *ring;
> int i;
>
> - for (i = 0; i < I915_NUM_RINGS; i++)
> - i915_gem_reset_ring_lists(dev_priv, &dev_priv->ring[i]);
> + for_each_ring(ring, dev_priv, i)
> + i915_gem_reset_ring_lists(dev_priv, ring);
>
> /* Remove anything from the flushing lists. The GPU cache is likely
> * to be lost on reset along with the data, so simply move the
> @@ -1763,10 +1764,11 @@ void
> i915_gem_retire_requests(struct drm_device *dev)
> {
> drm_i915_private_t *dev_priv = dev->dev_private;
> + struct intel_ring_buffer *ring;
> int i;
>
> - for (i = 0; i < I915_NUM_RINGS; i++)
> - i915_gem_retire_requests_ring(&dev_priv->ring[i]);
> + for_each_ring(ring, dev_priv, i)
> + i915_gem_retire_requests_ring(ring);
> }
>
> static void
> @@ -1774,6 +1776,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
> {
> drm_i915_private_t *dev_priv;
> struct drm_device *dev;
> + struct intel_ring_buffer *ring;
> bool idle;
> int i;
>
> @@ -1793,9 +1796,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
> * objects indefinitely.
> */
> idle = true;
> - for (i = 0; i < I915_NUM_RINGS; i++) {
> - struct intel_ring_buffer *ring = &dev_priv->ring[i];
> -
> + for_each_ring(ring, dev_priv, i) {
> if (!list_empty(&ring->gpu_write_list)) {
> struct drm_i915_gem_request *request;
> int ret;
> @@ -2137,13 +2138,18 @@ static int i915_ring_idle(struct intel_ring_buffer *ring)
> int i915_gpu_idle(struct drm_device *dev)
> {
> drm_i915_private_t *dev_priv = dev->dev_private;
> + struct intel_ring_buffer *ring;
> int ret, i;
>
> /* Flush everything onto the inactive list. */
> - for (i = 0; i < I915_NUM_RINGS; i++) {
> - ret = i915_ring_idle(&dev_priv->ring[i]);
> + for_each_ring(ring, dev_priv, i) {
> + ret = i915_ring_idle(ring);
> if (ret)
> return ret;
> +
> + /* Is the device fubar? */
> + if (WARN_ON(!list_empty(&ring->gpu_write_list)))
> + return -EBUSY;
> }
>
> return 0;
> @@ -3463,9 +3469,7 @@ void i915_gem_init_ppgtt(struct drm_device *dev)
> /* GFX_MODE is per-ring on gen7+ */
> }
>
> - for (i = 0; i < I915_NUM_RINGS; i++) {
> - ring = &dev_priv->ring[i];
> -
> + for_each_ring(ring, dev_priv, i) {
> if (INTEL_INFO(dev)->gen >= 7)
> I915_WRITE(RING_MODE_GEN7(ring),
> _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
> @@ -3581,10 +3585,11 @@ void
> i915_gem_cleanup_ringbuffer(struct drm_device *dev)
> {
> drm_i915_private_t *dev_priv = dev->dev_private;
> + struct intel_ring_buffer *ring;
> int i;
>
> - for (i = 0; i < I915_NUM_RINGS; i++)
> - intel_cleanup_ring_buffer(&dev_priv->ring[i]);
> + for_each_ring(ring, dev_priv, i)
> + intel_cleanup_ring_buffer(ring);
> }
>
> int
> @@ -3592,7 +3597,7 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
> struct drm_file *file_priv)
> {
> drm_i915_private_t *dev_priv = dev->dev_private;
> - int ret, i;
> + int ret;
>
> if (drm_core_check_feature(dev, DRIVER_MODESET))
> return 0;
> @@ -3614,10 +3619,6 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
> BUG_ON(!list_empty(&dev_priv->mm.active_list));
> BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
> BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
> - for (i = 0; i < I915_NUM_RINGS; i++) {
> - BUG_ON(!list_empty(&dev_priv->ring[i].active_list));
> - BUG_ON(!list_empty(&dev_priv->ring[i].request_list));
> - }
> mutex_unlock(&dev->struct_mutex);
>
> ret = drm_irq_install(dev);
> diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
> index 3bcf045..ae7c24e 100644
> --- a/drivers/gpu/drm/i915/i915_gem_evict.c
> +++ b/drivers/gpu/drm/i915/i915_gem_evict.c
> @@ -168,7 +168,7 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
> drm_i915_private_t *dev_priv = dev->dev_private;
> struct drm_i915_gem_object *obj, *next;
> bool lists_empty;
> - int ret,i;
> + int ret;
>
> lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
> list_empty(&dev_priv->mm.flushing_list) &&
> @@ -178,17 +178,13 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
>
> trace_i915_gem_evict_everything(dev, purgeable_only);
>
> - ret = i915_gpu_idle(dev);
> - if (ret)
> - return ret;
> -
> /* The gpu_idle will flush everything in the write domain to the
> * active list. Then we must move everything off the active list
> * with retire requests.
> */
> - for (i = 0; i < I915_NUM_RINGS; i++)
> - if (WARN_ON(!list_empty(&dev_priv->ring[i].gpu_write_list)))
> - return -EBUSY;
> + ret = i915_gpu_idle(dev);
> + if (ret)
> + return ret;
>
> i915_gem_retire_requests(dev);
>
> @@ -203,5 +199,5 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
> }
> }
>
> - return ret;
> + return 0;
> }
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 2a062d7..cc4a633 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -1022,15 +1022,11 @@ static void i915_gem_record_rings(struct drm_device *dev,
> struct drm_i915_error_state *error)
> {
> struct drm_i915_private *dev_priv = dev->dev_private;
> + struct intel_ring_buffer *ring;
> struct drm_i915_gem_request *request;
> int i, count;
>
> - for (i = 0; i < I915_NUM_RINGS; i++) {
> - struct intel_ring_buffer *ring = &dev_priv->ring[i];
> -
> - if (ring->obj == NULL)
> - continue;
> -
> + for_each_ring(ring, dev_priv, i) {
> i915_record_ring_state(dev, error, ring);
>
> error->ring[i].batchbuffer =
> @@ -1295,6 +1291,8 @@ static void i915_report_and_clear_eir(struct drm_device *dev)
> void i915_handle_error(struct drm_device *dev, bool wedged)
> {
> struct drm_i915_private *dev_priv = dev->dev_private;
> + struct intel_ring_buffer *ring;
> + int i;
>
> i915_capture_error_state(dev);
> i915_report_and_clear_eir(dev);
> @@ -1306,11 +1304,8 @@ void i915_handle_error(struct drm_device *dev, bool wedged)
> /*
> * Wakeup waiting processes so they don't hang
> */
> - wake_up_all(&dev_priv->ring[RCS].irq_queue);
> - if (HAS_BSD(dev))
> - wake_up_all(&dev_priv->ring[VCS].irq_queue);
> - if (HAS_BLT(dev))
> - wake_up_all(&dev_priv->ring[BCS].irq_queue);
> + for_each_ring(ring, dev_priv, i)
> + wake_up_all(&ring->irq_queue);
> }
>
> queue_work(dev_priv->wq, &dev_priv->error_work);
> @@ -1515,11 +1510,6 @@ ring_last_seqno(struct intel_ring_buffer *ring)
>
> static bool i915_hangcheck_ring_idle(struct intel_ring_buffer *ring, bool *err)
> {
> - /* We don't check whether the ring even exists before calling this
> - * function. Hence check whether it's initialized. */
> - if (ring->obj == NULL)
> - return true;
> -
> if (list_empty(&ring->request_list) ||
> i915_seqno_passed(ring->get_seqno(ring), ring_last_seqno(ring))) {
> /* Issue a wake-up to catch stuck h/w. */
> @@ -1553,26 +1543,25 @@ static bool i915_hangcheck_hung(struct drm_device *dev)
> drm_i915_private_t *dev_priv = dev->dev_private;
>
> if (dev_priv->hangcheck_count++ > 1) {
> + bool hung = true;
> +
> DRM_ERROR("Hangcheck timer elapsed... GPU hung\n");
> i915_handle_error(dev, true);
>
> if (!IS_GEN2(dev)) {
> + struct intel_ring_buffer *ring;
> + int i;
> +
> /* Is the chip hanging on a WAIT_FOR_EVENT?
> * If so we can simply poke the RB_WAIT bit
> * and break the hang. This should work on
> * all but the second generation chipsets.
> */
> - if (kick_ring(&dev_priv->ring[RCS]))
> - return false;
> -
> - if (HAS_BSD(dev) && kick_ring(&dev_priv->ring[VCS]))
> - return false;
> -
> - if (HAS_BLT(dev) && kick_ring(&dev_priv->ring[BCS]))
> - return false;
> + for_each_ring(ring, dev_priv, i)
> + hung &= !kick_ring(ring);
> }
>
> - return true;
> + return hung;
> }
>
> return false;
> @@ -1588,16 +1577,23 @@ void i915_hangcheck_elapsed(unsigned long data)
> {
> struct drm_device *dev = (struct drm_device *)data;
> drm_i915_private_t *dev_priv = dev->dev_private;
> - uint32_t acthd, instdone, instdone1, acthd_bsd, acthd_blt;
> - bool err = false;
> + uint32_t acthd[I915_NUM_RINGS], instdone, instdone1;
> + struct intel_ring_buffer *ring;
> + bool err = false, idle;
> + int i;
>
> if (!i915_enable_hangcheck)
> return;
>
> + memset(acthd, 0, sizeof(acthd));
> + idle = true;
> + for_each_ring(ring, dev_priv, i) {
> + idle &= i915_hangcheck_ring_idle(ring, &err);
> + acthd[i] = intel_ring_get_active_head(ring);
> + }
> +
> /* If all work is done then ACTHD clearly hasn't advanced. */
> - if (i915_hangcheck_ring_idle(&dev_priv->ring[RCS], &err) &&
> - i915_hangcheck_ring_idle(&dev_priv->ring[VCS], &err) &&
> - i915_hangcheck_ring_idle(&dev_priv->ring[BCS], &err)) {
> + if (idle) {
> if (err) {
> if (i915_hangcheck_hung(dev))
> return;
> @@ -1616,15 +1612,8 @@ void i915_hangcheck_elapsed(unsigned long data)
> instdone = I915_READ(INSTDONE_I965);
> instdone1 = I915_READ(INSTDONE1);
> }
> - acthd = intel_ring_get_active_head(&dev_priv->ring[RCS]);
> - acthd_bsd = HAS_BSD(dev) ?
> - intel_ring_get_active_head(&dev_priv->ring[VCS]) : 0;
> - acthd_blt = HAS_BLT(dev) ?
> - intel_ring_get_active_head(&dev_priv->ring[BCS]) : 0;
>
> - if (dev_priv->last_acthd == acthd &&
> - dev_priv->last_acthd_bsd == acthd_bsd &&
> - dev_priv->last_acthd_blt == acthd_blt &&
> + if (memcmp(dev_priv->last_acthd, acthd, sizeof(acthd)) == 0 &&
> dev_priv->last_instdone == instdone &&
> dev_priv->last_instdone1 == instdone1) {
> if (i915_hangcheck_hung(dev))
> @@ -1632,9 +1621,7 @@ void i915_hangcheck_elapsed(unsigned long data)
> } else {
> dev_priv->hangcheck_count = 0;
>
> - dev_priv->last_acthd = acthd;
> - dev_priv->last_acthd_bsd = acthd_bsd;
> - dev_priv->last_acthd_blt = acthd_blt;
> + memcpy(dev_priv->last_acthd, acthd, sizeof(acthd));
> dev_priv->last_instdone = instdone;
> dev_priv->last_instdone1 = instdone1;
> }
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 8f8d1da..8e79ff6 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2326,6 +2326,7 @@ int intel_enable_rc6(const struct drm_device *dev)
>
> void gen6_enable_rps(struct drm_i915_private *dev_priv)
> {
> + struct intel_ring_buffer *ring;
> u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
> u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
> u32 pcu_mbox, rc6_mask = 0;
> @@ -2360,8 +2361,8 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
> I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
> I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
>
> - for (i = 0; i < I915_NUM_RINGS; i++)
> - I915_WRITE(RING_MAX_IDLE(dev_priv->ring[i].mmio_base), 10);
> + for_each_ring(ring, dev_priv, i)
> + I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
>
> I915_WRITE(GEN6_RC_SLEEP, 0);
> I915_WRITE(GEN6_RC1e_THRESHOLD, 1000);
> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
> index baba757..55d3da2 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.h
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
> @@ -119,6 +119,12 @@ struct intel_ring_buffer {
> void *private;
> };
>
> +static inline bool
> +intel_ring_initialized(struct intel_ring_buffer *ring)
> +{
> + return ring->obj != NULL;
> +}
> +
> static inline unsigned
> intel_ring_flag(struct intel_ring_buffer *ring)
> {
--
Ben Widawsky, Intel Open Source Technology Center
next prev parent reply other threads:[~2012-05-11 19:46 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-05-11 13:29 [PATCH 1/3] drm/i915: Introduce for_each_ring() macro Chris Wilson
2012-05-11 13:29 ` [PATCH 2/3] drm/i915: Check whether the ring is initialised prior to dispatch Chris Wilson
2012-05-11 19:53 ` Ben Widawsky
2012-05-11 13:29 ` [PATCH 3/3] drm/i915: Replace the feature tests for BLT/BSD with ring init checks Chris Wilson
2012-05-11 19:58 ` Ben Widawsky
2012-05-11 20:24 ` Chris Wilson
2012-05-11 19:46 ` Ben Widawsky [this message]
2012-05-13 13:35 ` [PATCH 1/3] drm/i915: Introduce for_each_ring() macro Daniel Vetter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120511124623.30cc3b73@bwidawsk.net \
--to=ben@bwidawsk.net \
--cc=chris@chris-wilson.co.uk \
--cc=intel-gfx@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.