Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp420773pxb; Wed, 24 Feb 2021 05:57:30 -0800 (PST) X-Google-Smtp-Source: ABdhPJy0nPDq61OU8lxbgIiEi0Xg1lsXfbWhEk8idJKVF25VaNFlc+aYvJyIERhJlVd+bfDb0FKP X-Received: by 2002:a17:906:f288:: with SMTP id gu8mr31500644ejb.512.1614175050577; Wed, 24 Feb 2021 05:57:30 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1614175050; cv=none; d=google.com; s=arc-20160816; b=tU2Y5yxW76cI0odrI7J31gJwUdA8LlnV/KJJFI9uWtpxWnCvXvaaCqUkI5Q0r/theP 0NX748V9M42KNoK/Ehp/U8qblEXvKNPRjATdnOM3kEjPILTLRZtGweWwyy1a4pOPDMqR bwzgYu/Gv4oqNhtQDyh6ebu3phmgmwk+j821jHwJyd7OWp5wc6lt2z8zIy7+9DXDC3lZ RmfYUWoaqCWTdX5NS6/jnn9E7izIqTG8jaxPBCI/Aw3oybQiKbEoasHaIVDKj7Fs4uq8 hkmoykiZO3+7EqU86MJ4H4YJWEBH/WYBjLnJ9mbsVQIYKPzaj9mhHCExiEjVTRSAnfuC GlvQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=7VaKslU+sP9G1RIHUndLMJ5BcTq2v+Qu2T3x7WWi930=; b=LrCDwZLdDPuPD0hDSewVBS+Oh55muwgcarOdygeRlRqOw30kd/dwzYRPTTvK9Yeyk0 liEz+bqycnRlufgVCZxnj1txSQt7gK8RE7VOxwH/P90erEdaG3vUlDrtIHON2bom3wf0 kG63oWombVrFZ2HWoqyVlaN6Ptdika/9NhaieSTxSdockhg8WjfZyW/pOJ0fcdX/Zgqw A7A/o7rOvpACL8zBRoP/11Bj4LOKBs94czKJVW3CbnYBAN2PvEmADNj8TpkhchrAdjAm 8s0vlQ/wL6tYbSWpM1PfPaSAoKnLMaLrtLmjl5Wi2KI682fqMqBvB0rzMGO4+5O+JipO VnPw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=nZZ7TxMR; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id w8si1181471edc.83.2021.02.24.05.56.58; Wed, 24 Feb 2021 05:57:30 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=nZZ7TxMR; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237776AbhBXNrm (ORCPT + 99 others); Wed, 24 Feb 2021 08:47:42 -0500 Received: from mail.kernel.org ([198.145.29.99]:58436 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235710AbhBXNFC (ORCPT ); Wed, 24 Feb 2021 08:05:02 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id EDA2864F7E; Wed, 24 Feb 2021 12:54:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1614171243; bh=nmhDbiLN8SzIZcd7G6hoQrejKrrv37qolNba8EO8YvU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nZZ7TxMR+fWHUiWtMqUjN2mGUaWlOFsLYOiZv161wMgBSAsDDRapENvrYSLDa3sCX aj0GSFIIKp3un3kaYzuX1jlopNKdMU1P/aaZiH5Mr4vYOFD+DRKSXZBSLSsfpnAkKm c/5RVQ7lu8gUzd75lnOTAWxDg4iM63v/YTXo21fPrp5WMKbkzqsSib3qgev4hBTzfU YCi3j+KMsrnGxCzoSh8A+VVWANUFGoV6i7dJqoHgp2lw+td96dYSWEv+AhLKVGgjOq mddVumyfwnXlrZExowrcjzrak3zNeHGz1F5s6Fwx7DXInfCYiWQmo2RGjyZcY/V9dB oVlUo7dx2AG0A== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Defang Bo , =?UTF-8?q?Christian=20K=C3=B6nig?= , Alex Deucher , Sasha Levin , amd-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Subject: [PATCH AUTOSEL 5.4 17/40] drm/amdgpu: Add check to prevent IH overflow Date: Wed, 24 Feb 2021 07:53:17 -0500 Message-Id: <20210224125340.483162-17-sashal@kernel.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210224125340.483162-1-sashal@kernel.org> References: <20210224125340.483162-1-sashal@kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Defang Bo [ Upstream commit e4180c4253f3f2da09047f5139959227f5cf1173 ] Similar to commit ("drm/amdgpu: fix IH overflow on Vega10 v2"). When an ring buffer overflow happens the appropriate bit is set in the WPTR register which is also written back to memory. But clearing the bit in the WPTR doesn't trigger another memory writeback. So what can happen is that we end up processing the buffer overflow over and over again because the bit is never cleared. Resulting in a random system lockup because of an infinite loop in an interrupt handler. Reviewed-by: Christian König Signed-off-by: Defang Bo Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/cz_ih.c | 37 ++++++++++++++++--------- drivers/gpu/drm/amd/amdgpu/iceland_ih.c | 36 +++++++++++++++--------- drivers/gpu/drm/amd/amdgpu/tonga_ih.c | 37 ++++++++++++++++--------- 3 files changed, 71 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/cz_ih.c b/drivers/gpu/drm/amd/amdgpu/cz_ih.c index 1dca0cabc326a..13520d173296f 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_ih.c @@ -193,19 +193,30 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev, wptr = le32_to_cpu(*ih->wptr_cpu); - if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) { - wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0); - /* When a ring buffer overflow happen start parsing interrupt - * from the last not overwritten vector (wptr + 16). Hopefully - * this should allow us to catchup. - */ - dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", - wptr, ih->rptr, (wptr + 16) & ih->ptr_mask); - ih->rptr = (wptr + 16) & ih->ptr_mask; - tmp = RREG32(mmIH_RB_CNTL); - tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); - WREG32(mmIH_RB_CNTL, tmp); - } + if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) + goto out; + + /* Double check that the overflow wasn't already cleared. */ + wptr = RREG32(mmIH_RB_WPTR); + + if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) + goto out; + + wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0); + + /* When a ring buffer overflow happen start parsing interrupt + * from the last not overwritten vector (wptr + 16). Hopefully + * this should allow us to catchup. + */ + dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", + wptr, ih->rptr, (wptr + 16) & ih->ptr_mask); + ih->rptr = (wptr + 16) & ih->ptr_mask; + tmp = RREG32(mmIH_RB_CNTL); + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); + WREG32(mmIH_RB_CNTL, tmp); + + +out: return (wptr & ih->ptr_mask); } diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c index a13dd9a51149a..7d165f024f072 100644 --- a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c @@ -193,19 +193,29 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev, wptr = le32_to_cpu(*ih->wptr_cpu); - if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) { - wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0); - /* When a ring buffer overflow happen start parsing interrupt - * from the last not overwritten vector (wptr + 16). Hopefully - * this should allow us to catchup. - */ - dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", - wptr, ih->rptr, (wptr + 16) & ih->ptr_mask); - ih->rptr = (wptr + 16) & ih->ptr_mask; - tmp = RREG32(mmIH_RB_CNTL); - tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); - WREG32(mmIH_RB_CNTL, tmp); - } + if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) + goto out; + + /* Double check that the overflow wasn't already cleared. */ + wptr = RREG32(mmIH_RB_WPTR); + + if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) + goto out; + + wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0); + /* When a ring buffer overflow happen start parsing interrupt + * from the last not overwritten vector (wptr + 16). Hopefully + * this should allow us to catchup. + */ + dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", + wptr, ih->rptr, (wptr + 16) & ih->ptr_mask); + ih->rptr = (wptr + 16) & ih->ptr_mask; + tmp = RREG32(mmIH_RB_CNTL); + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); + WREG32(mmIH_RB_CNTL, tmp); + + +out: return (wptr & ih->ptr_mask); } diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c index e40140bf6699c..db0a3bda13fbe 100644 --- a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c @@ -195,19 +195,30 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev, wptr = le32_to_cpu(*ih->wptr_cpu); - if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) { - wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0); - /* When a ring buffer overflow happen start parsing interrupt - * from the last not overwritten vector (wptr + 16). Hopefully - * this should allow us to catchup. - */ - dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", - wptr, ih->rptr, (wptr + 16) & ih->ptr_mask); - ih->rptr = (wptr + 16) & ih->ptr_mask; - tmp = RREG32(mmIH_RB_CNTL); - tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); - WREG32(mmIH_RB_CNTL, tmp); - } + if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) + goto out; + + /* Double check that the overflow wasn't already cleared. */ + wptr = RREG32(mmIH_RB_WPTR); + + if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) + goto out; + + wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0); + + /* When a ring buffer overflow happen start parsing interrupt + * from the last not overwritten vector (wptr + 16). Hopefully + * this should allow us to catchup. + */ + + dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", + wptr, ih->rptr, (wptr + 16) & ih->ptr_mask); + ih->rptr = (wptr + 16) & ih->ptr_mask; + tmp = RREG32(mmIH_RB_CNTL); + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); + WREG32(mmIH_RB_CNTL, tmp); + +out: return (wptr & ih->ptr_mask); } -- 2.27.0