From: Daniel Vetter <daniel@ffwll.ch>
To: Andy Lutomirski <luto@amacapital.net>
Cc: linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
linux-fbdev@vger.kernel.org,
Daniel Vetter <daniel.vetter@ffwll.ch>,
Jerome Glisse <j.glisse@gmail.com>,
Alex Deucher <alexdeucher@gmail.com>,
Dave Airlie <airlied@gmail.com>
Subject: Re: [RFC/PATCH v2 1/8] Add arch_phys_wc_{add,del} to manipulate WC MTRRs if needed
Date: Fri, 10 May 2013 11:19:23 +0200 [thread overview]
Message-ID: <20130510091923.GH12292@phenom.ffwll.local> (raw)
In-Reply-To: <97346b603822ffd8ab446316fc08fbf7686c9d50.1368128020.git.luto@amacapital.net>
On Thu, May 09, 2013 at 12:46:20PM -0700, Andy Lutomirski wrote:
> Several drivers currently use mtrr_add through various #ifdef guards
> and/or drm wrappers. The vast majority of them want to add WC MTRRs
> on x86 systems and don't actually need the MTRR if PAT (i.e.
> ioremap_wc, etc) are working.
>
> arch_phys_wc_add and arch_phys_wc_del are new functions, available
> on all architectures and configurations, that add WC MTRRs on x86 if
> needed (and handle errors) and do nothing at all otherwise. They're
> also easier to use than mtrr_add and mtrr_del, so the call sites can
> be simplified.
>
> As an added benefit, this will avoid wasting MTRRs and possibly
> warning pointlessly on PAT-supporting systems.
>
> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
> ---
> arch/x86/include/asm/io.h | 7 ++++++
> arch/x86/include/asm/mtrr.h | 5 ++++-
> arch/x86/kernel/cpu/mtrr/main.c | 48 +++++++++++++++++++++++++++++++++++++++++
> include/linux/io.h | 25 +++++++++++++++++++++
> 4 files changed, 84 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
> index d8e8eef..34f69cb 100644
> --- a/arch/x86/include/asm/io.h
> +++ b/arch/x86/include/asm/io.h
> @@ -345,4 +345,11 @@ extern bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
>
> #define IO_SPACE_LIMIT 0xffff
>
> +#ifdef CONFIG_MTRR
> +extern int __must_check arch_phys_wc_add(unsigned long base,
> + unsigned long size);
> +extern void arch_phys_wc_del(int handle);
> +#define arch_phys_wc_add arch_phys_wc_add
> +#endif
> +
> #endif /* _ASM_X86_IO_H */
> diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
> index e235582..10d0fba 100644
> --- a/arch/x86/include/asm/mtrr.h
> +++ b/arch/x86/include/asm/mtrr.h
> @@ -26,7 +26,10 @@
> #include <uapi/asm/mtrr.h>
>
>
> -/* The following functions are for use by other drivers */
> +/*
> + * The following functions are for use by other drivers that cannot use
> + * arch_phys_wc_add and arch_phys_wc_del.
> + */
> # ifdef CONFIG_MTRR
> extern u8 mtrr_type_lookup(u64 addr, u64 end);
> extern void mtrr_save_fixed_ranges(void *);
> diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
> index 726bf96..23bd49a 100644
> --- a/arch/x86/kernel/cpu/mtrr/main.c
> +++ b/arch/x86/kernel/cpu/mtrr/main.c
> @@ -51,6 +51,7 @@
> #include <asm/e820.h>
> #include <asm/mtrr.h>
> #include <asm/msr.h>
> +#include <asm/pat.h>
>
> #include "mtrr.h"
>
> @@ -524,6 +525,53 @@ int mtrr_del(int reg, unsigned long base, unsigned long size)
> }
> EXPORT_SYMBOL(mtrr_del);
>
> +/**
> + * arch_phys_wc_add - 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 arch_phys_wc_add(unsigned long base, unsigned long size)
> +{
> + int ret;
> +
> + if (pat_enabled)
> + return 0; /* Success! (We don't need to do anything.) */
Shouldn't we #define a big number for this case since mtrr_add returns
0-based mtrr indices? Rather unlikely that the very first mtrr is unused I
know, but still feels like a cleaner interface. And we don't need to leak
that #define out at all to users of this interface.
-Daniel
> +
> + ret = mtrr_add(base, size, MTRR_TYPE_WRCOMB, true);
> + if (ret < 0) {
> + pr_warn("Failed to add WC MTRR for [%p-%p]; performance may suffer.",
> + (void *)base, (void *)(base + size - 1));
> + return ret;
> + }
> + return ret + 1000;
> +}
> +EXPORT_SYMBOL(arch_phys_wc_add);
> +
> +/*
> + * arch_phys_wc_del - undoes arch_phys_wc_add
> + * @handle: Return value from arch_phys_wc_add
> + *
> + * This cleans up after mtrr_add_wc_if_needed.
> + *
> + * The API guarantees that mtrr_del_wc_if_needed(error code) and
> + * mtrr_del_wc_if_needed(0) do nothing.
> + */
> +extern void arch_phys_wc_del(int handle)
> +{
> + if (handle >= 1) {
> + WARN_ON(handle < 1000);
> + mtrr_del(handle - 1000, 0, 0);
> + }
> +}
> +EXPORT_SYMBOL(arch_phys_wc_del);
> +
> /*
> * HACK ALERT!
> * These should be called implicitly, but we can't yet until all the initcall
> diff --git a/include/linux/io.h b/include/linux/io.h
> index 069e407..f4f42fa 100644
> --- a/include/linux/io.h
> +++ b/include/linux/io.h
> @@ -76,4 +76,29 @@ void devm_ioremap_release(struct device *dev, void *res);
> #define arch_has_dev_port() (1)
> #endif
>
> +/*
> + * Some systems (x86 without PAT) have a somewhat reliable way to mark a
> + * physical address range such that uncached mappings will actually
> + * end up write-combining. This facility should be used in conjunction
> + * with pgprot_writecombine, ioremap-wc, or set_memory_wc, since it has
> + * no effect if the per-page mechanisms are functional.
> + * (On x86 without PAT, these functions manipulate MTRRs.)
> + *
> + * arch_phys_del_wc(0) or arch_phys_del_wc(any error code) is guaranteed
> + * to have no effect.
> + */
> +#ifndef arch_phys_wc_add
> +static inline int __must_check arch_phys_wc_add(unsigned long base,
> + unsigned long size)
> +{
> + return 0; /* It worked (i.e. did nothing). */
> +}
> +
> +static inline void arch_phys_wc_del(int handle)
> +{
> +}
> +
> +#define arch_phys_wc_add arch_phys_wc_add
> +#endif
> +
> #endif /* _LINUX_IO_H */
> --
> 1.8.1.4
>
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
next prev parent reply other threads:[~2013-05-10 9:16 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-05-09 19:46 [RFC/PATCH v2 0/8] Clean up write-combining MTRR addition Andy Lutomirski
2013-05-09 19:46 ` [RFC/PATCH v2 1/8] Add arch_phys_wc_{add,del} to manipulate WC MTRRs if needed Andy Lutomirski
2013-05-10 9:19 ` Daniel Vetter [this message]
2013-05-10 18:00 ` Andy Lutomirski
2013-05-10 19:09 ` Daniel Vetter
2013-05-10 19:27 ` Andy Lutomirski
2013-05-10 19:34 ` Daniel Vetter
2013-05-09 19:46 ` [RFC/PATCH v2 2/8] drm (ast,cirrus,mgag200,nouveau,savage,vmwgfx): Remove drm_mtrr_{add,del} Andy Lutomirski
2013-05-09 19:46 ` [RFC/PATCH v2 3/8] drm: Update drm_addmap and drm_mmap to use PAT WC instead of MTRRs Andy Lutomirski
2013-05-09 19:46 ` [RFC/PATCH v2 4/8] drm,agpgart: Use pgprot_writecombine for AGP maps and make the MTRR optional Andy Lutomirski
2013-05-09 19:46 ` [RFC/PATCH v2 5/8] i915: Use arch_phys_wc_{add,del} Andy Lutomirski
2013-05-10 9:36 ` Daniel Vetter
2013-05-09 19:46 ` [RFC/PATCH v2 6/8] radeon: Switch to arch_phys_wc_add and add a missing ..._del Andy Lutomirski
2013-05-09 19:46 ` [RFC/PATCH v2 7/8] uvesafb: Clean up MTRR code Andy Lutomirski
2013-05-09 19:46 ` [RFC/PATCH v2 8/8] drm: Remove mtrr_add and mtrr_del fallback hack for non-MTRR systems Andy Lutomirski
2013-05-09 23:44 ` [RFC/PATCH v2 0/8] Clean up write-combining MTRR addition Jerome Glisse
2013-05-10 1:21 ` Andy Lutomirski
2013-05-10 9:42 ` Daniel Vetter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130510091923.GH12292@phenom.ffwll.local \
--to=daniel@ffwll.ch \
--cc=airlied@gmail.com \
--cc=alexdeucher@gmail.com \
--cc=daniel.vetter@ffwll.ch \
--cc=dri-devel@lists.freedesktop.org \
--cc=j.glisse@gmail.com \
--cc=linux-fbdev@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@amacapital.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox