Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* Re: [PATCH 2/7] drm (ast, cirrus, mgag200, nouveau, savage, vmwgfx): Rework drm_mtrr_{add, del}
From: Andy Lutomirski @ 2013-05-04 17:48 UTC (permalink / raw)
  To: Andy Lutomirski, linux-kernel, dri-devel, linux-fbdev
In-Reply-To: <20130504174555.GT5763@phenom.ffwll.local>

On Sat, May 4, 2013 at 10:45 AM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Fri, May 03, 2013 at 04:00:30PM -0700, Andy Lutomirski wrote:
>> This replaces drm_mtrr_{add,del} with drm_mtrr_{add,del}_wc.  The
>> interface is simplified (because the base and size parameters to
>> drm_mtrr_del never did anything) and it uses
>> mtrr_{add,del}_wc_if_needed to avoid allocating MTRRs on systems
>> that don't need them.
>>
>> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
>> ---
>
>
> Tbh I'm not a big fan of the drm_ indirection. Historically that was
> useful as an OS abstraction layer so that the same drivers could be used
> unchanged on Linux and the *BSD. But those days are long gone and drm
> drivers are now proper Linux drivers, and generally OS HALs seem to be
> frowned upon.
>
> Is there another reason than just being consistent with the historic stuff
> here? If we need dummy functions for !CONFIG_MTRR I think those should
> simply be in the core.


I admit to a bit of cargo-culting.  There was a layer of indirection,
so I kept it.  I'll just call mtrr_add/del_wc_if_needed directly in v2
(I added those functions in patch 1 of this series).

I'd assume you're okay with skipping mtrr addition if PAT is available
since i915 already does it :)  (Although the current logic is buggy --
cpu_has_pat is the wrong flag to check -- I think pat_enabled is
better.)

Note to self: I should remove #include <asm/pat.h> in i915_dma.c in v2.

--Andy

^ permalink raw reply

* [PATCH 11/13] video: mxsfb: Let device core handle pinctrl
From: Fabio Estevam @ 2013-05-06 18:05 UTC (permalink / raw)
  To: linux-fbdev

Since commit ab78029 (drivers/pinctrl: grab default handles from device core),
we can rely on device core for handling pinctrl.

So remove devm_pinctrl_get_select_default() from the driver. 

Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: <linux-fbdev@vger.kernel.org>
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
---
 drivers/video/mxsfb.c |    9 ---------
 1 file changed, 9 deletions(-)

diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 45169cb..a27f028 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -47,7 +47,6 @@
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
-#include <linux/pinctrl/consumer.h>
 #include <linux/mxsfb.h>
 
 #define REG_SET	4
@@ -783,7 +782,6 @@ static int mxsfb_probe(struct platform_device *pdev)
 	struct mxsfb_info *host;
 	struct fb_info *fb_info;
 	struct fb_modelist *modelist;
-	struct pinctrl *pinctrl;
 	int panel_enable;
 	enum of_gpio_flags flags;
 	int i, ret;
@@ -826,12 +824,6 @@ static int mxsfb_probe(struct platform_device *pdev)
 
 	host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
 
-	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-	if (IS_ERR(pinctrl)) {
-		ret = PTR_ERR(pinctrl);
-		goto error_getpin;
-	}
-
 	host->clk = clk_get(&host->pdev->dev, NULL);
 	if (IS_ERR(host->clk)) {
 		ret = PTR_ERR(host->clk);
@@ -906,7 +898,6 @@ error_pseudo_pallette:
 error_panel_enable:
 	clk_put(host->clk);
 error_getclock:
-error_getpin:
 	iounmap(host->base);
 error_ioremap:
 	framebuffer_release(fb_info);
-- 
1.7.9.5



^ permalink raw reply related

* Re: [PATCH 3/7] drm: Update drm_addmap and drm_mmap to use PAT WC instead of MTRRs
From: Andy Lutomirski @ 2013-05-06 21:22 UTC (permalink / raw)
  To: linux-kernel, dri-devel, linux-fbdev; +Cc: Andy Lutomirski
In-Reply-To: <d6e5e371e464b7de1115a00f02b5b834315cd986.1367621039.git.luto@amacapital.net>

On Fri, May 3, 2013 at 4:00 PM, Andy Lutomirski <luto@amacapital.net> wrote:
> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
> ---
>
> This needs careful review.  I don't really know what this code does, nor
> do I have the hardware.  (I don't understand AGP and the associated
> caching implications.)

This patch is wrong (I didn't update the matching mtrr_del), and I'm
reworking this whole series.  But I may need some help on this one:
why is the mtrr handle of a map (whatever a map is) exported to
userspace via the ADD_MAP and GET_MAP ioctls?  What (if anything) is
userspace supposed to do with it?  Do I need to return a valid MTRR
register number?  Is there any userspace code at all that sets
_DRM_WRITE_COMBINING in DRM_IOCTL_ADD_MAP with appropriate alignment
and needs the MTRR, for which the drm driver doesn't already add the
MTRR?

--Andy

^ permalink raw reply

* Re: [PATCH 3/7] drm: Update drm_addmap and drm_mmap to use PAT WC instead of MTRRs
From: Jerome Glisse @ 2013-05-06 23:04 UTC (permalink / raw)
  To: Andy Lutomirski; +Cc: linux-kernel, dri-devel, linux-fbdev
In-Reply-To: <CALCETrVe=JSPB=x79e1fAK=DrMgo7_Liagihib9quJDJ0N670Q@mail.gmail.com>

On Mon, May 6, 2013 at 5:22 PM, Andy Lutomirski <luto@amacapital.net> wrote:
> On Fri, May 3, 2013 at 4:00 PM, Andy Lutomirski <luto@amacapital.net> wrote:
>> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
>> ---
>>
>> This needs careful review.  I don't really know what this code does, nor
>> do I have the hardware.  (I don't understand AGP and the associated
>> caching implications.)
>
> This patch is wrong (I didn't update the matching mtrr_del), and I'm
> reworking this whole series.  But I may need some help on this one:
> why is the mtrr handle of a map (whatever a map is) exported to
> userspace via the ADD_MAP and GET_MAP ioctls?  What (if anything) is
> userspace supposed to do with it?  Do I need to return a valid MTRR
> register number?  Is there any userspace code at all that sets
> _DRM_WRITE_COMBINING in DRM_IOCTL_ADD_MAP with appropriate alignment
> and needs the MTRR, for which the drm driver doesn't already add the
> MTRR?
>
> --Andy

From memory, even on pat system we need mtrr for VRAM is PCI BAR. We
cover it with a write combine MTRR. The whole ioctl is use by some ddx
or maybe even directly the XServer to do this mtrr mess in userspace.

Sorry for the bad news, but that's what i remember on that front
thought i would need to read all the code again.

Cheers,
Jerome

^ permalink raw reply

* Re: [PATCH 3/7] drm: Update drm_addmap and drm_mmap to use PAT WC instead of MTRRs
From: Andy Lutomirski @ 2013-05-06 23:39 UTC (permalink / raw)
  To: Jerome Glisse; +Cc: linux-kernel, dri-devel, linux-fbdev
In-Reply-To: <CAH3drwYSZVrM4uWwFAxD+c0n1Q9i-et=Mwbk253E+cd+BtW9yw@mail.gmail.com>

On Mon, May 6, 2013 at 4:04 PM, Jerome Glisse <j.glisse@gmail.com> wrote:
> On Mon, May 6, 2013 at 5:22 PM, Andy Lutomirski <luto@amacapital.net> wrote:
>> On Fri, May 3, 2013 at 4:00 PM, Andy Lutomirski <luto@amacapital.net> wrote:
>>> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
>>> ---
>>>
>>> This needs careful review.  I don't really know what this code does, nor
>>> do I have the hardware.  (I don't understand AGP and the associated
>>> caching implications.)
>>
>> This patch is wrong (I didn't update the matching mtrr_del), and I'm
>> reworking this whole series.  But I may need some help on this one:
>> why is the mtrr handle of a map (whatever a map is) exported to
>> userspace via the ADD_MAP and GET_MAP ioctls?  What (if anything) is
>> userspace supposed to do with it?  Do I need to return a valid MTRR
>> register number?  Is there any userspace code at all that sets
>> _DRM_WRITE_COMBINING in DRM_IOCTL_ADD_MAP with appropriate alignment
>> and needs the MTRR, for which the drm driver doesn't already add the
>> MTRR?
>>
>> --Andy
>
> From memory, even on pat system we need mtrr for VRAM is PCI BAR. We
> cover it with a write combine MTRR. The whole ioctl is use by some ddx
> or maybe even directly the XServer to do this mtrr mess in userspace.

Egads!  So we have a _DRM_WRITE_COMBINING flag, which will continue to
work fine, but almost nothing uses it.

I'm amazed this stuff works in the current code, though.  Apparently
the memory type (WC or UC) of a drm mapping is determined by the mtrr
the driver set, but if one part of the BAR is textures or the
framebuffer and another part is an outgoing command ring, won't one of
them end up with the wrong memory type?

I'd really hate to have to track fake mtrrs in the drm core to emulate
real mtrrs.

>
> Sorry for the bad news, but that's what i remember on that front
> thought i would need to read all the code again.

On the bright side, in the entire 2005 monolithic xorg tarball, the
only thing that looks at the mtrr exported to userspace appears to be
dritests.

--Andy

^ permalink raw reply

* Re: [PATCH 3/7] drm: Update drm_addmap and drm_mmap to use PAT WC instead of MTRRs
From: Dave Airlie @ 2013-05-07  3:09 UTC (permalink / raw)
  To: Andy Lutomirski; +Cc: Jerome Glisse, linux-kernel, dri-devel, linux-fbdev
In-Reply-To: <CALCETrXO7OVxjw5nJ+HrBP7yAoAXk14w1cMbWBC4ZdBmZ6-3JQ@mail.gmail.com>

>>
>> From memory, even on pat system we need mtrr for VRAM is PCI BAR. We
>> cover it with a write combine MTRR. The whole ioctl is use by some ddx
>> or maybe even directly the XServer to do this mtrr mess in userspace.
>
> Egads!  So we have a _DRM_WRITE_COMBINING flag, which will continue to
> work fine, but almost nothing uses it.
>
> I'm amazed this stuff works in the current code, though.  Apparently
> the memory type (WC or UC) of a drm mapping is determined by the mtrr
> the driver set, but if one part of the BAR is textures or the
> framebuffer and another part is an outgoing command ring, won't one of
> them end up with the wrong memory type?

Nobody sane puts the command ring in VRAM.

Dave.

^ permalink raw reply

* Re: [PATCH 3/7] drm: Update drm_addmap and drm_mmap to use PAT WC instead of MTRRs
From: Alex Deucher @ 2013-05-07 14:08 UTC (permalink / raw)
  To: Andy Lutomirski; +Cc: Jerome Glisse, linux-fbdev, linux-kernel, dri-devel
In-Reply-To: <CALCETrXO7OVxjw5nJ+HrBP7yAoAXk14w1cMbWBC4ZdBmZ6-3JQ@mail.gmail.com>

On Mon, May 6, 2013 at 7:39 PM, Andy Lutomirski <luto@amacapital.net> wrote:
> On Mon, May 6, 2013 at 4:04 PM, Jerome Glisse <j.glisse@gmail.com> wrote:
>> On Mon, May 6, 2013 at 5:22 PM, Andy Lutomirski <luto@amacapital.net> wrote:
>>> On Fri, May 3, 2013 at 4:00 PM, Andy Lutomirski <luto@amacapital.net> wrote:
>>>> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
>>>> ---
>>>>
>>>> This needs careful review.  I don't really know what this code does, nor
>>>> do I have the hardware.  (I don't understand AGP and the associated
>>>> caching implications.)
>>>
>>> This patch is wrong (I didn't update the matching mtrr_del), and I'm
>>> reworking this whole series.  But I may need some help on this one:
>>> why is the mtrr handle of a map (whatever a map is) exported to
>>> userspace via the ADD_MAP and GET_MAP ioctls?  What (if anything) is
>>> userspace supposed to do with it?  Do I need to return a valid MTRR
>>> register number?  Is there any userspace code at all that sets
>>> _DRM_WRITE_COMBINING in DRM_IOCTL_ADD_MAP with appropriate alignment
>>> and needs the MTRR, for which the drm driver doesn't already add the
>>> MTRR?
>>>
>>> --Andy
>>
>> From memory, even on pat system we need mtrr for VRAM is PCI BAR. We
>> cover it with a write combine MTRR. The whole ioctl is use by some ddx
>> or maybe even directly the XServer to do this mtrr mess in userspace.
>
> Egads!  So we have a _DRM_WRITE_COMBINING flag, which will continue to
> work fine, but almost nothing uses it.
>
> I'm amazed this stuff works in the current code, though.  Apparently
> the memory type (WC or UC) of a drm mapping is determined by the mtrr
> the driver set, but if one part of the BAR is textures or the
> framebuffer and another part is an outgoing command ring, won't one of
> them end up with the wrong memory type?

A lot of old chips used to put the registers and framebuffer in the
same BAR.  IIRC, the xserver and later libpciaccess had workarounds to
deal with this.

Alex

^ permalink raw reply

* Re: [PATCH 3/7] drm: Update drm_addmap and drm_mmap to use PAT WC instead of MTRRs
From: Andy Lutomirski @ 2013-05-07 16:45 UTC (permalink / raw)
  To: Alex Deucher; +Cc: Jerome Glisse, linux-fbdev, linux-kernel, dri-devel
In-Reply-To: <CADnq5_OJF5NB8r3Pj5E9VaiBLMTyHtERC4N4X0yYLwXQLqqrmw@mail.gmail.com>

On Tue, May 7, 2013 at 7:08 AM, Alex Deucher <alexdeucher@gmail.com> wrote:
> On Mon, May 6, 2013 at 7:39 PM, Andy Lutomirski <luto@amacapital.net> wrote:
>> On Mon, May 6, 2013 at 4:04 PM, Jerome Glisse <j.glisse@gmail.com> wrote:
>>> On Mon, May 6, 2013 at 5:22 PM, Andy Lutomirski <luto@amacapital.net> wrote:
>>>> On Fri, May 3, 2013 at 4:00 PM, Andy Lutomirski <luto@amacapital.net> wrote:
>>>>> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
>>>>> ---
>>>>>
>>>>> This needs careful review.  I don't really know what this code does, nor
>>>>> do I have the hardware.  (I don't understand AGP and the associated
>>>>> caching implications.)
>>>>
>>>> This patch is wrong (I didn't update the matching mtrr_del), and I'm
>>>> reworking this whole series.  But I may need some help on this one:
>>>> why is the mtrr handle of a map (whatever a map is) exported to
>>>> userspace via the ADD_MAP and GET_MAP ioctls?  What (if anything) is
>>>> userspace supposed to do with it?  Do I need to return a valid MTRR
>>>> register number?  Is there any userspace code at all that sets
>>>> _DRM_WRITE_COMBINING in DRM_IOCTL_ADD_MAP with appropriate alignment
>>>> and needs the MTRR, for which the drm driver doesn't already add the
>>>> MTRR?
>>>>
>>>> --Andy
>>>
>>> From memory, even on pat system we need mtrr for VRAM is PCI BAR. We
>>> cover it with a write combine MTRR. The whole ioctl is use by some ddx
>>> or maybe even directly the XServer to do this mtrr mess in userspace.
>>
>> Egads!  So we have a _DRM_WRITE_COMBINING flag, which will continue to
>> work fine, but almost nothing uses it.
>>
>> I'm amazed this stuff works in the current code, though.  Apparently
>> the memory type (WC or UC) of a drm mapping is determined by the mtrr
>> the driver set, but if one part of the BAR is textures or the
>> framebuffer and another part is an outgoing command ring, won't one of
>> them end up with the wrong memory type?
>
> A lot of old chips used to put the registers and framebuffer in the
> same BAR.  IIRC, the xserver and later libpciaccess had workarounds to
> deal with this.

I think I read the code wrong (so my patch is garbage).  Maybe there's
actually no problem -- if DRM_AGP and DRM_FRAME_BUFFER are always WC,
DRM_REGISTERS is only WC if explicitly requested, and DRM_SHM is
always WB, so everything should be covered.

Anything using libpciaccess ought to be unaffected by my changes -- I
don't want to change /proc/mtrr or the sysfs stuff.  The only possible
issue is if there's a memtype conflict, but that's nothing new.

--Andy

^ permalink raw reply

* Re: [PATCH V2] video: implement a simple framebuffer driver
From: Andrew Morton @ 2013-05-07 21:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1956593.M6NmITdEKh@avalon>


We don't seem to have a well-defined path to travel here, and I don't
get the feeling that anyone has signed up to walk it?

So I'm inclined to merge Stephen's patch as-is into 3.10.  It's pretty
simple and standalone.  Any strenuous objections?

BTW, Olof told me off-list that this patch is a "critical piece" for
running mainline Linux on ARM Chromebooks.  That was important
information - more important than anything else we were told about this
patch!

So Stephen, could I please have a new changelog for this patch which
explains this application, and any other interesting/important things
which were left out?  Quickly, please.




From: Stephen Warren <swarren@wwwdotorg.org>
Subject: drivers/video: implement a simple framebuffer driver

A simple frame-buffer describes a raw memory region that may be rendered
to, with the assumption that the display hardware has already been set up
to scan out from that buffer.

This is useful in cases where a bootloader exists and has set up the
display hardware, but a Linux driver doesn't yet exist for the display
hardware.

[akpm@linux-foundation.org: make simplefb_formats[] static]
Signed-off-by: Stephen Warren <swarren@wwwdotorg.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Olof Johansson <olof@lixom.net>
Cc: Rob Clark <robclark@gmail.com>
Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Tomasz Figa <tomasz.figa@gmail.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 Documentation/devicetree/bindings/video/simple-framebuffer.txt |   25 +
 drivers/video/Kconfig                                          |   17 
 drivers/video/Makefile                                         |    1 
 drivers/video/simplefb.c                                       |  234 ++++++++++
 4 files changed, 277 insertions(+)

diff -puN /dev/null Documentation/devicetree/bindings/video/simple-framebuffer.txt
--- /dev/null
+++ a/Documentation/devicetree/bindings/video/simple-framebuffer.txt
@@ -0,0 +1,25 @@
+Simple Framebuffer
+
+A simple frame-buffer describes a raw memory region that may be rendered to,
+with the assumption that the display hardware has already been set up to scan
+out from that buffer.
+
+Required properties:
+- compatible: "simple-framebuffer"
+- reg: Should contain the location and size of the framebuffer memory.
+- width: The width of the framebuffer in pixels.
+- height: The height of the framebuffer in pixels.
+- stride: The number of bytes in each line of the framebuffer.
+- format: The format of the framebuffer surface. Valid values are:
+  - r5g6b5 (16-bit pixels, d[15:11]=r, d[10:5]=g, d[4:0]=b).
+
+Example:
+
+	framebuffer {
+		compatible = "simple-framebuffer";
+		reg = <0x1d385000 (1600 * 1200 * 2)>;
+		width = <1600>;
+		height = <1200>;
+		stride = <(1600 * 2)>;
+		format = "r5g6b5";
+	};
diff -puN drivers/video/Kconfig~drivers-video-implement-a-simple-framebuffer-driver drivers/video/Kconfig
--- a/drivers/video/Kconfig~drivers-video-implement-a-simple-framebuffer-driver
+++ a/drivers/video/Kconfig
@@ -2453,6 +2453,23 @@ config FB_HYPERV
 	help
 	  This framebuffer driver supports Microsoft Hyper-V Synthetic Video.
 
+config FB_SIMPLE
+	bool "Simple framebuffer support"
+	depends on (FB = y) && OF
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  Say Y if you want support for a simple frame-buffer.
+
+	  This driver assumes that the display hardware has been initialized
+	  before the kernel boots, and the kernel will simply render to the
+	  pre-allocated frame buffer surface.
+
+	  Configuration re: surface address, size, and format must be provided
+	  through device tree, or potentially plain old platform data in the
+	  future.
+
 source "drivers/video/omap/Kconfig"
 source "drivers/video/omap2/Kconfig"
 source "drivers/video/exynos/Kconfig"
diff -puN drivers/video/Makefile~drivers-video-implement-a-simple-framebuffer-driver drivers/video/Makefile
--- a/drivers/video/Makefile~drivers-video-implement-a-simple-framebuffer-driver
+++ a/drivers/video/Makefile
@@ -166,6 +166,7 @@ obj-$(CONFIG_FB_MX3)		  += mx3fb.o
 obj-$(CONFIG_FB_DA8XX)		  += da8xx-fb.o
 obj-$(CONFIG_FB_MXS)		  += mxsfb.o
 obj-$(CONFIG_FB_SSD1307)	  += ssd1307fb.o
+obj-$(CONFIG_FB_SIMPLE)           += simplefb.o
 
 # the test framebuffer is last
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
diff -puN /dev/null drivers/video/simplefb.c
--- /dev/null
+++ a/drivers/video/simplefb.c
@@ -0,0 +1,234 @@
+/*
+ * Simplest possible simple frame-buffer driver, as a platform device
+ *
+ * Copyright (c) 2013, Stephen Warren
+ *
+ * Based on q40fb.c, which was:
+ * Copyright (C) 2001 Richard Zidlicky <rz@linux-m68k.org>
+ *
+ * Also based on offb.c, which was:
+ * Copyright (C) 1997 Geert Uytterhoeven
+ * Copyright (C) 1996 Paul Mackerras
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+static struct fb_fix_screeninfo simplefb_fix = {
+	.id		= "simple",
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_TRUECOLOR,
+	.accel		= FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo simplefb_var = {
+	.height		= -1,
+	.width		= -1,
+	.activate	= FB_ACTIVATE_NOW,
+	.vmode		= FB_VMODE_NONINTERLACED,
+};
+
+static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			      u_int transp, struct fb_info *info)
+{
+	u32 *pal = info->pseudo_palette;
+	u32 cr = red >> (16 - info->var.red.length);
+	u32 cg = green >> (16 - info->var.green.length);
+	u32 cb = blue >> (16 - info->var.blue.length);
+	u32 value;
+
+	if (regno >= 16)
+		return -EINVAL;
+
+	value = (cr << info->var.red.offset) |
+		(cg << info->var.green.offset) |
+		(cb << info->var.blue.offset);
+	if (info->var.transp.length > 0) {
+		u32 mask = (1 << info->var.transp.length) - 1;
+		mask <<= info->var.transp.offset;
+		value |= mask;
+	}
+	pal[regno] = value;
+
+	return 0;
+}
+
+static struct fb_ops simplefb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_setcolreg	= simplefb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+struct simplefb_format {
+	const char *name;
+	u32 bits_per_pixel;
+	struct fb_bitfield red;
+	struct fb_bitfield green;
+	struct fb_bitfield blue;
+	struct fb_bitfield transp;
+};
+
+static struct simplefb_format simplefb_formats[] = {
+	{ "r5g6b5", 16, {11, 5}, {5, 6}, {0, 5}, {0, 0} },
+};
+
+struct simplefb_params {
+	u32 width;
+	u32 height;
+	u32 stride;
+	struct simplefb_format *format;
+};
+
+static int simplefb_parse_dt(struct platform_device *pdev,
+			   struct simplefb_params *params)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int ret;
+	const char *format;
+	int i;
+
+	ret = of_property_read_u32(np, "width", &params->width);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't parse width property\n");
+		return ret;
+	}
+
+	ret = of_property_read_u32(np, "height", &params->height);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't parse height property\n");
+		return ret;
+	}
+
+	ret = of_property_read_u32(np, "stride", &params->stride);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't parse stride property\n");
+		return ret;
+	}
+
+	ret = of_property_read_string(np, "format", &format);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't parse format property\n");
+		return ret;
+	}
+	params->format = NULL;
+	for (i = 0; i < ARRAY_SIZE(simplefb_formats); i++) {
+		if (strcmp(format, simplefb_formats[i].name))
+			continue;
+		params->format = &simplefb_formats[i];
+		break;
+	}
+	if (!params->format) {
+		dev_err(&pdev->dev, "Invalid format value\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int simplefb_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct simplefb_params params;
+	struct fb_info *info;
+	struct resource *mem;
+
+	if (fb_get_options("simplefb", NULL))
+		return -ENODEV;
+
+	ret = simplefb_parse_dt(pdev, &params);
+	if (ret)
+		return ret;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "No memory resource\n");
+		return -EINVAL;
+	}
+
+	info = framebuffer_alloc(sizeof(u32) * 16, &pdev->dev);
+	if (!info)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, info);
+
+	info->fix = simplefb_fix;
+	info->fix.smem_start = mem->start;
+	info->fix.smem_len = resource_size(mem);
+	info->fix.line_length = params.stride;
+
+	info->var = simplefb_var;
+	info->var.xres = params.width;
+	info->var.yres = params.height;
+	info->var.xres_virtual = params.width;
+	info->var.yres_virtual = params.height;
+	info->var.bits_per_pixel = params.format->bits_per_pixel;
+	info->var.red = params.format->red;
+	info->var.green = params.format->green;
+	info->var.blue = params.format->blue;
+	info->var.transp = params.format->transp;
+
+	info->fbops = &simplefb_ops;
+	info->flags = FBINFO_DEFAULT;
+	info->screen_base = devm_ioremap(&pdev->dev, info->fix.smem_start,
+					 info->fix.smem_len);
+	if (!info->screen_base) {
+		framebuffer_release(info);
+		return -ENODEV;
+	}
+	info->pseudo_palette = (void *)(info + 1);
+
+	ret = register_framebuffer(info);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret);
+		framebuffer_release(info);
+		return ret;
+	}
+
+	dev_info(&pdev->dev, "fb%d: simplefb registered!\n", info->node);
+
+	return 0;
+}
+
+static int simplefb_remove(struct platform_device *pdev)
+{
+	struct fb_info *info = platform_get_drvdata(pdev);
+
+	unregister_framebuffer(info);
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static const struct of_device_id simplefb_of_match[] = {
+	{ .compatible = "simple-framebuffer", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, simplefb_of_match);
+
+static struct platform_driver simplefb_driver = {
+	.driver = {
+		.name = "simple-framebuffer",
+		.owner = THIS_MODULE,
+		.of_match_table = simplefb_of_match,
+	},
+	.probe = simplefb_probe,
+	.remove = simplefb_remove,
+};
+module_platform_driver(simplefb_driver);
+
+MODULE_AUTHOR("Stephen Warren <swarren@wwwdotorg.org>");
+MODULE_DESCRIPTION("Simple framebuffer driver");
+MODULE_LICENSE("GPL v2");
_


^ permalink raw reply

* Re: [PATCH V2] video: implement a simple framebuffer driver
From: Stephen Warren @ 2013-05-08  2:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130507143338.79b3d893fcdc3bd79fbe9a57@linux-foundation.org>

On 05/07/2013 03:33 PM, Andrew Morton wrote:
> 
> We don't seem to have a well-defined path to travel here, and I don't
> get the feeling that anyone has signed up to walk it?
> 
> So I'm inclined to merge Stephen's patch as-is into 3.10.  It's pretty
> simple and standalone.  Any strenuous objections?
> 
> BTW, Olof told me off-list that this patch is a "critical piece" for
> running mainline Linux on ARM Chromebooks.  That was important
> information - more important than anything else we were told about this
> patch!
> 
> So Stephen, could I please have a new changelog for this patch which
> explains this application, and any other interesting/important things
> which were left out?  Quickly, please.

OK, how about the version below:

----------
Subject: drivers/video: implement a simple framebuffer driver

A simple frame-buffer describes a raw memory region that may be rendered
to, with the assumption that the display hardware has already been set
up to scan out from that buffer.

This is useful in cases where a bootloader exists and has set up the
display hardware, but a Linux driver doesn't yet exist for the display
hardware.

Examples use-cases include:

* The built-in LCD panels on the Samsung ARM chromebook, and Tegra
devices, and likely many other ARM or embedded systems. These cannot yet
be supported using a full graphics driver, since the panel control
should be provided by the CDF (Common Display Framework), which has been
stuck in design/review for quite some time. One could support these
panels using custom SoC-specific code, but there is a desire to use
common infra-structure rather than having each SoC vendor invent their
own code, hence the desire to wait for CDF.

* Hardware for which a full graphics driver is not yet available, and
the path to obtain one upstream isn't yet clear. For example, the
Raspberry Pi.

* Any hardware in early stages of upstreaming, before a full graphics
driver has been tackled. This driver can provide a graphical boot
console (even full X support) much earlier in the upstreaming process,
thus making new SoC or board support more generally useful earlier.
----------

I assume you can just edit the patch you have and don't need me to
resend with the adjusted description.

^ permalink raw reply

* Re: [PATCHv2 0/2] Add support for the Solomon SSD1306 OLED Controller
From: Tomi Valkeinen @ 2013-05-08  6:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1366624555-5616-1-git-send-email-maxime.ripard@free-electrons.com>

[-- Attachment #1: Type: text/plain, Size: 1078 bytes --]

On 22/04/13 12:55, Maxime Ripard wrote:
> Hi,
> 
> This patchset adds the needed bits to the ssd1307fb driver to support the
> very similar Solomon SSD1306 controller.
> 
> Since the SSD1307 has been replaced by the SSD1306 in the latest CFA-10036
> production samples, we also need to change the device tree accordingly.
> 
> Thanks,
> Maxime
> 
> Changes from v1:
>   - Fix style errors
> 
> Maxime Ripard (2):
>   video: ssd1307fb: Add support for SSD1306 OLED controller
>   ARM: dts: cfa10036: Change the OLED display to SSD1306
> 
>  .../devicetree/bindings/video/ssd1307fb.txt        |   10 +-
>  arch/arm/boot/dts/imx28-cfa10036.dts               |   14 +-
>  arch/arm/boot/dts/imx28-cfa10049.dts               |    4 +-
>  drivers/video/ssd1307fb.c                          |  273 +++++++++++++++-----
>  4 files changed, 216 insertions(+), 85 deletions(-)

I've taken the first patch, "video: ssd1307fb: Add support for SSD1306
OLED controller" into fbdev 3.11 branch. The dts changes should
preferably go through arch tree.

 Tomi




[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply

* Re: [PATCH 0/4] drivers: video: Optimisations for the ssd1307fb driver
From: Tomi Valkeinen @ 2013-05-08  6:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1366624945-5708-1-git-send-email-maxime.ripard@free-electrons.com>

On 22/04/13 13:02, Maxime Ripard wrote:
> Hi everyone,
> 
> This is a patchset to improve significantly (by an order of magnitude)
> the refreshing time of the SSD1306 and SSD1307.
> 
> We do so by sending the pixels by batches, instead of 8 at a time,
> combined with some additionnal features found on these controllers
> that allows to send a whole screen content at once.
> 
> This obviously removes the tearing effect that was previously seen
> with these controllers.
> 
> This patchset depends on the "Add support for the Solomon SSD1306 OLED
> Controller" I sent previously.
> 
> Thanks,
> Maxime
> 
> Maxime Ripard (4):
>   ARM: cfa10036: dt: Change i2c0 clock frequency
>   ssd1307fb: Rework the communication functions
>   ssd1307fb: Speed up the communication with the controller
>   ssd1307fb: Make use of horizontal addressing mode
> 
>  arch/arm/boot/dts/imx28-cfa10036.dts |    1 +
>  drivers/video/ssd1307fb.c            |  123 ++++++++++++++++++++++++----------
>  2 files changed, 89 insertions(+), 35 deletions(-)
> 

I've taken the patches 2-4 into fbdev 3.11 branch. The first patch "ARM:
cfa10036: dt: Change i2c0 clock frequency" should preferably go through
arch tree.

 Tomi


^ permalink raw reply

* dringender Vorschlag
From: John P. Goldman @ 2013-05-08  8:46 UTC (permalink / raw)
  To: linux-fbdev



Entschuldigungen für kommen in Ihre Privatsphäre! Ich bin Rechtsanwalt
Werner Erich Zeller; Ich habe einen meiner einflussreichen und
wohlhabenden Kunden zum Tode; und er hatte eine sehr geheime und private
Investitionen von €15,000,000.00 bei einer privaten Bank in Großbritannien
hier zu Lebzeiten. Diese Investition wurde ohne einen deklarierten
nächsten Angehörigen und begünstigte. Jetzt brauche ich Sie arbeiten mit
mir als mein Partner zu erholen und zu je 50 % Aktienfonds. Alle Dokumente
werden rechtlich beantragt und beschafft, und in 5 Werktage, wird diese
Transaktion auftreten. Aber ich brauche einen ernsten, treuen und
glaubwürdigen Partner.

Bitte senden Sie mir eine vertrauliche Antwort, wenn Sie denken, Sie
vertraut werden können und sind von den Qualitäten! Ich warte auf Ihre
schnelle Antwort.

Werner Erich Zeller (Rechtsanwalt)
Rufen Sie + 44-702-409-0820 (Office)

^ permalink raw reply

* Re: [PATCH 2/2] ARM: dts: cfa10036: Change the OLED display to SSD1306
From: Shawn Guo @ 2013-05-08 14:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1366624555-5616-3-git-send-email-maxime.ripard@free-electrons.com>

On Mon, Apr 22, 2013 at 11:55:55AM +0200, Maxime Ripard wrote:
> The SSD1307 was used in an early prototype that will never get
> distributed. The final board now has a SSD1306 instead, that has its own
> power generation unit and thus doesn't need any PWM. The panel attached
> to it also changed.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Applied, thanks.


^ permalink raw reply

* Re: [PATCH 1/4] ARM: cfa10036: dt: Change i2c0 clock frequency
From: Shawn Guo @ 2013-05-08 14:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1366624945-5708-2-git-send-email-maxime.ripard@free-electrons.com>

On Mon, Apr 22, 2013 at 12:02:22PM +0200, Maxime Ripard wrote:
> The OLED display can work faster. Change the i2c controller clock
> frequency to remove the tearing effect that can be seen on the display.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Applied, thanks.


^ permalink raw reply

* [PATCH v5, part3 07/15] mm, acornfb: use free_reserved_area() to simplify code
From: Jiang Liu @ 2013-05-08 15:17 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Jiang Liu, David Rientjes, Wen Congyang, Mel Gorman, Minchan Kim,
	KAMEZAWA Hiroyuki, Michal Hocko, James Bottomley, Sergei Shtylyov,
	David Howells, Mark Salter, Jianguo Wu, linux-mm, linux-arch,
	linux-kernel, Florian Tobias Schandinat, linux-fbdev
In-Reply-To: <1368026235-5976-1-git-send-email-jiang.liu@huawei.com>

Use common help function free_reserved_area() to simplify code.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: linux-fbdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/video/acornfb.c |   28 ++--------------------------
 1 file changed, 2 insertions(+), 26 deletions(-)

diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 6488a73..344f2bb 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -1188,32 +1188,8 @@ static int acornfb_detect_monitortype(void)
 static inline void
 free_unused_pages(unsigned int virtual_start, unsigned int virtual_end)
 {
-	int mb_freed = 0;
-
-	/*
-	 * Align addresses
-	 */
-	virtual_start = PAGE_ALIGN(virtual_start);
-	virtual_end = PAGE_ALIGN(virtual_end);
-
-	while (virtual_start < virtual_end) {
-		struct page *page;
-
-		/*
-		 * Clear page reserved bit,
-		 * set count to 1, and free
-		 * the page.
-		 */
-		page = virt_to_page(virtual_start);
-		ClearPageReserved(page);
-		init_page_count(page);
-		free_page(virtual_start);
-
-		virtual_start += PAGE_SIZE;
-		mb_freed += PAGE_SIZE / 1024;
-	}
-
-	printk("acornfb: freed %dK memory\n", mb_freed);
+	free_reserved_area(virtual_start, PAGE_ALIGN(virtual_end),
+			   -1, "acornfb");
 }
 
 static int acornfb_probe(struct platform_device *dev)
-- 
1.7.9.5


^ permalink raw reply related

* Re: [PATCH V2] video: implement a simple framebuffer driver
From: Olof Johansson @ 2013-05-08 19:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5189BA36.9000105@wwwdotorg.org>

On Tue, May 7, 2013 at 7:36 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 05/07/2013 03:33 PM, Andrew Morton wrote:
>>
>> We don't seem to have a well-defined path to travel here, and I don't
>> get the feeling that anyone has signed up to walk it?
>>
>> So I'm inclined to merge Stephen's patch as-is into 3.10.  It's pretty
>> simple and standalone.  Any strenuous objections?
>>
>> BTW, Olof told me off-list that this patch is a "critical piece" for
>> running mainline Linux on ARM Chromebooks.  That was important
>> information - more important than anything else we were told about this
>> patch!
>>
>> So Stephen, could I please have a new changelog for this patch which
>> explains this application, and any other interesting/important things
>> which were left out?  Quickly, please.
>
> OK, how about the version below:
>
> ----------
> Subject: drivers/video: implement a simple framebuffer driver
>
> A simple frame-buffer describes a raw memory region that may be rendered
> to, with the assumption that the display hardware has already been set
> up to scan out from that buffer.
>
> This is useful in cases where a bootloader exists and has set up the
> display hardware, but a Linux driver doesn't yet exist for the display
> hardware.
>
> Examples use-cases include:
>
> * The built-in LCD panels on the Samsung ARM chromebook, and Tegra
> devices, and likely many other ARM or embedded systems. These cannot yet
> be supported using a full graphics driver, since the panel control
> should be provided by the CDF (Common Display Framework), which has been
> stuck in design/review for quite some time. One could support these
> panels using custom SoC-specific code, but there is a desire to use
> common infra-structure rather than having each SoC vendor invent their
> own code, hence the desire to wait for CDF.
>
> * Hardware for which a full graphics driver is not yet available, and
> the path to obtain one upstream isn't yet clear. For example, the
> Raspberry Pi.
>
> * Any hardware in early stages of upstreaming, before a full graphics
> driver has been tackled. This driver can provide a graphical boot
> console (even full X support) much earlier in the upstreaming process,
> thus making new SoC or board support more generally useful earlier.
> ----------
>
> I assume you can just edit the patch you have and don't need me to
> resend with the adjusted description.

Oh, looks like it never got a:

Acked-by: Olof Johansson <olof@lixom.net>

Either. Feel free to add, Andrew.


-Olof

^ permalink raw reply

* Re: [PATCH V2] video: implement a simple framebuffer driver
From: Rob Landley @ 2013-05-08 20:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5189BA36.9000105@wwwdotorg.org>

On 05/07/2013 09:36:38 PM, Stephen Warren wrote:
> On 05/07/2013 03:33 PM, Andrew Morton wrote:
...
> Subject: drivers/video: implement a simple framebuffer driver
> 
> A simple frame-buffer describes a raw memory region that may be  
> rendered
> to, with the assumption that the display hardware has already been set
> up to scan out from that buffer.
> 
> This is useful in cases where a bootloader exists and has set up the
> display hardware, but a Linux driver doesn't yet exist for the display
> hardware.
> 
> Examples use-cases include:

Virtual environments such as QEMU.

Rob

^ permalink raw reply

* [RFC/PATCH v2 0/8] Clean up write-combining MTRR addition
From: Andy Lutomirski @ 2013-05-09 19:46 UTC (permalink / raw)
  To: linux-kernel, dri-devel, linux-fbdev
  Cc: Daniel Vetter, Jerome Glisse, Alex Deucher, Dave Airlie,
	Andy Lutomirski

A fair number of drivers (mostly graphics) add write-combining MTRRs.
Most ignore errors and most add the MTRR even on PAT systems which don't
need to use MTRRs.

This series adds new functions arch_phys_wc_{add,del} that, on PAT-less
x86 systems with MTRRs, add MTRRs and report errors, and that do nothing
otherwise.  (Other architectures, if any, with a similar mechanism could
implement them.)

I've only tested the radeon driver, since I don't have test hardware
easily available for the other drivers.

Benefits include:
 - Simpler code
 - No more complaints about MTRR conflict warnings on PAT systems
 - Eventual unexporting of the MTRR API?

This series eliminates about half of the mtrr_add calls in drivers/.

Changes from v1:
 - Helpers renamed
 - Lots of bugs fixed

The series is also at:
https://git.kernel.org/cgit/linux/kernel/git/luto/linux.git/log/?h=mtrr_cleanup/rfc_v2

Andy Lutomirski (8):
  Add arch_phys_wc_{add,del} to manipulate WC MTRRs if needed
  drm (ast,cirrus,mgag200,nouveau,savage,vmwgfx): Remove
    drm_mtrr_{add,del}
  drm: Update drm_addmap and drm_mmap to use PAT WC instead of MTRRs
  drm,agpgart: Use pgprot_writecombine for AGP maps and make the MTRR
    optional
  i915: Use arch_phys_wc_{add,del}
  radeon: Switch to arch_phys_wc_add and add a missing ..._del
  uvesafb: Clean up MTRR code
  drm: Remove mtrr_add and mtrr_del fallback hack for non-MTRR systems

 Documentation/fb/uvesafb.txt           | 16 +++-----
 arch/x86/include/asm/io.h              |  7 ++++
 arch/x86/include/asm/mtrr.h            |  5 ++-
 arch/x86/kernel/cpu/mtrr/main.c        | 48 +++++++++++++++++++++++
 drivers/char/agp/frontend.c            |  8 ++--
 drivers/gpu/drm/ast/ast_ttm.c          | 13 ++-----
 drivers/gpu/drm/cirrus/cirrus_ttm.c    | 15 ++------
 drivers/gpu/drm/drm_bufs.c             | 17 +++++----
 drivers/gpu/drm/drm_pci.c              |  8 ++--
 drivers/gpu/drm/drm_stub.c             | 10 +----
 drivers/gpu/drm/drm_vm.c               | 22 +++++------
 drivers/gpu/drm/i915/i915_dma.c        | 44 +++------------------
 drivers/gpu/drm/mgag200/mgag200_ttm.c  | 14 ++-----
 drivers/gpu/drm/nouveau/nouveau_ttm.c  | 13 ++-----
 drivers/gpu/drm/radeon/radeon_object.c |  5 ++-
 drivers/gpu/drm/savage/savage_bci.c    | 43 ++++++++-------------
 drivers/gpu/drm/savage/savage_drv.h    |  5 +--
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c    | 10 ++---
 drivers/video/uvesafb.c                | 70 +++++++++-------------------------
 include/drm/drmP.h                     | 34 +----------------
 include/drm/drm_os_linux.h             | 16 --------
 include/linux/io.h                     | 25 ++++++++++++
 include/video/uvesafb.h                |  1 +
 23 files changed, 181 insertions(+), 268 deletions(-)

-- 
1.8.1.4


^ permalink raw reply

* [RFC/PATCH v2 1/8] Add arch_phys_wc_{add,del} to manipulate WC MTRRs if needed
From: Andy Lutomirski @ 2013-05-09 19:46 UTC (permalink / raw)
  To: linux-kernel, dri-devel, linux-fbdev
  Cc: Daniel Vetter, Jerome Glisse, Alex Deucher, Dave Airlie,
	Andy Lutomirski
In-Reply-To: <cover.1368128020.git.luto@amacapital.net>

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.) */
+
+	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


^ permalink raw reply related

* [RFC/PATCH v2 2/8] drm (ast,cirrus,mgag200,nouveau,savage,vmwgfx): Remove drm_mtrr_{add,del}
From: Andy Lutomirski @ 2013-05-09 19:46 UTC (permalink / raw)
  To: linux-kernel, dri-devel, linux-fbdev
  Cc: Daniel Vetter, Jerome Glisse, Alex Deucher, Dave Airlie,
	Andy Lutomirski
In-Reply-To: <cover.1368128020.git.luto@amacapital.net>

This replaces drm_mtrr_{add,del} with arch_phys_wc_{add,del}.  The
interface is simplified (because the base and size parameters to
drm_mtrr_del never did anything), and it no longer adds MTRRs on
systems that don't need them.

Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---
 drivers/gpu/drm/ast/ast_ttm.c         | 13 +++--------
 drivers/gpu/drm/cirrus/cirrus_ttm.c   | 15 ++++--------
 drivers/gpu/drm/mgag200/mgag200_ttm.c | 14 ++++--------
 drivers/gpu/drm/nouveau/nouveau_ttm.c | 13 ++++-------
 drivers/gpu/drm/savage/savage_bci.c   | 43 ++++++++++++-----------------------
 drivers/gpu/drm/savage/savage_drv.h   |  5 +---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c   | 10 ++++----
 include/drm/drmP.h                    | 29 -----------------------
 8 files changed, 35 insertions(+), 107 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_ttm.c b/drivers/gpu/drm/ast/ast_ttm.c
index 3602731..c4574fd 100644
--- a/drivers/gpu/drm/ast/ast_ttm.c
+++ b/drivers/gpu/drm/ast/ast_ttm.c
@@ -271,26 +271,19 @@ int ast_mm_init(struct ast_private *ast)
 		return ret;
 	}
 
-	ast->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 0),
-				    pci_resource_len(dev->pdev, 0),
-				    DRM_MTRR_WC);
+	ast->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
+					pci_resource_len(dev->pdev, 0));
 
 	return 0;
 }
 
 void ast_mm_fini(struct ast_private *ast)
 {
-	struct drm_device *dev = ast->dev;
 	ttm_bo_device_release(&ast->ttm.bdev);
 
 	ast_ttm_global_release(ast);
 
-	if (ast->fb_mtrr >= 0) {
-		drm_mtrr_del(ast->fb_mtrr,
-			     pci_resource_start(dev->pdev, 0),
-			     pci_resource_len(dev->pdev, 0), DRM_MTRR_WC);
-		ast->fb_mtrr = -1;
-	}
+	arch_phys_wc_del(ast->fb_mtrr);
 }
 
 void ast_ttm_placement(struct ast_bo *bo, int domain)
diff --git a/drivers/gpu/drm/cirrus/cirrus_ttm.c b/drivers/gpu/drm/cirrus/cirrus_ttm.c
index 1413a26..09f06d3 100644
--- a/drivers/gpu/drm/cirrus/cirrus_ttm.c
+++ b/drivers/gpu/drm/cirrus/cirrus_ttm.c
@@ -271,9 +271,8 @@ int cirrus_mm_init(struct cirrus_device *cirrus)
 		return ret;
 	}
 
-	cirrus->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 0),
-				    pci_resource_len(dev->pdev, 0),
-				    DRM_MTRR_WC);
+	cirrus->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
+					   pci_resource_len(dev->pdev, 0));
 
 	cirrus->mm_inited = true;
 	return 0;
@@ -281,8 +280,6 @@ int cirrus_mm_init(struct cirrus_device *cirrus)
 
 void cirrus_mm_fini(struct cirrus_device *cirrus)
 {
-	struct drm_device *dev = cirrus->dev;
-
 	if (!cirrus->mm_inited)
 		return;
 
@@ -290,12 +287,8 @@ void cirrus_mm_fini(struct cirrus_device *cirrus)
 
 	cirrus_ttm_global_release(cirrus);
 
-	if (cirrus->fb_mtrr >= 0) {
-		drm_mtrr_del(cirrus->fb_mtrr,
-			     pci_resource_start(dev->pdev, 0),
-			     pci_resource_len(dev->pdev, 0), DRM_MTRR_WC);
-		cirrus->fb_mtrr = -1;
-	}
+	arch_phys_wc_del(cirrus->fb_mtrr);
+	cirrus->fb_mtrr = 0;
 }
 
 void cirrus_ttm_placement(struct cirrus_bo *bo, int domain)
diff --git a/drivers/gpu/drm/mgag200/mgag200_ttm.c b/drivers/gpu/drm/mgag200/mgag200_ttm.c
index 8fc9d92..5c6f3c8 100644
--- a/drivers/gpu/drm/mgag200/mgag200_ttm.c
+++ b/drivers/gpu/drm/mgag200/mgag200_ttm.c
@@ -270,26 +270,20 @@ int mgag200_mm_init(struct mga_device *mdev)
 		return ret;
 	}
 
-	mdev->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 0),
-				    pci_resource_len(dev->pdev, 0),
-				    DRM_MTRR_WC);
+	mdev->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
+					 pci_resource_len(dev->pdev, 0));
 
 	return 0;
 }
 
 void mgag200_mm_fini(struct mga_device *mdev)
 {
-	struct drm_device *dev = mdev->dev;
 	ttm_bo_device_release(&mdev->ttm.bdev);
 
 	mgag200_ttm_global_release(mdev);
 
-	if (mdev->fb_mtrr >= 0) {
-		drm_mtrr_del(mdev->fb_mtrr,
-			     pci_resource_start(dev->pdev, 0),
-			     pci_resource_len(dev->pdev, 0), DRM_MTRR_WC);
-		mdev->fb_mtrr = -1;
-	}
+	arch_phys_wc_del(mdev->fb_mtrr);
+	mdev->fb_mtrr = 0;
 }
 
 void mgag200_ttm_placement(struct mgag200_bo *bo, int domain)
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c
index 9be9cb5..63fa6a5 100644
--- a/drivers/gpu/drm/nouveau/nouveau_ttm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c
@@ -377,9 +377,8 @@ nouveau_ttm_init(struct nouveau_drm *drm)
 		return ret;
 	}
 
-	drm->ttm.mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1),
-				     pci_resource_len(dev->pdev, 1),
-				     DRM_MTRR_WC);
+	drm->ttm.mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 1),
+					 pci_resource_len(dev->pdev, 1));
 
 	/* GART init */
 	if (drm->agp.stat != ENABLED) {
@@ -414,10 +413,6 @@ nouveau_ttm_fini(struct nouveau_drm *drm)
 
 	nouveau_ttm_global_release(drm);
 
-	if (drm->ttm.mtrr >= 0) {
-		drm_mtrr_del(drm->ttm.mtrr,
-			     pci_resource_start(drm->dev->pdev, 1),
-			     pci_resource_len(drm->dev->pdev, 1), DRM_MTRR_WC);
-		drm->ttm.mtrr = -1;
-	}
+	arch_phys_wc_del(drm->ttm.mtrr);
+	drm->ttm.mtrr = 0;
 }
diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c
index b55c1d6..bd6b2cf 100644
--- a/drivers/gpu/drm/savage/savage_bci.c
+++ b/drivers/gpu/drm/savage/savage_bci.c
@@ -570,9 +570,6 @@ int savage_driver_firstopen(struct drm_device *dev)
 	unsigned int fb_rsrc, aper_rsrc;
 	int ret = 0;
 
-	dev_priv->mtrr[0].handle = -1;
-	dev_priv->mtrr[1].handle = -1;
-	dev_priv->mtrr[2].handle = -1;
 	if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
 		fb_rsrc = 0;
 		fb_base = pci_resource_start(dev->pdev, 0);
@@ -584,21 +581,14 @@ int savage_driver_firstopen(struct drm_device *dev)
 		if (pci_resource_len(dev->pdev, 0) = 0x08000000) {
 			/* Don't make MMIO write-cobining! We need 3
 			 * MTRRs. */
-			dev_priv->mtrr[0].base = fb_base;
-			dev_priv->mtrr[0].size = 0x01000000;
-			dev_priv->mtrr[0].handle -			    drm_mtrr_add(dev_priv->mtrr[0].base,
-				         dev_priv->mtrr[0].size, DRM_MTRR_WC);
-			dev_priv->mtrr[1].base = fb_base + 0x02000000;
-			dev_priv->mtrr[1].size = 0x02000000;
-			dev_priv->mtrr[1].handle -			    drm_mtrr_add(dev_priv->mtrr[1].base,
-					 dev_priv->mtrr[1].size, DRM_MTRR_WC);
-			dev_priv->mtrr[2].base = fb_base + 0x04000000;
-			dev_priv->mtrr[2].size = 0x04000000;
-			dev_priv->mtrr[2].handle -			    drm_mtrr_add(dev_priv->mtrr[2].base,
-					 dev_priv->mtrr[2].size, DRM_MTRR_WC);
+			dev_priv->mtrr_handles[0] +				arch_phys_wc_add(fb_base, 0x01000000);
+			dev_priv->mtrr_handles[1] +				arch_phys_wc_add(fb_base + 0x02000000,
+						 0x02000000);
+			dev_priv->mtrr_handles[2] +				arch_phys_wc_add(fb_base + 0x04000000,
+						0x04000000);
 		} else {
 			DRM_ERROR("strange pci_resource_len %08llx\n",
 				  (unsigned long long)
@@ -616,11 +606,9 @@ int savage_driver_firstopen(struct drm_device *dev)
 		if (pci_resource_len(dev->pdev, 1) = 0x08000000) {
 			/* Can use one MTRR to cover both fb and
 			 * aperture. */
-			dev_priv->mtrr[0].base = fb_base;
-			dev_priv->mtrr[0].size = 0x08000000;
-			dev_priv->mtrr[0].handle -			    drm_mtrr_add(dev_priv->mtrr[0].base,
-					 dev_priv->mtrr[0].size, DRM_MTRR_WC);
+			dev_priv->mtrr_handles[0] +				arch_phys_wc_add(fb_base,
+						 0x08000000);
 		} else {
 			DRM_ERROR("strange pci_resource_len %08llx\n",
 				  (unsigned long long)
@@ -660,11 +648,10 @@ void savage_driver_lastclose(struct drm_device *dev)
 	drm_savage_private_t *dev_priv = dev->dev_private;
 	int i;
 
-	for (i = 0; i < 3; ++i)
-		if (dev_priv->mtrr[i].handle >= 0)
-			drm_mtrr_del(dev_priv->mtrr[i].handle,
-				 dev_priv->mtrr[i].base,
-				 dev_priv->mtrr[i].size, DRM_MTRR_WC);
+	for (i = 0; i < 3; ++i) {
+		arch_phys_wc_del(dev_priv->mtrr_handles[i]);
+		dev_priv->mtrr_handles[i] = 0;
+	}
 }
 
 int savage_driver_unload(struct drm_device *dev)
diff --git a/drivers/gpu/drm/savage/savage_drv.h b/drivers/gpu/drm/savage/savage_drv.h
index df2aac6..c05082a 100644
--- a/drivers/gpu/drm/savage/savage_drv.h
+++ b/drivers/gpu/drm/savage/savage_drv.h
@@ -160,10 +160,7 @@ typedef struct drm_savage_private {
 	drm_local_map_t *cmd_dma;
 	drm_local_map_t fake_dma;
 
-	struct {
-		int handle;
-		unsigned long base, size;
-	} mtrr[3];
+	int mtrr_handles[3];
 
 	/* BCI and status-related stuff */
 	volatile uint32_t *status_ptr, *bci_ptr;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 07dfd82..78e2164 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -565,8 +565,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 		dev_priv->has_gmr = false;
 	}
 
-	dev_priv->mmio_mtrr = drm_mtrr_add(dev_priv->mmio_start,
-					   dev_priv->mmio_size, DRM_MTRR_WC);
+	dev_priv->mmio_mtrr = arch_phys_wc_add(dev_priv->mmio_start,
+					       dev_priv->mmio_size);
 
 	dev_priv->mmio_virt = ioremap_wc(dev_priv->mmio_start,
 					 dev_priv->mmio_size);
@@ -664,8 +664,7 @@ out_no_device:
 out_err4:
 	iounmap(dev_priv->mmio_virt);
 out_err3:
-	drm_mtrr_del(dev_priv->mmio_mtrr, dev_priv->mmio_start,
-		     dev_priv->mmio_size, DRM_MTRR_WC);
+	arch_phys_wc_del(dev_priv->mmio_mtrr);
 	if (dev_priv->has_gmr)
 		(void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR);
 	(void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
@@ -709,8 +708,7 @@ static int vmw_driver_unload(struct drm_device *dev)
 
 	ttm_object_device_release(&dev_priv->tdev);
 	iounmap(dev_priv->mmio_virt);
-	drm_mtrr_del(dev_priv->mmio_mtrr, dev_priv->mmio_start,
-		     dev_priv->mmio_size, DRM_MTRR_WC);
+	arch_phys_wc_del(dev_priv->mmio_mtrr);
 	if (dev_priv->has_gmr)
 		(void)ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR);
 	(void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 2d94d74..3e6cfa0 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1249,37 +1249,8 @@ static inline int drm_core_has_MTRR(struct drm_device *dev)
 {
 	return drm_core_check_feature(dev, DRIVER_USE_MTRR);
 }
-
-#define DRM_MTRR_WC		MTRR_TYPE_WRCOMB
-
-static inline int drm_mtrr_add(unsigned long offset, unsigned long size,
-			       unsigned int flags)
-{
-	return mtrr_add(offset, size, flags, 1);
-}
-
-static inline int drm_mtrr_del(int handle, unsigned long offset,
-			       unsigned long size, unsigned int flags)
-{
-	return mtrr_del(handle, offset, size);
-}
-
 #else
 #define drm_core_has_MTRR(dev) (0)
-
-#define DRM_MTRR_WC		0
-
-static inline int drm_mtrr_add(unsigned long offset, unsigned long size,
-			       unsigned int flags)
-{
-	return 0;
-}
-
-static inline int drm_mtrr_del(int handle, unsigned long offset,
-			       unsigned long size, unsigned int flags)
-{
-	return 0;
-}
 #endif
 
 static inline void drm_device_set_unplugged(struct drm_device *dev)
-- 
1.8.1.4


^ permalink raw reply related

* [RFC/PATCH v2 3/8] drm: Update drm_addmap and drm_mmap to use PAT WC instead of MTRRs
From: Andy Lutomirski @ 2013-05-09 19:46 UTC (permalink / raw)
  To: linux-kernel, dri-devel, linux-fbdev
  Cc: Daniel Vetter, Jerome Glisse, Alex Deucher, Dave Airlie,
	Andy Lutomirski
In-Reply-To: <cover.1368128020.git.luto@amacapital.net>

Previously, DRM_FRAME_BUFFER mappings, as well as DRM_REGISTERS
mappings with DRM_WRITE_COMBINING set, resulted in an unconditional
MTRR being added but the actual mappings being created as UC-.

Now these mappings have the MTRR added only if needed, but they will
be mapped with pgprot_writecombine.

The non-WC DRM_REGISTERS case now uses pgprot_noncached instead of
hardcoding the bit twiddling.

The DRM_AGP case is unchanged for now.

Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---

Unlike v1, this should work well even for drivers that call
drmAddMap from userspace.  I didn't understand how the flags were
supposed to work last time around.

 drivers/gpu/drm/drm_bufs.c | 17 +++++++++--------
 drivers/gpu/drm/drm_vm.c   | 23 +++++++++++------------
 2 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
index 0128147..0190fce 100644
--- a/drivers/gpu/drm/drm_bufs.c
+++ b/drivers/gpu/drm/drm_bufs.c
@@ -210,12 +210,16 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
 		if (drm_core_has_MTRR(dev)) {
 			if (map->type = _DRM_FRAME_BUFFER ||
 			    (map->flags & _DRM_WRITE_COMBINING)) {
-				map->mtrr = mtrr_add(map->offset, map->size,
-						     MTRR_TYPE_WRCOMB, 1);
+				map->mtrr +					arch_phys_wc_add(map->offset, map->size);
 			}
 		}
 		if (map->type = _DRM_REGISTERS) {
-			map->handle = ioremap(map->offset, map->size);
+			if (map->flags & _DRM_WRITE_COMBINING)
+				map->handle = ioremap_wc(map->offset,
+							 map->size);
+			else
+				map->handle = ioremap(map->offset, map->size);
 			if (!map->handle) {
 				kfree(map);
 				return -ENOMEM;
@@ -451,11 +455,8 @@ int drm_rmmap_locked(struct drm_device *dev, struct drm_local_map *map)
 		iounmap(map->handle);
 		/* FALLTHROUGH */
 	case _DRM_FRAME_BUFFER:
-		if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
-			int retcode;
-			retcode = mtrr_del(map->mtrr, map->offset, map->size);
-			DRM_DEBUG("mtrr_del=%d\n", retcode);
-		}
+		if (drm_core_has_MTRR(dev))
+			arch_phys_wc_del(map->mtrr);
 		break;
 	case _DRM_SHM:
 		vfree(map->handle);
diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
index db7bd29..163f436 100644
--- a/drivers/gpu/drm/drm_vm.c
+++ b/drivers/gpu/drm/drm_vm.c
@@ -43,14 +43,18 @@
 static void drm_vm_open(struct vm_area_struct *vma);
 static void drm_vm_close(struct vm_area_struct *vma);
 
-static pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma)
+static pgprot_t drm_io_prot(struct drm_local_map *map,
+			    struct vm_area_struct *vma)
 {
 	pgprot_t tmp = vm_get_page_prot(vma->vm_flags);
 
 #if defined(__i386__) || defined(__x86_64__)
-	if (boot_cpu_data.x86 > 3 && map_type != _DRM_AGP) {
-		pgprot_val(tmp) |= _PAGE_PCD;
-		pgprot_val(tmp) &= ~_PAGE_PWT;
+	if (map->type != _DRM_AGP) {
+		if (map->type = _DRM_FRAME_BUFFER ||
+		    map->flags & _DRM_WRITE_COMBINING)
+			tmp = pgprot_writecombine(tmp);
+		else
+			tmp = pgprot_noncached(tmp);
 	}
 #elif defined(__powerpc__)
 	pgprot_val(tmp) |= _PAGE_NO_CACHE;
@@ -250,13 +254,8 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
 			switch (map->type) {
 			case _DRM_REGISTERS:
 			case _DRM_FRAME_BUFFER:
-				if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
-					int retcode;
-					retcode = mtrr_del(map->mtrr,
-							   map->offset,
-							   map->size);
-					DRM_DEBUG("mtrr_del = %d\n", retcode);
-				}
+				if (drm_core_has_MTRR(dev))
+					arch_phys_wc_del(map->mtrr);
 				iounmap(map->handle);
 				break;
 			case _DRM_SHM:
@@ -617,7 +616,7 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
 	case _DRM_REGISTERS:
 		offset = drm_core_get_reg_ofs(dev);
 		vma->vm_flags |= VM_IO;	/* not in core dump */
-		vma->vm_page_prot = drm_io_prot(map->type, vma);
+		vma->vm_page_prot = drm_io_prot(map, vma);
 		if (io_remap_pfn_range(vma, vma->vm_start,
 				       (map->offset + offset) >> PAGE_SHIFT,
 				       vma->vm_end - vma->vm_start,
-- 
1.8.1.4


^ permalink raw reply related

* [RFC/PATCH v2 4/8] drm,agpgart: Use pgprot_writecombine for AGP maps and make the MTRR optional
From: Andy Lutomirski @ 2013-05-09 19:46 UTC (permalink / raw)
  To: linux-kernel, dri-devel, linux-fbdev
  Cc: Daniel Vetter, Jerome Glisse, Alex Deucher, Dave Airlie,
	Andy Lutomirski
In-Reply-To: <cover.1368128020.git.luto@amacapital.net>

I'm not sure I understand the intent of the previous behavior.  mmap
on /dev/agpgart and DRM_AGP maps had no cache flags set, so they
would be fully cacheable.  But the DRM code (most of the time) would
add a write-combining MTRR that would change the effective memory
type to WC.

The new behavior just requests WC explicitly for all AGP maps.

If there is any code out there that expects cacheable access to the
AGP aperture (because the drm driver doesn't request an MTRR or
because it's using /dev/agpgart directly), then it will now end up
with a UC or WC mapping, depending on the architecture and PAT
availability.  But cacheable access to the aperture seems like it's
asking for trouble, because, AIUI, the aperture is an alias of RAM.

Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---

It's conceivable that libpciaccess could have issues with this due to
memtype conflicts, but I think this is unlikely (as long as a WC
mapping gets there first, I think the conflict resolution rules will
all work out).  In any case, everything that maps the AGP aperture
ought to be using /dev/agpgart or the DRM API, in which case
everything should be okay.

I don't have anything with an AGP slot to test AFAIK.

 drivers/char/agp/frontend.c |  8 +++++---
 drivers/gpu/drm/drm_pci.c   |  8 ++++----
 drivers/gpu/drm/drm_stub.c  | 10 ++--------
 drivers/gpu/drm/drm_vm.c    | 11 ++++-------
 4 files changed, 15 insertions(+), 22 deletions(-)

diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
index 2e04433..1b19239 100644
--- a/drivers/char/agp/frontend.c
+++ b/drivers/char/agp/frontend.c
@@ -603,7 +603,8 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
 			vma->vm_ops = kerninfo.vm_ops;
 		} else if (io_remap_pfn_range(vma, vma->vm_start,
 				(kerninfo.aper_base + offset) >> PAGE_SHIFT,
-					    size, vma->vm_page_prot)) {
+				size,
+				pgprot_writecombine(vma->vm_page_prot))) {
 			goto out_again;
 		}
 		mutex_unlock(&(agp_fe.agp_mutex));
@@ -618,8 +619,9 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
 		if (kerninfo.vm_ops) {
 			vma->vm_ops = kerninfo.vm_ops;
 		} else if (io_remap_pfn_range(vma, vma->vm_start,
-					    kerninfo.aper_base >> PAGE_SHIFT,
-					    size, vma->vm_page_prot)) {
+				kerninfo.aper_base >> PAGE_SHIFT,
+				size,
+				pgprot_writecombine(vma->vm_page_prot))) {
 			goto out_again;
 		}
 		mutex_unlock(&(agp_fe.agp_mutex));
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
index bd719e9..d0f6699 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -278,10 +278,10 @@ int drm_pci_agp_init(struct drm_device *dev)
 		}
 		if (drm_core_has_MTRR(dev)) {
 			if (dev->agp)
-				dev->agp->agp_mtrr -					mtrr_add(dev->agp->agp_info.aper_base,
-						 dev->agp->agp_info.aper_size *
-						 1024 * 1024, MTRR_TYPE_WRCOMB, 1);
+				dev->agp->agp_mtrr = arch_phys_wc_add(
+					dev->agp->agp_info.aper_base,
+					dev->agp->agp_info.aper_size *
+					1024 * 1024);
 		}
 	}
 	return 0;
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 7d30802..9e2acdf 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -451,14 +451,8 @@ void drm_put_dev(struct drm_device *dev)
 
 	drm_lastclose(dev);
 
-	if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
-	    dev->agp && dev->agp->agp_mtrr >= 0) {
-		int retval;
-		retval = mtrr_del(dev->agp->agp_mtrr,
-				  dev->agp->agp_info.aper_base,
-				  dev->agp->agp_info.aper_size * 1024 * 1024);
-		DRM_DEBUG("mtrr_del=%d\n", retval);
-	}
+	if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && dev->agp)
+		arch_phys_wc_del(dev->agp->agp_mtrr);
 
 	if (dev->driver->unload)
 		dev->driver->unload(dev);
diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
index 163f436..b1e4ec8 100644
--- a/drivers/gpu/drm/drm_vm.c
+++ b/drivers/gpu/drm/drm_vm.c
@@ -49,13 +49,10 @@ static pgprot_t drm_io_prot(struct drm_local_map *map,
 	pgprot_t tmp = vm_get_page_prot(vma->vm_flags);
 
 #if defined(__i386__) || defined(__x86_64__)
-	if (map->type != _DRM_AGP) {
-		if (map->type = _DRM_FRAME_BUFFER ||
-		    map->flags & _DRM_WRITE_COMBINING)
-			tmp = pgprot_writecombine(tmp);
-		else
-			tmp = pgprot_noncached(tmp);
-	}
+	if (map->type = _DRM_REGISTERS && !(map->flags & _DRM_WRITE_COMBINING))
+		tmp = pgprot_noncached(tmp);
+	else
+		tmp = pgprot_writecombine(tmp);
 #elif defined(__powerpc__)
 	pgprot_val(tmp) |= _PAGE_NO_CACHE;
 	if (map_type = _DRM_REGISTERS)
-- 
1.8.1.4


^ permalink raw reply related

* [RFC/PATCH v2 5/8] i915: Use arch_phys_wc_{add,del}
From: Andy Lutomirski @ 2013-05-09 19:46 UTC (permalink / raw)
  To: linux-kernel, dri-devel, linux-fbdev
  Cc: Daniel Vetter, Jerome Glisse, Alex Deucher, Dave Airlie,
	Andy Lutomirski
In-Reply-To: <cover.1368128020.git.luto@amacapital.net>

i915 open-coded logic that was essentially equivalent to the new API.

Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---

Changes from v1: More cleanup

 drivers/gpu/drm/i915/i915_dma.c | 44 ++++++-----------------------------------
 1 file changed, 6 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 4fa6beb..cfdfb45 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -42,7 +42,6 @@
 #include <linux/vga_switcheroo.h>
 #include <linux/slab.h>
 #include <acpi/video.h>
-#include <asm/pat.h>
 
 #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
 
@@ -1393,29 +1392,6 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
 	master->driver_priv = NULL;
 }
 
-static void
-i915_mtrr_setup(struct drm_i915_private *dev_priv, unsigned long base,
-		unsigned long size)
-{
-	dev_priv->mm.gtt_mtrr = -1;
-
-#if defined(CONFIG_X86_PAT)
-	if (cpu_has_pat)
-		return;
-#endif
-
-	/* Set up a WC MTRR for non-PAT systems.  This is more common than
-	 * one would think, because the kernel disables PAT on first
-	 * generation Core chips because WC PAT gets overridden by a UC
-	 * MTRR if present.  Even if a UC MTRR isn't present.
-	 */
-	dev_priv->mm.gtt_mtrr = mtrr_add(base, size, MTRR_TYPE_WRCOMB, 1);
-	if (dev_priv->mm.gtt_mtrr < 0) {
-		DRM_INFO("MTRR allocation failed.  Graphics "
-			 "performance may suffer.\n");
-	}
-}
-
 static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
 {
 	struct apertures_struct *ap;
@@ -1552,8 +1528,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 		goto out_rmmap;
 	}
 
-	i915_mtrr_setup(dev_priv, dev_priv->gtt.mappable_base,
-			aperture_size);
+	dev_priv->mm.gtt_mtrr = arch_phys_wc_add(dev_priv->gtt.mappable_base,
+						 aperture_size);
 
 	/* The i915 workqueue is primarily used for batched retirement of
 	 * requests (and thus managing bo) once the task has been completed
@@ -1656,12 +1632,8 @@ out_gem_unload:
 	intel_teardown_mchbar(dev);
 	destroy_workqueue(dev_priv->wq);
 out_mtrrfree:
-	if (dev_priv->mm.gtt_mtrr >= 0) {
-		mtrr_del(dev_priv->mm.gtt_mtrr,
-			 dev_priv->gtt.mappable_base,
-			 aperture_size);
-		dev_priv->mm.gtt_mtrr = -1;
-	}
+	arch_phys_wc_del(dev_priv->mm.gtt_mtrr);
+	dev_priv->mm.gtt_mtrr = 0;
 	io_mapping_free(dev_priv->gtt.mappable);
 out_rmmap:
 	pci_iounmap(dev->pdev, dev_priv->regs);
@@ -1697,12 +1669,8 @@ int i915_driver_unload(struct drm_device *dev)
 	cancel_delayed_work_sync(&dev_priv->mm.retire_work);
 
 	io_mapping_free(dev_priv->gtt.mappable);
-	if (dev_priv->mm.gtt_mtrr >= 0) {
-		mtrr_del(dev_priv->mm.gtt_mtrr,
-			 dev_priv->gtt.mappable_base,
-			 dev_priv->gtt.mappable_end);
-		dev_priv->mm.gtt_mtrr = -1;
-	}
+	arch_phys_wc_del(dev_priv->mm.gtt_mtrr);
+	dev_priv->mm.gtt_mtrr = 0;
 
 	acpi_video_unregister();
 
-- 
1.8.1.4


^ permalink raw reply related

* [RFC/PATCH v2 6/8] radeon: Switch to arch_phys_wc_add and add a missing ..._del
From: Andy Lutomirski @ 2013-05-09 19:46 UTC (permalink / raw)
  To: linux-kernel, dri-devel, linux-fbdev
  Cc: Daniel Vetter, Jerome Glisse, Alex Deucher, Dave Airlie,
	Andy Lutomirski
In-Reply-To: <cover.1368128020.git.luto@amacapital.net>

Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---
 drivers/gpu/drm/radeon/radeon_object.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index d3aface..15cd34b 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -321,8 +321,8 @@ void radeon_bo_force_delete(struct radeon_device *rdev)
 int radeon_bo_init(struct radeon_device *rdev)
 {
 	/* Add an MTRR for the VRAM */
-	rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size,
-			MTRR_TYPE_WRCOMB, 1);
+	rdev->mc.vram_mtrr = arch_phys_wc_add(rdev->mc.aper_base,
+					      rdev->mc.aper_size);
 	DRM_INFO("Detected VRAM RAM=%lluM, BAR=%lluM\n",
 		rdev->mc.mc_vram_size >> 20,
 		(unsigned long long)rdev->mc.aper_size >> 20);
@@ -334,6 +334,7 @@ int radeon_bo_init(struct radeon_device *rdev)
 void radeon_bo_fini(struct radeon_device *rdev)
 {
 	radeon_ttm_fini(rdev);
+	arch_phys_wc_del(rdev->mc.vram_mtrr);
 }
 
 void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
-- 
1.8.1.4


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox