From patchwork Fri May 3 23:00:29 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Lutomirski X-Patchwork-Id: 2520621 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id 1BE19DF25A for ; Sat, 4 May 2013 14:10:25 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1153AE5F64 for ; Sat, 4 May 2013 07:10:25 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-pa0-f47.google.com (mail-pa0-f47.google.com [209.85.220.47]) by gabe.freedesktop.org (Postfix) with ESMTP id 95011E5D07 for ; Fri, 3 May 2013 16:00:54 -0700 (PDT) Received: by mail-pa0-f47.google.com with SMTP id kl13so1148388pab.34 for ; Fri, 03 May 2013 16:00:54 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references:in-reply-to:references:x-gm-message-state; bh=vKTdHwRhi9b+g5JB6f59ezwSbIDMAXRVx4Dx1tCJB1k=; b=c6XiaXReCokFhLdzcMAU/mCt60LEGNKKwhsmn/v3kUOT9j8aJnoLtTTJVr/BYp1GEB 2c5i18qgLBENIIH2aUbpTdGaot+vV9p0MBLfPbdhsKjtRnk88GfsX4pXAIXOz8V9J4NV VaHpKmFX8EsUe7C0oDvBZrgtLtHytabhdmKxkaVSP2mhXODF/I8nu7QcX48e2RRddGf0 qiI6BKApf7TXoyAANTVvSBnXviOeD9qKpwVGcf0R/L6mA28DtpBYkWsvGG/bl8quo1Ly JnY6QBzGlo1OAZGUQTnW0u0YyQXFy/fnFLDa8gFx6ZIlXzoYeNffm6lyyoDsdg6NuAiL nCJg== X-Received: by 10.68.113.194 with SMTP id ja2mr15766008pbb.65.1367622054303; Fri, 03 May 2013 16:00:54 -0700 (PDT) Received: from localhost (50-76-60-73-ip-static.hfc.comcastbusiness.net. [50.76.60.73]) by mx.google.com with ESMTPSA id uf2sm13236795pbc.41.2013.05.03.16.00.52 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Fri, 03 May 2013 16:00:53 -0700 (PDT) From: Andy Lutomirski To: linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-fbdev@vger.kernel.org Subject: [PATCH 1/7] x86: Add mtrr_{add,del}_wc_if_needed Date: Fri, 3 May 2013 16:00:29 -0700 Message-Id: X-Mailer: git-send-email 1.8.1.4 In-Reply-To: References: In-Reply-To: References: X-Gm-Message-State: ALoCoQnPtLJfHRfwa97zfu7Xqv6uB+UBsmHDvD+Ex7yftRvzcd5sH7U4sVt+gWd3ajeVeit00N53 X-Mailman-Approved-At: Sat, 04 May 2013 07:08:30 -0700 Cc: x86@kernel.org, Andy Lutomirski 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 These MTRR helpers add a WC MTRR if PAT is disabled. Modern drivers should be using ioremap_wc, etc. to get WC memory; the MTRR is just a fallback if the system doesn't have PAT. So, rather than allocating an unnecessary MTRR even on PAT systems and having error handling spread out and handled differently by different drivers, consolidate it all and don't waste the MTRR on PAT-supporting systems. (Follow-up changes will update drivers.) This should be a simple change, a bit of a clean-up, and it will flush out any drivers that actually depend on the MTRR for write combining. Signed-off-by: Andy Lutomirski --- arch/x86/include/asm/mtrr.h | 21 ++++++++++++++++ arch/x86/kernel/cpu/mtrr/main.c | 53 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index e235582..cc96c72 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -45,6 +45,18 @@ extern void mtrr_aps_init(void); extern void mtrr_bp_restore(void); extern int mtrr_trim_uncached_memory(unsigned long end_pfn); extern int amd_special_default_mtrr(void); + +/* + * These are for drivers (mostly video) that want to add WC MTRRs as a + * fallback if PAT is unavailable. There is no need to check for errors. + * + * The handles used by the _if_needed functions are *not* MTRR indices. + * mtrr_del_wc_if_needed(0) and mtrr_del_wc_if_needed(-1) are + * guaranteed to have no effect. + */ +extern int __must_check mtrr_add_wc_if_needed(unsigned long base, + unsigned long size); +extern void mtrr_del_wc_if_needed(int handle); # else static inline u8 mtrr_type_lookup(u64 addr, u64 end) { @@ -86,6 +98,15 @@ static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) #define set_mtrr_aps_delayed_init() do {} while (0) #define mtrr_aps_init() do {} while (0) #define mtrr_bp_restore() do {} while (0) + +static inline int __must_check mtrr_add_wc_if_needed(unsigned long base, + unsigned long size) +{ + return -ENODEV; +} +static inline void mtrr_del_wc_if_needed(int handle) +{ +} # endif #ifdef CONFIG_COMPAT diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 726bf96..6370238 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -51,6 +51,7 @@ #include #include #include +#include #include "mtrr.h" @@ -524,6 +525,58 @@ int mtrr_del(int reg, unsigned long base, unsigned long size) } EXPORT_SYMBOL(mtrr_del); +/** + * mtrr_add_wc_if_needed - add a WC MTRR and handle errors if PAT is unavailable + * @base: Physical base address + * @size: Size of region + * + * If PAT is available, this does nothing. If PAT is unavailable, it + * attempts to add a WC MTRR covering size bytes starting at base and + * logs an error if this fails. + * + * Drivers must store the return value to pass to mtrr_del_wc_if_needed, + * but drivers should not try to interpret that return value. + */ +int mtrr_add_wc_if_needed(unsigned long base, unsigned long size) +{ + int ret; + + if (pat_enabled) { + /* + * Don't bother -- we don't need the MTRR. Return an error + * so that no one gets confused. + */ + return -EBUSY; /* The error doesn't matter. */ + } + + ret = mtrr_add(base, size, MTRR_TYPE_WRCOMB, true); + if (ret < 0) { + pr_warn("Failed to add WC MTRR for [%p-%p]; performance will suffer.", + (void *)base, (void *)(base + size - 1)); + return ret; + } + return ret + 1000; +} +EXPORT_SYMBOL(mtrr_add_wc_if_needed); + +/* + * mtrr_del_wc_if_needed - undoes mtrr_add_wc_if_needed + * @handle: Return value from mtrr_add_wc_if_needed + * + * This cleans up after mtrr_add_wc_if_needed. + * + * The API guarantees that mtrr_del_wc_if_needed(-1) and + * mtrr_del_wc_if_needed(0) do nothing. + */ +extern void mtrr_del_wc_if_needed(int handle) +{ + if (handle >= 1) { + WARN_ON(handle < 1000); + mtrr_del(handle - 1000, 0, 0); + } +} +EXPORT_SYMBOL(mtrr_del_wc_if_needed); + /* * HACK ALERT! * These should be called implicitly, but we can't yet until all the initcall