From patchwork Wed Jun 26 13:21:28 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Deucher X-Patchwork-Id: 2784581 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 F11289F968 for ; Wed, 26 Jun 2013 13:33:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7245C204AD for ; Wed, 26 Jun 2013 13:33:55 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id B373320498 for ; Wed, 26 Jun 2013 13:33:53 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 481A5E636E for ; Wed, 26 Jun 2013 06:33:53 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-qc0-f179.google.com (mail-qc0-f179.google.com [209.85.216.179]) by gabe.freedesktop.org (Postfix) with ESMTP id 54DBAE6367 for ; Wed, 26 Jun 2013 06:24:18 -0700 (PDT) Received: by mail-qc0-f179.google.com with SMTP id e11so8144823qcx.38 for ; Wed, 26 Jun 2013 06:24:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=aSjSHp5DzKNCFMNTPiezVuJSXfV0eiUHx2l7YsrD5/g=; b=ulctIYjS2jALUapf7BHQrBhJcgVcv6Qi4IUrt4Ngc8+zZ5xF77agtOFlkOCkFTDsKZ JBAgl9g9ekJaE/7NKyGNzxKiwtuGmehpqVSZQ/DXWmOS8pwV2HnI5r9fFXeeQKUwqFUN Z4y4kZUkfTHfTGWdry/3M04iNAu4CPcaavL93eei4kw/vheBzWo5jdq0d5GPCA5IeEFs YsGLRLjbeEL7rZ6ioTwu6N6CnUVdG1fraLFoh32x9frzvpRXj4uavFYfIgbn8+SL+DhW WJd6sHzLMDbauEchOx7mskzwjeGDGC76JBsf/P6y7toGSeN9vBakXgx6ARdcctwnWkWO sVuQ== X-Received: by 10.224.124.193 with SMTP id v1mr5346330qar.62.1372253057867; Wed, 26 Jun 2013 06:24:17 -0700 (PDT) Received: from localhost.localdomain (static-74-96-105-49.washdc.fios.verizon.net. [74.96.105.49]) by mx.google.com with ESMTPSA id r10sm32665096qeu.4.2013.06.26.06.24.17 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Wed, 26 Jun 2013 06:24:17 -0700 (PDT) From: alexdeucher@gmail.com To: dri-devel@lists.freedesktop.org Subject: [PATCH 008/165] drm/radeon: Add support for CIK GPU reset (v2) Date: Wed, 26 Jun 2013 09:21:28 -0400 Message-Id: <1372253045-17042-9-git-send-email-alexdeucher@gmail.com> X-Mailer: git-send-email 1.7.7.5 In-Reply-To: <1372253045-17042-1-git-send-email-alexdeucher@gmail.com> References: <1372253045-17042-1-git-send-email-alexdeucher@gmail.com> Cc: Alex Deucher X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org X-Spam-Status: No, score=-5.4 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, 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 From: Alex Deucher v2: split soft reset into compute and gfx. Still need to make reset more fine grained, but this should be a start. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 197 +++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/cikd.h | 80 +++++++++++++++++ 2 files changed, 277 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 28f68dc..e448ae2 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -27,9 +27,13 @@ #include #include "drmP.h" #include "radeon.h" +#include "radeon_asic.h" #include "cikd.h" #include "atom.h" +extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); +extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); + /* * Core functions */ @@ -1190,3 +1194,196 @@ static void cik_gpu_init(struct radeon_device *rdev) udelay(50); } +/** + * cik_gpu_is_lockup - check if the 3D engine is locked up + * + * @rdev: radeon_device pointer + * @ring: radeon_ring structure holding ring information + * + * Check if the 3D engine is locked up (CIK). + * Returns true if the engine is locked, false if not. + */ +bool cik_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) +{ + u32 srbm_status, srbm_status2; + u32 grbm_status, grbm_status2; + u32 grbm_status_se0, grbm_status_se1, grbm_status_se2, grbm_status_se3; + + srbm_status = RREG32(SRBM_STATUS); + srbm_status2 = RREG32(SRBM_STATUS2); + grbm_status = RREG32(GRBM_STATUS); + grbm_status2 = RREG32(GRBM_STATUS2); + grbm_status_se0 = RREG32(GRBM_STATUS_SE0); + grbm_status_se1 = RREG32(GRBM_STATUS_SE1); + grbm_status_se2 = RREG32(GRBM_STATUS_SE2); + grbm_status_se3 = RREG32(GRBM_STATUS_SE3); + if (!(grbm_status & GUI_ACTIVE)) { + radeon_ring_lockup_update(ring); + return false; + } + /* force CP activities */ + radeon_ring_force_activity(rdev, ring); + return radeon_ring_test_lockup(rdev, ring); +} + +/** + * cik_gfx_gpu_soft_reset - soft reset the 3D engine and CPG + * + * @rdev: radeon_device pointer + * + * Soft reset the GFX engine and CPG blocks (CIK). + * XXX: deal with reseting RLC and CPF + * Returns 0 for success. + */ +static int cik_gfx_gpu_soft_reset(struct radeon_device *rdev) +{ + struct evergreen_mc_save save; + u32 grbm_reset = 0; + + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + return 0; + + dev_info(rdev->dev, "GPU GFX softreset \n"); + dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", + RREG32(GRBM_STATUS)); + dev_info(rdev->dev, " GRBM_STATUS2=0x%08X\n", + RREG32(GRBM_STATUS2)); + dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", + RREG32(GRBM_STATUS_SE0)); + dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", + RREG32(GRBM_STATUS_SE1)); + dev_info(rdev->dev, " GRBM_STATUS_SE2=0x%08X\n", + RREG32(GRBM_STATUS_SE2)); + dev_info(rdev->dev, " GRBM_STATUS_SE3=0x%08X\n", + RREG32(GRBM_STATUS_SE3)); + dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", + RREG32(SRBM_STATUS)); + dev_info(rdev->dev, " SRBM_STATUS2=0x%08X\n", + RREG32(SRBM_STATUS2)); + evergreen_mc_stop(rdev, &save); + if (radeon_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); + } + /* Disable CP parsing/prefetching */ + WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT); + + /* reset all the gfx block and all CPG blocks */ + grbm_reset = SOFT_RESET_CPG | SOFT_RESET_GFX; + + dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset); + WREG32(GRBM_SOFT_RESET, grbm_reset); + (void)RREG32(GRBM_SOFT_RESET); + udelay(50); + WREG32(GRBM_SOFT_RESET, 0); + (void)RREG32(GRBM_SOFT_RESET); + /* Wait a little for things to settle down */ + udelay(50); + dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", + RREG32(GRBM_STATUS)); + dev_info(rdev->dev, " GRBM_STATUS2=0x%08X\n", + RREG32(GRBM_STATUS2)); + dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", + RREG32(GRBM_STATUS_SE0)); + dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", + RREG32(GRBM_STATUS_SE1)); + dev_info(rdev->dev, " GRBM_STATUS_SE2=0x%08X\n", + RREG32(GRBM_STATUS_SE2)); + dev_info(rdev->dev, " GRBM_STATUS_SE3=0x%08X\n", + RREG32(GRBM_STATUS_SE3)); + dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", + RREG32(SRBM_STATUS)); + dev_info(rdev->dev, " SRBM_STATUS2=0x%08X\n", + RREG32(SRBM_STATUS2)); + evergreen_mc_resume(rdev, &save); + return 0; +} + +/** + * cik_compute_gpu_soft_reset - soft reset CPC + * + * @rdev: radeon_device pointer + * + * Soft reset the CPC blocks (CIK). + * XXX: deal with reseting RLC and CPF + * Returns 0 for success. + */ +static int cik_compute_gpu_soft_reset(struct radeon_device *rdev) +{ + struct evergreen_mc_save save; + u32 grbm_reset = 0; + + dev_info(rdev->dev, "GPU compute softreset \n"); + dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", + RREG32(GRBM_STATUS)); + dev_info(rdev->dev, " GRBM_STATUS2=0x%08X\n", + RREG32(GRBM_STATUS2)); + dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", + RREG32(GRBM_STATUS_SE0)); + dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", + RREG32(GRBM_STATUS_SE1)); + dev_info(rdev->dev, " GRBM_STATUS_SE2=0x%08X\n", + RREG32(GRBM_STATUS_SE2)); + dev_info(rdev->dev, " GRBM_STATUS_SE3=0x%08X\n", + RREG32(GRBM_STATUS_SE3)); + dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", + RREG32(SRBM_STATUS)); + dev_info(rdev->dev, " SRBM_STATUS2=0x%08X\n", + RREG32(SRBM_STATUS2)); + evergreen_mc_stop(rdev, &save); + if (radeon_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); + } + /* Disable CP parsing/prefetching */ + WREG32(CP_MEC_CNTL, MEC_ME1_HALT | MEC_ME2_HALT); + + /* reset all the CPC blocks */ + grbm_reset = SOFT_RESET_CPG; + + dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset); + WREG32(GRBM_SOFT_RESET, grbm_reset); + (void)RREG32(GRBM_SOFT_RESET); + udelay(50); + WREG32(GRBM_SOFT_RESET, 0); + (void)RREG32(GRBM_SOFT_RESET); + /* Wait a little for things to settle down */ + udelay(50); + dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", + RREG32(GRBM_STATUS)); + dev_info(rdev->dev, " GRBM_STATUS2=0x%08X\n", + RREG32(GRBM_STATUS2)); + dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", + RREG32(GRBM_STATUS_SE0)); + dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", + RREG32(GRBM_STATUS_SE1)); + dev_info(rdev->dev, " GRBM_STATUS_SE2=0x%08X\n", + RREG32(GRBM_STATUS_SE2)); + dev_info(rdev->dev, " GRBM_STATUS_SE3=0x%08X\n", + RREG32(GRBM_STATUS_SE3)); + dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", + RREG32(SRBM_STATUS)); + dev_info(rdev->dev, " SRBM_STATUS2=0x%08X\n", + RREG32(SRBM_STATUS2)); + evergreen_mc_resume(rdev, &save); + return 0; +} + +/** + * cik_asic_reset - soft reset compute and gfx + * + * @rdev: radeon_device pointer + * + * Soft reset the CPC blocks (CIK). + * XXX: make this more fine grained and only reset + * what is necessary. + * Returns 0 for success. + */ +int cik_asic_reset(struct radeon_device *rdev) +{ + int r; + + r = cik_compute_gpu_soft_reset(rdev); + if (r) + dev_info(rdev->dev, "Compute reset failed!\n"); + + return cik_gfx_gpu_soft_reset(rdev); +} diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index e51fb41..41b2316 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h @@ -30,6 +30,9 @@ #define DMIF_ADDR_CALC 0xC00 +#define SRBM_STATUS2 0xE4C +#define SRBM_STATUS 0xE50 + #define MC_SHARED_CHMAP 0x2004 #define NOOFCHAN_SHIFT 12 #define NOOFCHAN_MASK 0x0000f000 @@ -65,6 +68,83 @@ #define GRBM_CNTL 0x8000 #define GRBM_READ_TIMEOUT(x) ((x) << 0) +#define GRBM_STATUS2 0x8008 +#define ME0PIPE1_CMDFIFO_AVAIL_MASK 0x0000000F +#define ME0PIPE1_CF_RQ_PENDING (1 << 4) +#define ME0PIPE1_PF_RQ_PENDING (1 << 5) +#define ME1PIPE0_RQ_PENDING (1 << 6) +#define ME1PIPE1_RQ_PENDING (1 << 7) +#define ME1PIPE2_RQ_PENDING (1 << 8) +#define ME1PIPE3_RQ_PENDING (1 << 9) +#define ME2PIPE0_RQ_PENDING (1 << 10) +#define ME2PIPE1_RQ_PENDING (1 << 11) +#define ME2PIPE2_RQ_PENDING (1 << 12) +#define ME2PIPE3_RQ_PENDING (1 << 13) +#define RLC_RQ_PENDING (1 << 14) +#define RLC_BUSY (1 << 24) +#define TC_BUSY (1 << 25) +#define CPF_BUSY (1 << 28) +#define CPC_BUSY (1 << 29) +#define CPG_BUSY (1 << 30) + +#define GRBM_STATUS 0x8010 +#define ME0PIPE0_CMDFIFO_AVAIL_MASK 0x0000000F +#define SRBM_RQ_PENDING (1 << 5) +#define ME0PIPE0_CF_RQ_PENDING (1 << 7) +#define ME0PIPE0_PF_RQ_PENDING (1 << 8) +#define GDS_DMA_RQ_PENDING (1 << 9) +#define DB_CLEAN (1 << 12) +#define CB_CLEAN (1 << 13) +#define TA_BUSY (1 << 14) +#define GDS_BUSY (1 << 15) +#define WD_BUSY_NO_DMA (1 << 16) +#define VGT_BUSY (1 << 17) +#define IA_BUSY_NO_DMA (1 << 18) +#define IA_BUSY (1 << 19) +#define SX_BUSY (1 << 20) +#define WD_BUSY (1 << 21) +#define SPI_BUSY (1 << 22) +#define BCI_BUSY (1 << 23) +#define SC_BUSY (1 << 24) +#define PA_BUSY (1 << 25) +#define DB_BUSY (1 << 26) +#define CP_COHERENCY_BUSY (1 << 28) +#define CP_BUSY (1 << 29) +#define CB_BUSY (1 << 30) +#define GUI_ACTIVE (1 << 31) +#define GRBM_STATUS_SE0 0x8014 +#define GRBM_STATUS_SE1 0x8018 +#define GRBM_STATUS_SE2 0x8038 +#define GRBM_STATUS_SE3 0x803C +#define SE_DB_CLEAN (1 << 1) +#define SE_CB_CLEAN (1 << 2) +#define SE_BCI_BUSY (1 << 22) +#define SE_VGT_BUSY (1 << 23) +#define SE_PA_BUSY (1 << 24) +#define SE_TA_BUSY (1 << 25) +#define SE_SX_BUSY (1 << 26) +#define SE_SPI_BUSY (1 << 27) +#define SE_SC_BUSY (1 << 29) +#define SE_DB_BUSY (1 << 30) +#define SE_CB_BUSY (1 << 31) + +#define GRBM_SOFT_RESET 0x8020 +#define SOFT_RESET_CP (1 << 0) /* All CP blocks */ +#define SOFT_RESET_RLC (1 << 2) /* RLC */ +#define SOFT_RESET_GFX (1 << 16) /* GFX */ +#define SOFT_RESET_CPF (1 << 17) /* CP fetcher shared by gfx and compute */ +#define SOFT_RESET_CPC (1 << 18) /* CP Compute (MEC1/2) */ +#define SOFT_RESET_CPG (1 << 19) /* CP GFX (PFP, ME, CE) */ + +#define CP_MEC_CNTL 0x8234 +#define MEC_ME2_HALT (1 << 28) +#define MEC_ME1_HALT (1 << 30) + +#define CP_ME_CNTL 0x86D8 +#define CP_CE_HALT (1 << 24) +#define CP_PFP_HALT (1 << 26) +#define CP_ME_HALT (1 << 28) + #define CP_MEQ_THRESHOLDS 0x8764 #define MEQ1_START(x) ((x) << 0) #define MEQ2_START(x) ((x) << 8)