From patchwork Tue Aug 19 12:22:59 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maarten Lankhorst X-Patchwork-Id: 4742481 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 68C9C9F375 for ; Tue, 19 Aug 2014 12:23:08 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6D4742014A for ; Tue, 19 Aug 2014 12:23:07 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 0AEE420123 for ; Tue, 19 Aug 2014 12:23:05 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 012BB6E0D9; Tue, 19 Aug 2014 05:23:04 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from youngberry.canonical.com (youngberry.canonical.com [91.189.89.112]) by gabe.freedesktop.org (Postfix) with ESMTP id DF87F6E0D9 for ; Tue, 19 Aug 2014 05:23:02 -0700 (PDT) Received: from 5ed49945.cm-7-5c.dynamic.ziggo.nl ([94.212.153.69] helo=[192.168.1.128]) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1XJiRI-0007G6-PL; Tue, 19 Aug 2014 12:23:00 +0000 Message-ID: <53F341A3.6060902@canonical.com> Date: Tue, 19 Aug 2014 14:22:59 +0200 From: Maarten Lankhorst User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.0 MIME-Version: 1.0 To: =?UTF-8?B?Q2hyaXN0aWFuIEvDtm5pZw==?= , "Deucher, Alexander" Subject: [PATCH v3 1/3] drm/radeon: take exclusive_lock in read mode during, ring tests, v3 Cc: "dri-devel@lists.freedesktop.org" X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Status: No, score=-4.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This is needed for the next commit, because the lockup detection will need the read lock to run. Signed-off-by: Maarten Lankhorst --- radeon_pm_compute_clocks already checks if dpm is enabled, so no need to check a second time. Because of locking and waiting stuff the radeon_pm_compute_clocks and resume_force_mode calls have to be done with read lock held. Seems to survive on my radeon when catting /sys/kernel/debug/dri/0/radeon_gpu_reset although uvd fails to reset, and that ring gets disabled as a result. drivers/gpu/drm/radeon/radeon.h | 2 +- drivers/gpu/drm/radeon/radeon_device.c | 57 +++++++++++++++++++-------------- drivers/gpu/drm/radeon/radeon_display.c | 4 ++- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index b281886f6f51..9d97409c0443 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -2315,7 +2315,7 @@ struct radeon_device { bool need_dma32; bool accel_working; bool fastfb_working; /* IGP feature*/ - bool needs_reset; + bool needs_reset, in_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/radeon/radeon_device.c index 6a219bcee66d..124d8994e02a 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1671,6 +1671,7 @@ int radeon_gpu_reset(struct radeon_device *rdev) down_write(&rdev->exclusive_lock); if (!rdev->needs_reset) { + WARN_ON(rdev->in_reset); up_write(&rdev->exclusive_lock); return 0; } @@ -1683,17 +1684,21 @@ int radeon_gpu_reset(struct radeon_device *rdev) radeon_suspend(rdev); radeon_hpd_fini(rdev); - for (i = 0; i < RADEON_NUM_RINGS; ++i) { - ring_sizes[i] = radeon_ring_backup(rdev, &rdev->ring[i], - &ring_data[i]); - if (ring_sizes[i]) { - saved = true; - dev_info(rdev->dev, "Saved %d dwords of commands " - "on ring %d.\n", ring_sizes[i], i); + if (!rdev->in_reset) { + rdev->in_reset = true; + + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + ring_sizes[i] = radeon_ring_backup(rdev, &rdev->ring[i], + &ring_data[i]); + if (ring_sizes[i]) { + saved = true; + dev_info(rdev->dev, "Saved %d dwords of commands " + "on ring %d.\n", ring_sizes[i], i); + } } - } + } else + memset(ring_data, 0, sizeof(ring_data)); -retry: r = radeon_asic_reset(rdev); if (!r) { dev_info(rdev->dev, "GPU reset succeeded, trying to resume\n"); @@ -1709,16 +1714,6 @@ retry: ring_sizes[i] = 0; ring_data[i] = NULL; } - - r = radeon_ib_ring_tests(rdev); - if (r) { - dev_err(rdev->dev, "ib ring test failed (%d).\n", r); - if (saved) { - saved = false; - radeon_suspend(rdev); - goto retry; - } - } } else { radeon_fence_driver_force_completion(rdev); for (i = 0; i < RADEON_NUM_RINGS; ++i) { @@ -1728,8 +1723,7 @@ retry: if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) { /* do dpm late init */ - r = radeon_pm_late_init(rdev); - if (r) { + if (radeon_pm_late_init(rdev)) { rdev->pm.dpm_enabled = false; DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n"); } @@ -1753,19 +1747,34 @@ retry: /* reset hpd state */ radeon_hpd_init(rdev); + ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); + downgrade_write(&rdev->exclusive_lock); + drm_helper_resume_force_mode(rdev->ddev); /* set the power state here in case we are a PX system or headless */ - if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) + if ((rdev->pm.pm_method == PM_METHOD_DPM)) radeon_pm_compute_clocks(rdev); - ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); + if (!r) { + r = radeon_ib_ring_tests(rdev); + if (r) { + dev_err(rdev->dev, "ib ring test failed (%d).\n", r); + if (saved) { + rdev->needs_reset = true; + up_read(&rdev->exclusive_lock); + return -EAGAIN; + } + } + } + if (r) { /* bad news, how to tell it to userspace ? */ dev_info(rdev->dev, "GPU reset failed\n"); } - up_write(&rdev->exclusive_lock); + rdev->in_reset = false; + up_read(&rdev->exclusive_lock); return r; } diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 3fdf87318069..bd0d687379ee 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -405,7 +405,9 @@ static void radeon_flip_work_func(struct work_struct *__work) r = radeon_fence_wait(work->fence, false); if (r == -EDEADLK) { up_read(&rdev->exclusive_lock); - r = radeon_gpu_reset(rdev); + do { + r = radeon_gpu_reset(rdev); + } while (r == -EAGAIN); down_read(&rdev->exclusive_lock); } if (r)