From mboxrd@z Thu Jan 1 00:00:00 1970 From: =?UTF-8?B?Q2hyaXN0aWFuIEvDtm5pZw==?= Subject: Re: [PATCH] drm/radeon: signal all fences after lockup to avoid endless waiting in GEM_WAIT Date: Tue, 08 Oct 2013 18:21:37 +0200 Message-ID: <52543111.9000405@vodafone.de> References: <5252961D.8010502@vodafone.de> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------060809080803030604050801" Return-path: Received: from smtp-03.vodafone.de (mxout.vodafone.de [80.84.1.40]) by gabe.freedesktop.org (Postfix) with ESMTP id EB9EAE6624 for ; Tue, 8 Oct 2013 09:21:43 -0700 (PDT) In-Reply-To: <5252961D.8010502@vodafone.de> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org Errors-To: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org To: =?UTF-8?B?TWFyZWsgT2zFocOhaw==?= Cc: dri-devel@lists.freedesktop.org List-Id: dri-devel@lists.freedesktop.org This is a multi-part message in MIME format. --------------060809080803030604050801 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable Hi Marek, please try the attached patch as a replacement for your signaling all=20 fences patch. I'm not 100% sure if it fixes all issues, but it's at=20 least a start. Thanks, Christian. Am 07.10.2013 13:08, schrieb Christian K=C3=B6nig: >> First of all, I can't complain about the reliability of the hardware >> GPU reset. It's mostly the kernel driver that happens to run into a >> deadlock at the same time. > > Alex and I spend quite some time on making this reliable again after=20 > activating more rings and adding VM support. The main problem is that=20 > I couldn't figure out where the CPU deadlock comes from, cause I=20 > couldn't reliable reproduce the issue. > > What is the content of /proc//task/*/stack and=20 > sys/kernel/debug/dri/0/radeon_fence_info when the X server is stuck in=20 > the deadlock situation? > > I'm pretty sure that we nearly always have a problem when two threads=20 > are waiting for fences on one of them detects that we have a lockup=20 > while the other one keeps holding the exclusive lock. Signaling all=20 > fences might work around that problem, but it probably would be better=20 > to fix the underlying issue. > > Going to take a deeper look into it. > > Christian. > > Am 03.10.2013 02:45, schrieb Marek Ol=C5=A1=C3=A1k: >> First of all, I can't complain about the reliability of the hardware >> GPU reset. It's mostly the kernel driver that happens to run into a >> deadlock at the same time. >> >> Regarding the issue with fences, the problem is that the GPU reset >> completes successfully according to dmesg, but X doesn't respond. I >> can move the cursor on the screen, but I can't do anything else and >> the UI is frozen. gdb says that X is stuck in GEM_WAIT_IDLE. I can >> easily reproduce this, because it's the most common reason why a GPU >> lockup leads to frozen X. The GPU actually recovers, but X is hung. I >> can't tell whether the fences are just not signalled or whether there >> is actually a real CPU deadlock I can't see. >> >> This patch makes the problem go away and GPU resets are successful >> (except for extreme cases, see below). With a small enough lockup >> timeout, the lockups are just a minor annoyance and I thought I could >> get through a piglit run just with a few tens or hundreds of GPU >> resets... >> >> A different type of deadlock showed up, though it needs a lot of >> concurrently-running apps like piglit. What happened is that the >> kernel driver was stuck/deadlocked in radeon_cs_ioctl presumably due >> to a GPU hang while holding onto the exclusive lock, and another >> thread wanting to do the GPU reset was unable to acquire the lock. >> >> That said, I will use the patch locally, because it helps a lot. I got >> a few lockups while writing this email and I'm glad I didn't have to >> reboot. >> >> Marek >> >> On Wed, Oct 2, 2013 at 4:50 PM, Christian K=C3=B6nig=20 >> wrote: >>> Possible, but I would rather guess that this doesn't work because=20 >>> the IB test runs into a deadlock situation and so the GPU reset=20 >>> never fully completes. >>> >>> Can you reproduce the problem? >>> >>> If you want to make GPU resets more reliable I would rather suggest=20 >>> to remove the ring lock dependency. >>> Then we should try to give all the fence wait functions a (reliable)=20 >>> timeout and move reset handling a layer up into the ioctl functions.=20 >>> But for this you need to rip out the old PM code first. >>> >>> Christian. >>> >>> Marek Ol=C5=A1=C3=A1k schrieb: >>> >>>> I'm afraid signalling the fences with an IB test is not reliable. >>>> >>>> Marek >>>> >>>> On Wed, Oct 2, 2013 at 3:52 PM, Christian K=C3=B6nig=20 >>>> wrote: >>>>> NAK, after recovering from a lockup the first thing we do is=20 >>>>> signalling all remaining fences with an IB test. >>>>> >>>>> If we don't recover we indeed signal all fences manually. >>>>> >>>>> Signalling all fences regardless of the outcome of the reset=20 >>>>> creates problems with both types of partial resets. >>>>> >>>>> Christian. >>>>> >>>>> Marek Ol=C5=A1=C3=A1k schrieb: >>>>> >>>>>> From: Marek Ol=C5=A1=C3=A1k >>>>>> >>>>>> After a lockup, fences are not signalled sometimes, causing >>>>>> the GEM_WAIT_IDLE ioctl to never return, which sometimes results >>>>>> in an X server freeze. >>>>>> >>>>>> This fixes only one of many deadlocks which can occur during a=20 >>>>>> lockup. >>>>>> >>>>>> Signed-off-by: Marek Ol=C5=A1=C3=A1k >>>>>> --- >>>>>> drivers/gpu/drm/radeon/radeon_device.c | 5 +++++ >>>>>> 1 file changed, 5 insertions(+) >>>>>> >>>>>> diff --git a/drivers/gpu/drm/radeon/radeon_device.c=20 >>>>>> b/drivers/gpu/drm/radeon/radeon_device.c >>>>>> index 841d0e0..7b97baa 100644 >>>>>> --- a/drivers/gpu/drm/radeon/radeon_device.c >>>>>> +++ b/drivers/gpu/drm/radeon/radeon_device.c >>>>>> @@ -1552,6 +1552,11 @@ int radeon_gpu_reset(struct radeon_device=20 >>>>>> *rdev) >>>>>> radeon_save_bios_scratch_regs(rdev); >>>>>> /* block TTM */ >>>>>> resched =3D ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev)= ; >>>>>> + >>>>>> + mutex_lock(&rdev->ring_lock); >>>>>> + radeon_fence_driver_force_completion(rdev); >>>>>> + mutex_unlock(&rdev->ring_lock); >>>>>> + >>>>>> radeon_pm_suspend(rdev); >>>>>> radeon_suspend(rdev); >>>>>> >>>>>> --=20 >>>>>> 1.8.1.2 >>>>>> >>>>>> _______________________________________________ >>>>>> dri-devel mailing list >>>>>> dri-devel@lists.freedesktop.org >>>>>> http://lists.freedesktop.org/mailman/listinfo/dri-devel > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel --------------060809080803030604050801 Content-Type: text/x-diff; name="0001-drm-radeon-rework-and-fix-reset-detection.patch" Content-Disposition: attachment; filename="0001-drm-radeon-rework-and-fix-reset-detection.patch" Content-Transfer-Encoding: quoted-printable >>From b2a36ace270eb5649743f42f3c559cfdff7f41a2 Mon Sep 17 00:00:00 2001 From: =3D?UTF-8?q?Christian=3D20K=3DC3=3DB6nig?=3D Date: Tue, 8 Oct 2013 18:02:38 +0200 Subject: [PATCH] drm/radeon: rework and fix reset detection MIME-Version: 1.0 Content-Type: text/plain; charset=3DUTF-8 Content-Transfer-Encoding: 8bit Stop fiddling with jiffies, always wait for RADEON_FENCE_JIFFIES_TIMEOUT. Consolidate the two wait sequence implementations into just one function. Activate all waiters and remember if the reset was already done instead o= f trying to reset from only one thread. Signed-off-by: Christian K=C3=B6nig --- drivers/gpu/drm/radeon/radeon.h | 2 +- drivers/gpu/drm/radeon/radeon_device.c | 7 + drivers/gpu/drm/radeon/radeon_fence.c | 347 +++++++++++----------------= ------ 3 files changed, 126 insertions(+), 230 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/rad= eon.h index a400ac1..0201c6e 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -327,7 +327,6 @@ struct radeon_fence_driver { /* sync_seq is protected by ring emission lock */ uint64_t sync_seq[RADEON_NUM_RINGS]; atomic64_t last_seq; - unsigned long last_activity; bool initialized; }; =20 @@ -2170,6 +2169,7 @@ struct radeon_device { bool need_dma32; bool accel_working; bool fastfb_working; /* IGP feature*/ + bool needs_reset; struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES]; const struct firmware *me_fw; /* all family ME firmware */ const struct firmware *pfp_fw; /* r6/700 PFP firmware */ diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/rad= eon/radeon_device.c index 841d0e0..0eb9365 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1549,6 +1549,12 @@ int radeon_gpu_reset(struct radeon_device *rdev) int resched; =20 down_write(&rdev->exclusive_lock); + + if (!rdev->needs_reset) { + up_write(&rdev->exclusive_lock); + return 0; + } + radeon_save_bios_scratch_regs(rdev); /* block TTM */ resched =3D ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); @@ -1607,6 +1613,7 @@ retry: dev_info(rdev->dev, "GPU reset failed\n"); } =20 + rdev->needs_reset =3D false; up_write(&rdev->exclusive_lock); return r; } diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/rade= on/radeon_fence.c index ddb8f8e..b8f68b2 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -190,10 +190,8 @@ void radeon_fence_process(struct radeon_device *rdev= , int ring) } } while (atomic64_xchg(&rdev->fence_drv[ring].last_seq, seq) > seq); =20 - if (wake) { - rdev->fence_drv[ring].last_activity =3D jiffies; + if (wake) wake_up_all(&rdev->fence_queue); - } } =20 /** @@ -212,13 +210,13 @@ static void radeon_fence_destroy(struct kref *kref) } =20 /** - * radeon_fence_seq_signaled - check if a fence sequeuce number has sign= aled + * radeon_fence_seq_signaled - check if a fence sequence number has sign= aled * * @rdev: radeon device pointer * @seq: sequence number * @ring: ring index the fence is associated with * - * Check if the last singled fence sequnce number is >=3D the requested + * Check if the last signaled fence sequnce number is >=3D the requested * sequence number (all asics). * Returns true if the fence has signaled (current fence value * is >=3D requested value) or false if it has not (current fence @@ -263,113 +261,131 @@ bool radeon_fence_signaled(struct radeon_fence *f= ence) } =20 /** - * radeon_fence_wait_seq - wait for a specific sequence number + * radeon_fence_any_seq_signaled - check if any sequence number is signa= led * * @rdev: radeon device pointer - * @target_seq: sequence number we want to wait for - * @ring: ring index the fence is associated with + * @seq: sequence numbers + * + * Check if the last signaled fence sequnce number is >=3D the requested + * sequence number (all asics). + * Returns true if any has signaled (current value is >=3D requested val= ue) + * or false if it has not. Helper function for radeon_fence_wait_seq. + */ +static bool radeon_fence_any_seq_signaled(struct radeon_device *rdev, u6= 4 *seq) +{ + unsigned i; + + for (i =3D 0; i < RADEON_NUM_RINGS; ++i) { + if (seq[i] && radeon_fence_seq_signaled(rdev, seq[i], i)) + return true; + } + return false; +} + +/** + * radeon_fence_wait_seq - wait for a specific sequence numbers + * + * @rdev: radeon device pointer + * @target_seq: sequence number(s) we want to wait for * @intr: use interruptable sleep * @lock_ring: whether the ring should be locked or not * - * Wait for the requested sequence number to be written (all asics). + * Wait for the requested sequence number(s) to be written by any ring + * (all asics). Sequnce number array is indexed by ring id. * @intr selects whether to use interruptable (true) or non-interruptabl= e * (false) sleep when waiting for the sequence number. Helper function - * for radeon_fence_wait(), et al. + * for radeon_fence_wait_*(). * Returns 0 if the sequence number has passed, error for all other case= s. - * -EDEADLK is returned when a GPU lockup has been detected and the ring= is - * marked as not ready so no further jobs get scheduled until a successf= ul - * reset. + * -EDEADLK is returned when a GPU lockup has been detected. */ -static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_= seq, - unsigned ring, bool intr, bool lock_ring) +static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 *target= _seq, + bool intr, bool lock_ring) { - unsigned long timeout, last_activity; - uint64_t seq; - unsigned i; + uint64_t last_seq[RADEON_NUM_RINGS]; bool signaled; - int r; + int i, r; + + while (!radeon_fence_any_seq_signaled(rdev, target_seq)) { + + /* Save current sequence values, used to check for GPU lockups */ + for (i =3D 0; i < RADEON_NUM_RINGS; ++i) { + if (!target_seq[i]) + continue; =20 - while (target_seq > atomic64_read(&rdev->fence_drv[ring].last_seq)) { - if (!rdev->ring[ring].ready) { - return -EBUSY; + last_seq[i] =3D atomic64_read(&rdev->fence_drv[i].last_seq); + trace_radeon_fence_wait_begin(rdev->ddev, target_seq[i]); + radeon_irq_kms_sw_irq_get(rdev, i); } =20 - timeout =3D jiffies - RADEON_FENCE_JIFFIES_TIMEOUT; - if (time_after(rdev->fence_drv[ring].last_activity, timeout)) { - /* the normal case, timeout is somewhere before last_activity */ - timeout =3D rdev->fence_drv[ring].last_activity - timeout; + if (intr) { + r =3D wait_event_interruptible_timeout(rdev->fence_queue, ( + (signaled =3D radeon_fence_any_seq_signaled(rdev, target_seq)) + || rdev->needs_reset), RADEON_FENCE_JIFFIES_TIMEOUT); } else { - /* either jiffies wrapped around, or no fence was signaled in the las= t 500ms - * anyway we will just wait for the minimum amount and then check for= a lockup - */ - timeout =3D 1; + r =3D wait_event_timeout(rdev->fence_queue, ( + (signaled =3D radeon_fence_any_seq_signaled(rdev, target_seq)) + || rdev->needs_reset), RADEON_FENCE_JIFFIES_TIMEOUT); } - seq =3D atomic64_read(&rdev->fence_drv[ring].last_seq); - /* Save current last activity valuee, used to check for GPU lockups */ - last_activity =3D rdev->fence_drv[ring].last_activity; =20 - trace_radeon_fence_wait_begin(rdev->ddev, seq); - radeon_irq_kms_sw_irq_get(rdev, ring); - if (intr) { - r =3D wait_event_interruptible_timeout(rdev->fence_queue, - (signaled =3D radeon_fence_seq_signaled(rdev, target_seq, ring)), - timeout); - } else { - r =3D wait_event_timeout(rdev->fence_queue, - (signaled =3D radeon_fence_seq_signaled(rdev, target_seq, ring)), - timeout); + for (i =3D 0; i < RADEON_NUM_RINGS; ++i) { + if (!target_seq[i]) + continue; + + radeon_irq_kms_sw_irq_put(rdev, i); + trace_radeon_fence_wait_end(rdev->ddev, target_seq[i]); } - radeon_irq_kms_sw_irq_put(rdev, ring); - if (unlikely(r < 0)) { + + if (unlikely(r < 0)) return r; - } - trace_radeon_fence_wait_end(rdev->ddev, seq); =20 if (unlikely(!signaled)) { + if (rdev->needs_reset) + return -EDEADLK; + /* we were interrupted for some reason and fence * isn't signaled yet, resume waiting */ - if (r) { + if (r) continue; + + for (i =3D 0; i < RADEON_NUM_RINGS; ++i) { + if (!target_seq[i]) + continue; + + if (last_seq[i] !=3D atomic64_read(&rdev->fence_drv[i].last_seq)) + break; } =20 - /* check if sequence value has changed since last_activity */ - if (seq !=3D atomic64_read(&rdev->fence_drv[ring].last_seq)) { + if (i !=3D RADEON_NUM_RINGS) continue; - } =20 - if (lock_ring) { + if (lock_ring) mutex_lock(&rdev->ring_lock); - } =20 - /* test if somebody else has already decided that this is a lockup */ - if (last_activity !=3D rdev->fence_drv[ring].last_activity) { - if (lock_ring) { - mutex_unlock(&rdev->ring_lock); - } - continue; + for (i =3D 0; i < RADEON_NUM_RINGS; ++i) { + if (!target_seq[i]) + continue; + + if (radeon_ring_is_lockup(rdev, i, &rdev->ring[i])) + break; } =20 - if (radeon_ring_is_lockup(rdev, ring, &rdev->ring[ring])) { + if (i < RADEON_NUM_RINGS) { /* good news we believe it's a lockup */ - dev_warn(rdev->dev, "GPU lockup (waiting for 0x%016llx last fence id= 0x%016llx)\n", - target_seq, seq); - - /* change last activity so nobody else think there is a lockup */ - for (i =3D 0; i < RADEON_NUM_RINGS; ++i) { - rdev->fence_drv[i].last_activity =3D jiffies; - } - - /* mark the ring as not ready any more */ - rdev->ring[ring].ready =3D false; - if (lock_ring) { + dev_warn(rdev->dev, "GPU lockup (waiting for " + "0x%016llx last fence id 0x%016llx on" + " ring %d)\n", + target_seq[i], last_seq[i], i); + + /* remember that we need an reset */ + rdev->needs_reset =3D true; + if (lock_ring) mutex_unlock(&rdev->ring_lock); - } + wake_up_all(&rdev->fence_queue); return -EDEADLK; } =20 - if (lock_ring) { + if (lock_ring) mutex_unlock(&rdev->ring_lock); - } } } return 0; @@ -388,6 +404,7 @@ static int radeon_fence_wait_seq(struct radeon_device= *rdev, u64 target_seq, */ int radeon_fence_wait(struct radeon_fence *fence, bool intr) { + uint64_t seq[RADEON_NUM_RINGS] =3D {}; int r; =20 if (fence =3D=3D NULL) { @@ -395,147 +412,15 @@ int radeon_fence_wait(struct radeon_fence *fence, = bool intr) return -EINVAL; } =20 - r =3D radeon_fence_wait_seq(fence->rdev, fence->seq, - fence->ring, intr, true); - if (r) { - return r; - } - fence->seq =3D RADEON_FENCE_SIGNALED_SEQ; - return 0; -} - -static bool radeon_fence_any_seq_signaled(struct radeon_device *rdev, u6= 4 *seq) -{ - unsigned i; - - for (i =3D 0; i < RADEON_NUM_RINGS; ++i) { - if (seq[i] && radeon_fence_seq_signaled(rdev, seq[i], i)) { - return true; - } - } - return false; -} - -/** - * radeon_fence_wait_any_seq - wait for a sequence number on any ring - * - * @rdev: radeon device pointer - * @target_seq: sequence number(s) we want to wait for - * @intr: use interruptable sleep - * - * Wait for the requested sequence number(s) to be written by any ring - * (all asics). Sequnce number array is indexed by ring id. - * @intr selects whether to use interruptable (true) or non-interruptabl= e - * (false) sleep when waiting for the sequence number. Helper function - * for radeon_fence_wait_any(), et al. - * Returns 0 if the sequence number has passed, error for all other case= s. - */ -static int radeon_fence_wait_any_seq(struct radeon_device *rdev, - u64 *target_seq, bool intr) -{ - unsigned long timeout, last_activity, tmp; - unsigned i, ring =3D RADEON_NUM_RINGS; - bool signaled; - int r; - - for (i =3D 0, last_activity =3D 0; i < RADEON_NUM_RINGS; ++i) { - if (!target_seq[i]) { - continue; - } - - /* use the most recent one as indicator */ - if (time_after(rdev->fence_drv[i].last_activity, last_activity)) { - last_activity =3D rdev->fence_drv[i].last_activity; - } - - /* For lockup detection just pick the lowest ring we are - * actively waiting for - */ - if (i < ring) { - ring =3D i; - } - } - - /* nothing to wait for ? */ - if (ring =3D=3D RADEON_NUM_RINGS) { - return -ENOENT; - } - - while (!radeon_fence_any_seq_signaled(rdev, target_seq)) { - timeout =3D jiffies - RADEON_FENCE_JIFFIES_TIMEOUT; - if (time_after(last_activity, timeout)) { - /* the normal case, timeout is somewhere before last_activity */ - timeout =3D last_activity - timeout; - } else { - /* either jiffies wrapped around, or no fence was signaled in the las= t 500ms - * anyway we will just wait for the minimum amount and then check for= a lockup - */ - timeout =3D 1; - } + seq[fence->ring] =3D fence->seq; + if (seq[fence->ring] =3D=3D RADEON_FENCE_SIGNALED_SEQ) + return 0; =20 - trace_radeon_fence_wait_begin(rdev->ddev, target_seq[ring]); - for (i =3D 0; i < RADEON_NUM_RINGS; ++i) { - if (target_seq[i]) { - radeon_irq_kms_sw_irq_get(rdev, i); - } - } - if (intr) { - r =3D wait_event_interruptible_timeout(rdev->fence_queue, - (signaled =3D radeon_fence_any_seq_signaled(rdev, target_seq)), - timeout); - } else { - r =3D wait_event_timeout(rdev->fence_queue, - (signaled =3D radeon_fence_any_seq_signaled(rdev, target_seq)), - timeout); - } - for (i =3D 0; i < RADEON_NUM_RINGS; ++i) { - if (target_seq[i]) { - radeon_irq_kms_sw_irq_put(rdev, i); - } - } - if (unlikely(r < 0)) { - return r; - } - trace_radeon_fence_wait_end(rdev->ddev, target_seq[ring]); - - if (unlikely(!signaled)) { - /* we were interrupted for some reason and fence - * isn't signaled yet, resume waiting */ - if (r) { - continue; - } - - mutex_lock(&rdev->ring_lock); - for (i =3D 0, tmp =3D 0; i < RADEON_NUM_RINGS; ++i) { - if (time_after(rdev->fence_drv[i].last_activity, tmp)) { - tmp =3D rdev->fence_drv[i].last_activity; - } - } - /* test if somebody else has already decided that this is a lockup */ - if (last_activity !=3D tmp) { - last_activity =3D tmp; - mutex_unlock(&rdev->ring_lock); - continue; - } - - if (radeon_ring_is_lockup(rdev, ring, &rdev->ring[ring])) { - /* good news we believe it's a lockup */ - dev_warn(rdev->dev, "GPU lockup (waiting for 0x%016llx)\n", - target_seq[ring]); - - /* change last activity so nobody else think there is a lockup */ - for (i =3D 0; i < RADEON_NUM_RINGS; ++i) { - rdev->fence_drv[i].last_activity =3D jiffies; - } + r =3D radeon_fence_wait_seq(fence->rdev, seq, intr, true); + if (r) + return r; =20 - /* mark the ring as not ready any more */ - rdev->ring[ring].ready =3D false; - mutex_unlock(&rdev->ring_lock); - return -EDEADLK; - } - mutex_unlock(&rdev->ring_lock); - } - } + fence->seq =3D RADEON_FENCE_SIGNALED_SEQ; return 0; } =20 @@ -557,7 +442,7 @@ int radeon_fence_wait_any(struct radeon_device *rdev, bool intr) { uint64_t seq[RADEON_NUM_RINGS]; - unsigned i; + unsigned i, num_rings =3D 0; int r; =20 for (i =3D 0; i < RADEON_NUM_RINGS; ++i) { @@ -567,15 +452,19 @@ int radeon_fence_wait_any(struct radeon_device *rde= v, continue; } =20 - if (fences[i]->seq =3D=3D RADEON_FENCE_SIGNALED_SEQ) { - /* something was allready signaled */ - return 0; - } - seq[i] =3D fences[i]->seq; + ++num_rings; + + /* test if something was allready signaled */ + if (seq[i] =3D=3D RADEON_FENCE_SIGNALED_SEQ) + return 0; } =20 - r =3D radeon_fence_wait_any_seq(rdev, seq, intr); + /* nothing to wait for ? */ + if (num_rings =3D=3D 0) + return -ENOENT; + + r =3D radeon_fence_wait_seq(rdev, seq, intr, true); if (r) { return r; } @@ -594,15 +483,15 @@ int radeon_fence_wait_any(struct radeon_device *rde= v, */ int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring) { - uint64_t seq; + uint64_t seq[RADEON_NUM_RINGS] =3D {}; =20 - seq =3D atomic64_read(&rdev->fence_drv[ring].last_seq) + 1ULL; - if (seq >=3D rdev->fence_drv[ring].sync_seq[ring]) { + seq[ring] =3D atomic64_read(&rdev->fence_drv[ring].last_seq) + 1ULL; + if (seq[ring] >=3D rdev->fence_drv[ring].sync_seq[ring]) { /* nothing to wait for, last_seq is already the last emited fence */ return -ENOENT; } - return radeon_fence_wait_seq(rdev, seq, ring, false, false); + return radeon_fence_wait_seq(rdev, seq, false, false); } =20 /** @@ -617,14 +506,15 @@ int radeon_fence_wait_next_locked(struct radeon_dev= ice *rdev, int ring) */ int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) { - uint64_t seq =3D rdev->fence_drv[ring].sync_seq[ring]; + uint64_t seq[RADEON_NUM_RINGS] =3D {}; int r; =20 - r =3D radeon_fence_wait_seq(rdev, seq, ring, false, false); + seq[ring] =3D rdev->fence_drv[ring].sync_seq[ring]; + r =3D radeon_fence_wait_seq(rdev, seq, false, false); if (r) { - if (r =3D=3D -EDEADLK) { + if (r =3D=3D -EDEADLK) return -EDEADLK; - } + dev_err(rdev->dev, "error waiting for ring[%d] to become idle (%d)\n", ring, r); } @@ -826,7 +716,6 @@ static void radeon_fence_driver_init_ring(struct rade= on_device *rdev, int ring) for (i =3D 0; i < RADEON_NUM_RINGS; ++i) rdev->fence_drv[ring].sync_seq[i] =3D 0; atomic64_set(&rdev->fence_drv[ring].last_seq, 0); - rdev->fence_drv[ring].last_activity =3D jiffies; rdev->fence_drv[ring].initialized =3D false; } =20 --=20 1.8.1.2 --------------060809080803030604050801 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel --------------060809080803030604050801--