[PATCH] drm/radeon: fix typo in trinity tiling setup

2012-05-24 Thread alexdeuc...@gmail.com
From: Alex Deucher 

Using the wrong union.

Signed-off-by: Alex Deucher 
Cc: stable at vger.kernel.org
---
 drivers/gpu/drm/radeon/ni.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index b01c2dd..ce4e7cc 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -865,7 +865,7 @@ static void cayman_gpu_init(struct radeon_device *rdev)

/* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */
if (rdev->flags & RADEON_IS_IGP)
-   rdev->config.evergreen.tile_config |= 1 << 4;
+   rdev->config.cayman.tile_config |= 1 << 4;
else
rdev->config.cayman.tile_config |=
((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 
4;
-- 
1.7.7.5



[PATCH 0/4] drm/i915: Make video sprites survive a modeset

2012-05-24 Thread Ville Syrjälä
On Thu, May 24, 2012 at 08:49:53PM +0200, Daniel Vetter wrote:
> On Thu, May 24, 2012 at 11:35:35AM -0700, Jesse Barnes wrote:
> > On Thu, 24 May 2012 21:29:46 +0300
> > ville.syrjala at linux.intel.com wrote:
> > 
> > > Currently the video sprites appear to get disabled on modeset more by
> > > accient than by design.
> > > 
> > > With the current API that behaviour makes very little sense to me.
> > > You first enable some plane, and then it can get disabled due to some
> > > unrelated operation.
> > > 
> > > So these patches change the behaviour so that planes survive a modeset.
> > > There's a new hook to make sure they get disabled when swithing
> > > back to fbdev to show a panic oops.
> > 
> > Yeah that's not really a design requirement; the assumption was that
> > the display manager would do the right thing in any case (both mode
> > sets and plane sets are privileged ops).  When doing a mode set, the
> > plane parameters will probably need to be changed anyway...
> > 
> > But keeping it on with some kind of sensible behavior makes the simple
> > cases easier.
> 
> tbh I don't see the use-case. If you issue a modeset from userspace, you
> better start out with something sensible (like a black screeen) and fade
> in nicely whatever you want to show. And if you change the layout, you
> have to reorg everything anyway.

Mainly I just dislike incoherent behaviour.

One use case might be flipping to another framebuffer using the
setcrtc ioctl, in case the page flip ioctl isn't provided, or can't
be used. With the current code the result depends on various
implementation specific details like whether the driver implements
a set_base type of optimization in a certain way. From the user
space POV it's just a setcrtc ioctl, but there's no sensible way
to know whether the operation will destroy some unrelated state
or not.

-- 
Ville Syrj?l?
Intel OTC


[Bug 50325] Glyphy bad render on r600g (software render is fine)

2012-05-24 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=50325

--- Comment #2 from T?r?k Edwin  2012-05-24 14:57:24 
PDT ---
Created attachment 62080
  --> https://bugs.freedesktop.org/attachment.cgi?id=62080
sw-good.png

-- 
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are the assignee for the bug.


[Bug 50325] Glyphy bad render on r600g (software render is fine)

2012-05-24 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=50325

--- Comment #1 from T?r?k Edwin  2012-05-24 14:57:08 
PDT ---
Created attachment 62079
  --> https://bugs.freedesktop.org/attachment.cgi?id=62079
r600g-bad.png

-- 
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are the assignee for the bug.


[Bug 50325] New: Glyphy bad render on r600g (software render is fine)

2012-05-24 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=50325

 Bug #: 50325
   Summary: Glyphy bad render on r600g (software render is fine)
Classification: Unclassified
   Product: Mesa
   Version: 8.0
  Platform: x86-64 (AMD64)
OS/Version: Linux (All)
Status: NEW
  Severity: normal
  Priority: medium
 Component: Drivers/Gallium/r600
AssignedTo: dri-devel at lists.freedesktop.org
ReportedBy: edwin+mesa at etorok.net


Created attachment 62078
  --> https://bugs.freedesktop.org/attachment.cgi?id=62078
apitrace (cf. https://github.com/apitrace/apitrace/tree/1.0)

I just tried Glyphy on r600g and the output is very bad.
Don't know if its Glyphy bug or Mesa bug, but if I force software rendering in
Mesa then I do see the output.

Attached screenshots of bad (r600g) and good (software render).

The bad render was obtained by:
demo/glyphy-demo

The good one:
LIBGL_ALWAYS_SOFTWARE=1 demo/glyphy-demo

I tested on:
OpenGL vendor string: X.Org
OpenGL renderer string: Gallium 0.4 on AMD RV730
OpenGL version string: 2.1 Mesa 8.0.2
OpenGL shading language version string: 1.20

I'll try to test on mesa git later to see if its still an issue there.

Also attached is a an apitrace, and the bad render can be reproduced with:
build/glretrace lt-glyphy-demo.trace

The good render (initialization a bit slow, but works):
LIBGL_ALWAYS_SOFTWARE=1 build/glretrace lt-glyphy-demo.trace

The source code for Glyphy can be found here:
https://code.google.com/p/glyphy/source/checkout

-- 
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are the assignee for the bug.


[PATCH 2/3] drm: Be more paranoid with integer overflows

2012-05-24 Thread Ville Syrjälä
On Thu, May 24, 2012 at 08:30:23PM +0200, Daniel Vetter wrote:
> On Thu, May 24, 2012 at 08:53:59PM +0300, ville.syrjala at linux.intel.com 
> wrote:
> > From: Ville Syrj?l? 
> > 
> > Make sure 'width * cpp' and 'height * pitch + offset' don't exceed
> > UINT_MAX.
> > 
> > Signed-off-by: Ville Syrj?l? 
> > ---
> >  drivers/gpu/drm/drm_crtc.c |   10 +-
> >  1 files changed, 9 insertions(+), 1 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> > index 80a34e7..e1b53fb 100644
> > --- a/drivers/gpu/drm/drm_crtc.c
> > +++ b/drivers/gpu/drm/drm_crtc.c
> > @@ -2211,13 +2211,21 @@ static int framebuffer_check(struct 
> > drm_mode_fb_cmd2 *r)
> >  
> > for (i = 0; i < num_planes; i++) {
> > unsigned int width = r->width / (i != 0 ? hsub : 1);
> > +   unsigned int height = r->height / (i != 0 ? vsub : 1);
> > +   unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
> >  
> > if (!r->handles[i]) {
> > DRM_DEBUG_KMS("no buffer object handle for plane %d\n", 
> > i);
> > return -EINVAL;
> > }
> >  
> > -   if (r->pitches[i] < drm_format_plane_cpp(r->pixel_format, i) * 
> > width) {
> > +   if ((uint64_t) width * cpp > UINT_MAX)
> > +   return -ERANGE;
> > +
> 
> iirc that blows up on 32bit because gcc likes to use a compiler built-in.

I think that problem only happens w/ 64bit divs, which is why you have do_div()
and friends. At least with a small test app 'gcc -O2 -m32' generates the obvious
mul+cmp code, and mul+add+adc+cmp for the case w/ offsets[i] added. Maybe other
archs can't do it so neatly though.

> And the usual pattern I've seen is if (UINT_MAX / a < b) return -ERANGE;

I'm not a fan of divs :)

-- 
Ville Syrj?l?
Intel OTC


[Intel-gfx] [PATCH 5/6] drm/i915: Handle framebuffer offsets[]

2012-05-24 Thread Ville Syrjälä
On Thu, May 24, 2012 at 11:31:32AM -0700, Jesse Barnes wrote:
> On Thu, 24 May 2012 21:08:58 +0300
> ville.syrjala at linux.intel.com wrote:
> 
> > From: Ville Syrj?l? 
> > 
> > Take fb->offset[0] into account when calculating the linear and tile x/y
> > offsets.
> > 
> > For non-tiled surfaces fb->offset[0] is simply added to the linear
> > byte offset.
> > 
> > For tiled surfaces treat fb->offsets[0] as a byte offset into the
> > linearized view of the surface. So we end up converting fb->offsets[0]
> > into additional x and y offsets.
> 
> Do you have code using a non-zero offsets[0]?  At least for current
> code that would indicate some kind of problem... though hopefully we'll
> be adding planar support back again sometime soon.

I did have some test app that used offsets[] at some point, but tbh I
didn't excercise these changes with it.

I have a sort of semi working skeleton of a test app which I just modify
for various use cases as need arises. I really should try to clean it up
a bit and generalize it so that it wouldn't need constant code changes
to test different scenarios.

-- 
Ville Syrj?l?
Intel OTC


[PATCH 4/4] drm/i915: Implement restore_fbdev_mode hook

2012-05-24 Thread ville.syrj...@linux.intel.com
From: Ville Syrj?l? 

Convert intel_fb_restore_mode to be useable as the
drm_fb_helper.restore_fbdev_mode hook. This will cause all planes to be
disabled when swithing back to fbcon.

Signed-off-by: Ville Syrj?l? 
---
 drivers/gpu/drm/i915/i915_dma.c  |2 +-
 drivers/gpu/drm/i915/intel_drv.h |2 +-
 drivers/gpu/drm/i915/intel_fb.c  |   14 ++
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index f947926..186308a 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1738,7 +1738,7 @@ void i915_driver_lastclose(struct drm_device * dev)
drm_i915_private_t *dev_priv = dev->dev_private;

if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) {
-   intel_fb_restore_mode(dev);
+   intel_fb_restore_mode(_priv->fbdev->helper);
vga_switcheroo_process_delayed_switch();
return;
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 3e09188..2ec63a8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -452,7 +452,7 @@ extern int intel_overlay_attrs(struct drm_device *dev, void 
*data,
   struct drm_file *file_priv);

 extern void intel_fb_output_poll_changed(struct drm_device *dev);
-extern void intel_fb_restore_mode(struct drm_device *dev);
+extern int intel_fb_restore_mode(struct drm_fb_helper *helper);

 extern void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
bool state);
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index 07404ac..51b7fd1 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -192,6 +192,7 @@ static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
.gamma_set = intel_crtc_fb_gamma_set,
.gamma_get = intel_crtc_fb_gamma_get,
.fb_probe = intel_fb_find_or_create_single,
+   .restore_fbdev_mode = intel_fb_restore_mode,
 };

 static void intel_fbdev_destroy(struct drm_device *dev,
@@ -272,22 +273,27 @@ void intel_fb_output_poll_changed(struct drm_device *dev)
drm_fb_helper_hotplug_event(_priv->fbdev->helper);
 }

-void intel_fb_restore_mode(struct drm_device *dev)
+int intel_fb_restore_mode(struct drm_fb_helper *helper)
 {
+   struct drm_device *dev = helper->dev;
int ret;
-   drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_mode_config *config = >mode_config;
struct drm_plane *plane;

mutex_lock(>mode_config.mutex);

-   ret = drm_fb_helper_restore_fbdev_mode(_priv->fbdev->helper);
-   if (ret)
+   ret = drm_fb_helper_restore_fbdev_mode(helper);
+   if (ret) {
DRM_DEBUG("failed to restore crtc mode\n");
+   goto out;
+   }

/* Be sure to shut off any planes that may be active */
list_for_each_entry(plane, >plane_list, head)
plane->funcs->disable_plane(plane);

+out:
mutex_unlock(>mode_config.mutex);
+
+   return ret;
 }
-- 
1.7.3.4



[PATCH 3/4] drm/i915: Disable/enable planes around mode set

2012-05-24 Thread ville.syrj...@linux.intel.com
From: Ville Syrj?l? 

When setting a display mode, disable all planes on the CRTC beforehand,
and re-enable them after the new mode has been set.

Signed-off-by: Ville Syrj?l? 
---
 drivers/gpu/drm/i915/intel_display.c |   48 ++
 1 files changed, 48 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 72ac2f9..aec6cac 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3012,6 +3012,49 @@ void intel_cpt_verify_modeset(struct drm_device *dev, 
int pipe)
}
 }

+static int intel_crtc_disable_planes(struct drm_crtc *crtc)
+{
+   struct drm_device *dev = crtc->dev;
+   struct drm_plane *plane;
+
+   list_for_each_entry(plane, >mode_config.plane_list, head) {
+   int ret;
+
+   if (plane->crtc != crtc || !plane->fb)
+   continue;
+
+   ret = plane->funcs->disable_plane(plane);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
+}
+
+static int intel_crtc_enable_planes(struct drm_crtc *crtc)
+{
+   struct drm_device *dev = crtc->dev;
+   struct drm_plane *plane;
+
+   list_for_each_entry(plane, >mode_config.plane_list, head) {
+   int ret;
+
+   if (plane->crtc != crtc || !plane->fb)
+   continue;
+
+   ret = plane->funcs->update_plane(plane,
+plane->crtc, plane->fb,
+plane->crtc_x, plane->crtc_y,
+plane->crtc_w, plane->crtc_h,
+plane->src_x, plane->src_y,
+plane->src_w, plane->src_h);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
+}
+
 static void ironlake_crtc_enable(struct drm_crtc *crtc)
 {
struct drm_device *dev = crtc->dev;
@@ -3060,6 +3103,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
intel_crtc_load_lut(crtc);

intel_enable_pipe(dev_priv, pipe, is_pch_port);
+   intel_crtc_enable_planes(crtc);
intel_enable_plane(dev_priv, plane, pipe);

if (is_pch_port)
@@ -3088,6 +3132,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
drm_vblank_off(dev, pipe);
intel_crtc_update_cursor(crtc, false);

+   intel_crtc_disable_planes(crtc);
intel_disable_plane(dev_priv, plane, pipe);

if (dev_priv->cfb_plane == plane)
@@ -3233,6 +3278,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)

intel_enable_pll(dev_priv, pipe);
intel_enable_pipe(dev_priv, pipe, false);
+
intel_enable_plane(dev_priv, plane, pipe);

intel_crtc_load_lut(crtc);
@@ -3241,6 +3287,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
/* Give the overlay scaler a chance to enable if it's on this pipe */
intel_crtc_dpms_overlay(intel_crtc, true);
intel_crtc_update_cursor(crtc, true);
+   intel_crtc_enable_planes(crtc);
 }

 static void i9xx_crtc_disable(struct drm_crtc *crtc)
@@ -3259,6 +3306,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
drm_vblank_off(dev, pipe);
intel_crtc_dpms_overlay(intel_crtc, false);
intel_crtc_update_cursor(crtc, false);
+   intel_crtc_disable_planes(crtc);

if (dev_priv->cfb_plane == plane)
intel_disable_fbc(dev);
-- 
1.7.3.4



[PATCH 1/4] drm: Keep a copy of last plane coordinates

2012-05-24 Thread ville.syrj...@linux.intel.com
From: Ville Syrj?l? 

If the update_plane() operation succeeds, make a copy of the requested
src and crtc coordinates, so that the the plane may be reclipped if the
display mode changed later.

Signed-off-by: Ville Syrj?l? 
---
 drivers/gpu/drm/drm_crtc.c |8 
 include/drm/drm_crtc.h |4 
 2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index d981fe2..6dafb99 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1793,6 +1793,14 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
if (!ret) {
plane->crtc = crtc;
plane->fb = fb;
+   plane->crtc_x = plane_req->crtc_x;
+   plane->crtc_y = plane_req->crtc_y;
+   plane->crtc_w = plane_req->crtc_w;
+   plane->crtc_h = plane_req->crtc_h;
+   plane->src_x = plane_req->src_x;
+   plane->src_y = plane_req->src_y;
+   plane->src_w = plane_req->src_w;
+   plane->src_h = plane_req->src_h;
}

 out:
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 8a17cce..3261492 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -657,6 +657,10 @@ struct drm_plane {
void *helper_private;

struct drm_object_properties properties;
+
+   uint32_t src_x, src_y, src_w, src_h;
+   int32_t crtc_x, crtc_y;
+   uint32_t crtc_w, crtc_h;
 };

 /**
-- 
1.7.3.4



[PATCH 14/14] drm/i915: s/mdelay/msleep/ in the sdvo detect function

2012-05-24 Thread Daniel Vetter
A 30 ms delay is simply way too big to waste cpu cycles on.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/i915/intel_sdvo.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sdvo.c 
b/drivers/gpu/drm/i915/intel_sdvo.c
index 6056603..efa0d17 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1370,7 +1370,7 @@ intel_sdvo_detect(struct drm_connector *connector, bool 
force)

/* add 30ms delay when the output type might be TV */
if (intel_sdvo->caps.output_flags & SDVO_TV_MASK)
-   mdelay(30);
+   msleep(30);

if (!intel_sdvo_read_response(intel_sdvo, , 2))
return connector_status_unknown;
-- 
1.7.7.6



[PATCH 13/14] drm/i915/sdvo: implement correct return value for ->get_modes

2012-05-24 Thread Daniel Vetter
We should return the number of added modes. Luckily no one really
cares, but it kinda sticked out compared to the other ->get_modes
functions I've looked at recently.

Signed-Off-by: Daniel Vetter 
---
 drivers/gpu/drm/i915/intel_sdvo.c |   41 ++--
 1 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sdvo.c 
b/drivers/gpu/drm/i915/intel_sdvo.c
index fdc0574..6056603 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1428,8 +1428,9 @@ intel_sdvo_detect(struct drm_connector *connector, bool 
force)
return ret;
 }

-static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
+static int intel_sdvo_get_ddc_modes(struct drm_connector *connector)
 {
+   int ret = 0;
struct edid *edid;

/* set the bus switch and get the modes */
@@ -1448,12 +1449,14 @@ static void intel_sdvo_get_ddc_modes(struct 
drm_connector *connector)
if 
(intel_sdvo_connector_matches_edid(to_intel_sdvo_connector(connector),
  edid)) {
drm_mode_connector_update_edid_property(connector, 
edid);
-   drm_add_edid_modes(connector, edid);
+   ret = drm_add_edid_modes(connector, edid);
}

connector->display_info.raw_edid = NULL;
kfree(edid);
}
+
+   return ret;
 }

 /*
@@ -1521,12 +1524,12 @@ static const struct drm_display_mode sdvo_tv_modes[] = {
   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
 };

-static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
+static int intel_sdvo_get_tv_modes(struct drm_connector *connector)
 {
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
struct intel_sdvo_sdtv_resolution_request tv_res;
uint32_t reply = 0, format_map = 0;
-   int i;
+   int i, ret = 0;

/* Read the list of supported input resolutions for the selected TV
 * format.
@@ -1536,39 +1539,44 @@ static void intel_sdvo_get_tv_modes(struct 
drm_connector *connector)
   min(sizeof(format_map), sizeof(struct 
intel_sdvo_sdtv_resolution_request)));

if (!intel_sdvo_set_target_output(intel_sdvo, 
intel_sdvo->attached_output))
-   return;
+   return 0;

BUILD_BUG_ON(sizeof(tv_res) != 3);
if (!intel_sdvo_write_cmd(intel_sdvo,
  SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT,
  _res, sizeof(tv_res)))
-   return;
+   return 0;
if (!intel_sdvo_read_response(intel_sdvo, , 3))
-   return;
+   return 0;

for (i = 0; i < ARRAY_SIZE(sdvo_tv_modes); i++)
if (reply & (1 << i)) {
struct drm_display_mode *nmode;
nmode = drm_mode_duplicate(connector->dev,
   _tv_modes[i]);
-   if (nmode)
+   if (nmode) {
drm_mode_probed_add(connector, nmode);
+   ret++;
+   }
}
+
+   return ret;
 }

-static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
+static int intel_sdvo_get_lvds_modes(struct drm_connector *connector)
 {
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
struct drm_i915_private *dev_priv = connector->dev->dev_private;
struct drm_display_mode *newmode;
+   int ret;

/*
 * Attempt to get the mode list from DDC.
 * Assume that the preferred modes are
 * arranged in priority order.
 */
-   intel_ddc_get_modes(connector, intel_sdvo->i2c);
-   if (list_empty(>probed_modes) == false)
+   ret = intel_ddc_get_modes(connector, intel_sdvo->i2c);
+   if (ret)
goto end;

/* Fetch modes from VBT */
@@ -1580,6 +1588,8 @@ static void intel_sdvo_get_lvds_modes(struct 
drm_connector *connector)
newmode->type = (DRM_MODE_TYPE_PREFERRED |
 DRM_MODE_TYPE_DRIVER);
drm_mode_probed_add(connector, newmode);
+
+   ret++;
}
}

@@ -1594,6 +1604,7 @@ end:
}
}

+   return ret;
 }

 static int intel_sdvo_get_modes(struct drm_connector *connector)
@@ -1601,13 +1612,11 @@ static int intel_sdvo_get_modes(struct drm_connector 
*connector)
struct intel_sdvo_connector *intel_sdvo_connector = 
to_intel_sdvo_connector(connector);

if (IS_TV(intel_sdvo_connector))
-   intel_sdvo_get_tv_modes(connector);
+   return intel_sdvo_get_tv_modes(connector);
else if (IS_LVDS(intel_sdvo_connector))
-   

[PATCH 12/14] drm/i915: cache hdmi edid

2012-05-24 Thread Daniel Vetter
Like the previous patches.

While at it also kill a stale comment - we've moved hdmi audio
detection from ->get_modes to ->detect and the audio property handling
functions.

Signed-Off-by: Daniel Vetter 
---
 drivers/gpu/drm/i915/intel_drv.h  |1 +
 drivers/gpu/drm/i915/intel_hdmi.c |   48 +++--
 2 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 3b6f716..8693551 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -301,6 +301,7 @@ struct intel_hdmi {
enum hdmi_force_audio force_audio;
void (*write_infoframe)(struct drm_encoder *encoder,
struct dip_infoframe *frame);
+   struct edid *cached_edid;
 };

 static inline struct drm_crtc *
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c 
b/drivers/gpu/drm/i915/intel_hdmi.c
index 2ead3bf..373d252 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -452,19 +452,37 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder 
*encoder,
return true;
 }

+struct edid *
+intel_hdmi_get_edid(struct drm_connector *connector)
+{
+   struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+   struct drm_i915_private *dev_priv = connector->dev->dev_private;
+
+   if (!intel_hdmi->cached_edid) {
+   struct i2c_adapter *adapter;
+
+   adapter = intel_gmbus_get_adapter(dev_priv,
+ intel_hdmi->ddc_bus);
+   intel_hdmi->cached_edid = drm_get_edid(connector, adapter);
+   }
+
+   return intel_hdmi->cached_edid;
+}
+
 static enum drm_connector_status
 intel_hdmi_detect(struct drm_connector *connector, bool force)
 {
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
-   struct drm_i915_private *dev_priv = connector->dev->dev_private;
struct edid *edid;
enum drm_connector_status status = connector_status_disconnected;

+   /* Clean the edid cache. */
+   kfree(intel_hdmi->cached_edid);
+   intel_hdmi->cached_edid = NULL;
+
intel_hdmi->has_hdmi_sink = false;
intel_hdmi->has_audio = false;
-   edid = drm_get_edid(connector,
-   intel_gmbus_get_adapter(dev_priv,
-   intel_hdmi->ddc_bus));
+   edid = intel_hdmi_get_edid(connector);

if (edid) {
if (edid->input & DRM_EDID_INPUT_DIGITAL) {
@@ -477,6 +495,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool 
force)
connector->display_info.raw_edid = NULL;
kfree(edid);
}
+   intel_hdmi->cached_edid = edid;

if (status == connector_status_connected) {
if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO)
@@ -489,29 +508,19 @@ intel_hdmi_detect(struct drm_connector *connector, bool 
force)

 static int intel_hdmi_get_modes(struct drm_connector *connector)
 {
-   struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
-   struct drm_i915_private *dev_priv = connector->dev->dev_private;
-
-   /* We should parse the EDID data and find out if it's an HDMI sink so
-* we can send audio to it.
-*/
+   struct edid *edid;

-   return intel_ddc_get_modes(connector,
-  intel_gmbus_get_adapter(dev_priv,
-  
intel_hdmi->ddc_bus));
+   edid = intel_hdmi_get_edid(connector);
+   return intel_edid_get_modes(connector, edid);
 }

 static bool
 intel_hdmi_detect_audio(struct drm_connector *connector)
 {
-   struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
-   struct drm_i915_private *dev_priv = connector->dev->dev_private;
struct edid *edid;
bool has_audio = false;

-   edid = drm_get_edid(connector,
-   intel_gmbus_get_adapter(dev_priv,
-   intel_hdmi->ddc_bus));
+   edid = intel_hdmi_get_edid(connector);
if (edid) {
if (edid->input & DRM_EDID_INPUT_DIGITAL)
has_audio = drm_detect_monitor_audio(edid);
@@ -580,8 +589,11 @@ done:

 static void intel_hdmi_destroy(struct drm_connector *connector)
 {
+   struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
+   kfree(intel_hdmi->cached_edid);
kfree(connector);
 }

-- 
1.7.7.6



[PATCH 11/14] drm/i915: cache dp edid

2012-05-24 Thread Daniel Vetter
Again, let's be slightly more clever here.

Signed-Off-by: Daniel Vetter 
---
 drivers/gpu/drm/i915/intel_dp.c |   47 ++
 1 files changed, 22 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 3bbd754..1c84a97 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -67,6 +67,7 @@ struct intel_dp {
struct drm_display_mode *panel_fixed_mode;  /* for eDP */
struct delayed_work panel_vdd_work;
bool want_panel_vdd;
+   struct edid *cached_edid;
 };

 /**
@@ -2089,30 +2090,19 @@ g4x_dp_detect(struct intel_dp *intel_dp)
 }

 static struct edid *
-intel_dp_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
+intel_dp_get_edid(struct drm_connector *connector)
 {
struct intel_dp *intel_dp = intel_attached_dp(connector);
-   struct edid *edid;
-
-   ironlake_edp_panel_vdd_on(intel_dp);
-   edid = drm_get_edid(connector, adapter);
-   ironlake_edp_panel_vdd_off(intel_dp, false);
-   return edid;
-}

-static int
-intel_dp_get_edid_modes(struct drm_connector *connector, struct i2c_adapter 
*adapter)
-{
-   struct intel_dp *intel_dp = intel_attached_dp(connector);
-   int ret;
+   if (!intel_dp->cached_edid) {
+   ironlake_edp_panel_vdd_on(intel_dp);
+   intel_dp->cached_edid = drm_get_edid(connector, 
_dp->adapter);
+   ironlake_edp_panel_vdd_off(intel_dp, false);
+   }

-   ironlake_edp_panel_vdd_on(intel_dp);
-   ret = intel_ddc_get_modes(connector, adapter);
-   ironlake_edp_panel_vdd_off(intel_dp, false);
-   return ret;
+   return intel_dp->cached_edid;
 }

-
 /**
  * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection.
  *
@@ -2127,6 +2117,10 @@ intel_dp_detect(struct drm_connector *connector, bool 
force)
enum drm_connector_status status;
struct edid *edid = NULL;

+   /* Clean the edid cache. */
+   kfree(intel_dp->cached_edid);
+   intel_dp->cached_edid = NULL;
+
intel_dp->has_audio = false;

if (HAS_PCH_SPLIT(dev))
@@ -2145,11 +2139,10 @@ intel_dp_detect(struct drm_connector *connector, bool 
force)
if (intel_dp->force_audio != HDMI_AUDIO_AUTO) {
intel_dp->has_audio = (intel_dp->force_audio == HDMI_AUDIO_ON);
} else {
-   edid = intel_dp_get_edid(connector, _dp->adapter);
+   edid = intel_dp_get_edid(connector);
if (edid) {
intel_dp->has_audio = drm_detect_monitor_audio(edid);
connector->display_info.raw_edid = NULL;
-   kfree(edid);
}
}

@@ -2161,12 +2154,16 @@ static int intel_dp_get_modes(struct drm_connector 
*connector)
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct drm_device *dev = intel_dp->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
-   int ret;
+   struct edid *edid;
+   int ret = 0;

/* We should parse the EDID data and find out if it has an audio sink
 */

-   ret = intel_dp_get_edid_modes(connector, _dp->adapter);
+   edid = intel_dp_get_edid(connector);
+   if (edid)
+   ret = intel_edid_get_modes(connector, edid);
+
if (ret) {
if (is_edp(intel_dp) && !intel_dp->panel_fixed_mode) {
struct drm_display_mode *newmode;
@@ -2206,16 +2203,14 @@ static int intel_dp_get_modes(struct drm_connector 
*connector)
 static bool
 intel_dp_detect_audio(struct drm_connector *connector)
 {
-   struct intel_dp *intel_dp = intel_attached_dp(connector);
struct edid *edid;
bool has_audio = false;

-   edid = intel_dp_get_edid(connector, _dp->adapter);
+   edid = intel_dp_get_edid(connector);
if (edid) {
has_audio = drm_detect_monitor_audio(edid);

connector->display_info.raw_edid = NULL;
-   kfree(edid);
}

return has_audio;
@@ -2279,6 +2274,7 @@ done:
 static void
 intel_dp_destroy(struct drm_connector *connector)
 {
+   struct intel_dp *intel_dp = intel_attached_dp(connector);
struct drm_device *dev = connector->dev;

if (intel_dpd_is_edp(dev))
@@ -2286,6 +2282,7 @@ intel_dp_destroy(struct drm_connector *connector)

drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
+   kfree(intel_dp->cached_edid);
kfree(connector);
 }

-- 
1.7.7.6



[PATCH 10/14] drm/i915: cache crt edid

2012-05-24 Thread Daniel Vetter
Let's put all this new output detection infrastructure and rework
to some good use and cache the crt edid. Given that the drm helpers
now only call ->detect when actually required, we only need to reset
the edid there and can keep it otherwise.

Slashes xrandr time on systems that are hotplug capable if there's
something connected to the VGA connector.

v2: Remember to clean up the cached edid on destroy.

Signed-Off-by: Daniel Vetter 
---
 drivers/gpu/drm/i915/intel_crt.c   |   25 -
 drivers/gpu/drm/i915/intel_drv.h   |1 +
 drivers/gpu/drm/i915/intel_modes.c |   18 ++
 3 files changed, 35 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index a60d131..46a0716 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -47,6 +47,7 @@
 struct intel_crt {
struct intel_encoder base;
bool force_hotplug_required;
+   struct edid *cached_edid;
 };

 static struct intel_crt *intel_attached_crt(struct drm_connector *connector)
@@ -310,7 +311,7 @@ static bool intel_crt_detect_ddc(struct drm_connector 
*connector)
if (edid != NULL) {
is_digital = edid->input & DRM_EDID_INPUT_DIGITAL;
connector->display_info.raw_edid = NULL;
-   kfree(edid);
+   crt->cached_edid = edid;
}

if (!is_digital) {
@@ -452,6 +453,10 @@ intel_crt_detect(struct drm_connector *connector, bool 
force)
enum drm_connector_status status;
struct intel_load_detect_pipe tmp;

+   /* Clean the edid cache. */
+   kfree(crt->cached_edid);
+   crt->cached_edid = NULL;
+
if (I915_HAS_HOTPLUG(dev)) {
if (intel_crt_detect_hotplug(connector)) {
DRM_DEBUG_KMS("CRT detected via hotplug\n");
@@ -485,8 +490,11 @@ intel_crt_detect(struct drm_connector *connector, bool 
force)

 static void intel_crt_destroy(struct drm_connector *connector)
 {
+   struct intel_crt *crt = intel_attached_crt(connector);
+
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
+   kfree(crt->cached_edid);
kfree(connector);
 }

@@ -494,17 +502,24 @@ static int intel_crt_get_modes(struct drm_connector 
*connector)
 {
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
-   int ret;
+   struct intel_crt *crt = intel_attached_crt(connector);
+   int ret = 0;
struct i2c_adapter *i2c;

-   i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
-   ret = intel_ddc_get_modes(connector, i2c);
+   if (!crt->cached_edid) {
+   i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
+   crt->cached_edid = drm_get_edid(connector, i2c);
+   }
+
+   ret = intel_edid_get_modes(connector, crt->cached_edid);
if (ret || !IS_G4X(dev))
return ret;

/* Try to probe digital port for output in DVI-I -> VGA mode. */
i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB);
-   return intel_ddc_get_modes(connector, i2c);
+   kfree(crt->cached_edid);
+   crt->cached_edid = drm_get_edid(connector, i2c);
+   return intel_edid_get_modes(connector, crt->cached_edid);
 }

 static int intel_crt_set_property(struct drm_connector *connector,
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 3e09188..3b6f716 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -335,6 +335,7 @@ struct intel_fbc_work {
 };

 int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
+int intel_edid_get_modes(struct drm_connector *connector, struct edid *edid);
 extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus);

 extern void intel_attach_force_audio_property(struct drm_connector *connector);
diff --git a/drivers/gpu/drm/i915/intel_modes.c 
b/drivers/gpu/drm/i915/intel_modes.c
index d67ec3a..6c723d9 100644
--- a/drivers/gpu/drm/i915/intel_modes.c
+++ b/drivers/gpu/drm/i915/intel_modes.c
@@ -60,6 +60,19 @@ bool intel_ddc_probe(struct intel_encoder *intel_encoder, 
int ddc_bus)
msgs, 2) == 2;
 }

+int intel_edid_get_modes(struct drm_connector *connector,
+struct edid *edid)
+{
+   int ret;
+
+   drm_mode_connector_update_edid_property(connector, edid);
+   ret = drm_add_edid_modes(connector, edid);
+   drm_edid_to_eld(connector, edid);
+   connector->display_info.raw_edid = NULL;
+
+   return ret;
+}
+
 /**
  * intel_ddc_get_modes - get modelist from monitor
  * @connector: DRM connector device to use
@@ -75,10 +88,7 @@ int intel_ddc_get_modes(struct drm_connector *connector,

edid = drm_get_edid(connector, adapter);
if (edid) {
-   

[PATCH 09/14] drm: don't poll forced connectors

2012-05-24 Thread Daniel Vetter
Otherwise if the detect callback reports a different state than what
the user forced (rather likely), we continously annoy userspace about
a hotplug uevent.

Signed-Off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc_helper.c |4 
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c 
b/drivers/gpu/drm/drm_crtc_helper.c
index 87a45de..9214612 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -948,6 +948,10 @@ static void output_poll_execute(struct work_struct *work)
mutex_lock(>mode_config.mutex);
list_for_each_entry(connector, >mode_config.connector_list, head) {

+   /* Ignore forced connectors. */
+   if (connector->force)
+   continue;
+
/* Ignore HDP capable connectors and connectors where we don't
 * want any hotplug detection at all for polling. */
if (!connector->polled ||
-- 
1.7.7.6



[PATCH 08/14] drm: don't unnecessarily enable the polling work

2012-05-24 Thread Daniel Vetter
... by properly checking connector->polled. This doesn't matter too
much because the polling work itself gets this slightly more right and
doesn't set repoll if there's nothing to do. But we can do better.

Signed-Off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc_helper.c |6 ++
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c 
b/drivers/gpu/drm/drm_crtc_helper.c
index f17953e..87a45de 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -955,9 +955,6 @@ static void output_poll_execute(struct work_struct *work)
(connector->polled & DRM_CONNECTOR_POLL_HPD))
continue;

-   else if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | 
DRM_CONNECTOR_POLL_DISCONNECT))
-   repoll = true;
-
old_status = connector->status;
/* if we are connected and don't want to poll for disconnect
   skip it */
@@ -1000,7 +997,8 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
return;

list_for_each_entry(connector, >mode_config.connector_list, head) {
-   if (connector->polled)
+   if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
+DRM_CONNECTOR_POLL_DISCONNECT))
poll = true;
}

-- 
1.7.7.6



[PATCH 07/14] drm: don't start the poll engine in probe_single_connector

2012-05-24 Thread Daniel Vetter
Actually there's a reason this stuff is there, and it's called

commit e58f637bb96d5a0ae0919b9998b891d1ba7e47c9
Author: Chris Wilson 
Date:   Fri Aug 20 09:13:36 2010 +0100

drm/kms: Add a module parameter to disable polling

The idea has been that users can enable/disable polling at runtime. So
the quick hack has been to just re-enable the output polling if xrandr
asks for the latest state of the connectors.

The problem with that hack is that when we force connectors to another
state than what would be detected, we nicely ping-pong:
- Userspace calls probe, gets the forced state, but polling starts
  again.
- Polling notices that the state is actually different, wakes up
  userspace.
- Repeat.

As that commit already explains, the right fix would be to make the
locking more fine-grained, so that hotplug detection on one output
does not interfere with cursor updates on another crtc.

But that is way too much work. So let's just safe this gross hack by
caching the last-seen state of drm_kms_helper_poll for that driver,
and only fire up the poll engine again if it changed from off to on.

v2: Fixup the edge detection of drm_kms_helper_poll.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=49907
Tested-by: Tvrtko Ursulin 
Signed-Off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc_helper.c |7 ++-
 include/drm/drm_crtc.h|1 +
 2 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c 
b/drivers/gpu/drm/drm_crtc_helper.c
index db93e4d..f17953e 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -110,9 +110,14 @@ int drm_helper_probe_single_connector_modes(struct 
drm_connector *connector,
} else if (connector->polled & DRM_CONNECTOR_POLL_FORCE ||
   connector->status == connector_status_unknown) {
connector->status = connector->funcs->detect(connector, true);
-   drm_kms_helper_poll_enable(dev);
}

+   /* Re-enable polling in case the global poll config changed. */
+   if (drm_kms_helper_poll != dev->mode_config.poll_running)
+   drm_kms_helper_poll_enable(dev);
+
+   dev->mode_config.poll_running = drm_kms_helper_poll;
+
if (connector->status == connector_status_disconnected) {
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
connector->base.id, drm_get_connector_name(connector));
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 4417da2..fb21121 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -783,6 +783,7 @@ struct drm_mode_config {

/* output poll support */
bool poll_enabled;
+   bool poll_running;
struct delayed_work output_poll_work;

/* pointers to standard properties */
-- 
1.7.7.6



[PATCH 06/14] drm: kill unnecessary calls to connector->detect

2012-05-24 Thread Daniel Vetter
Only call that function if something has actually changed (i.e. in the
output polling or hdp handling functions) or when userspace asks for
the information and DRM_CONNECTOR_POLL_FORCE is set.

Let's see how many bugs this uncovers.

v2: Run ->detect if the current connector status is 'unknown' -
otherwise we won't ever detect the boot-up/resume state correctly.

Signed-Off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc_helper.c |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c 
b/drivers/gpu/drm/drm_crtc_helper.c
index 8ea1c1e..db93e4d 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -107,7 +107,8 @@ int drm_helper_probe_single_connector_modes(struct 
drm_connector *connector,
connector->status = connector_status_disconnected;
if (connector->funcs->force)
connector->funcs->force(connector);
-   } else {
+   } else if (connector->polled & DRM_CONNECTOR_POLL_FORCE ||
+  connector->status == connector_status_unknown) {
connector->status = connector->funcs->detect(connector, true);
drm_kms_helper_poll_enable(dev);
}
-- 
1.7.7.6



[PATCH 05/14] drm: properly init/reset connector status

2012-05-24 Thread Daniel Vetter
We need this because otherwise the improved connector code has no idea
when it needs to run the ->detect callback after boot/resume on all
connectors.

Because drm/i915 is the only driver that properly calls
mode_config_reset at resume time, this will horribly blow up
everywhere else.

Signed-Off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc.c |6 +-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index a177d0a..82eaff0 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -495,6 +495,7 @@ int drm_connector_init(struct drm_device *dev,
INIT_LIST_HEAD(>probed_modes);
INIT_LIST_HEAD(>modes);
connector->edid_blob_ptr = NULL;
+   connector->status = connector_status_unknown;

list_add_tail(>head, >mode_config.connector_list);
dev->mode_config.num_connector++;
@@ -3521,9 +3522,12 @@ void drm_mode_config_reset(struct drm_device *dev)
if (encoder->funcs->reset)
encoder->funcs->reset(encoder);

-   list_for_each_entry(connector, >mode_config.connector_list, head)
+   list_for_each_entry(connector, >mode_config.connector_list, head) {
+   connector->status = connector_status_unknown;
+
if (connector->funcs->reset)
connector->funcs->reset(connector);
+   }
 }
 EXPORT_SYMBOL(drm_mode_config_reset);

-- 
1.7.7.6



[PATCH 03/14] drm: introduce DRM_CONNECTOR_POLL_FORCE

2012-05-24 Thread Daniel Vetter
Useful for ->detect functions that have different behaviour if force
is set. This way probe_single_connector can avoid to do the expensive
edid dance on connectors where this is not needed.

I've checked through all drivers and set this flag everywhere where
the connector->detect function has different behaviour if force is
set. For nouveau and radeon I've got lost in the code traces, so I've
set this flag unconditionally.

Note that we also need to update the poll_execute function to now
also ignore connectors which have only this new flag set.

v2: Change POLL_HDP checks so that they ignore POLL_FORCE for both the
poll and the hpd handling code.

v3: Sprinkle POLL_FORCE more liberally over drivers. It should be now
everywhere where a non-intel driver can return anything else than
connector_status_connected in its detect callback.

Signed-Off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc_helper.c |6 --
 drivers/gpu/drm/exynos/exynos_drm_connector.c |2 ++
 drivers/gpu/drm/gma500/cdv_intel_crt.c|2 ++
 drivers/gpu/drm/gma500/cdv_intel_hdmi.c   |2 ++
 drivers/gpu/drm/gma500/mdfld_dsi_output.c |1 +
 drivers/gpu/drm/gma500/oaktrail_hdmi.c|2 ++
 drivers/gpu/drm/gma500/psb_intel_sdvo.c   |2 ++
 drivers/gpu/drm/i915/intel_crt.c  |3 ++-
 drivers/gpu/drm/i915/intel_tv.c   |3 ++-
 drivers/gpu/drm/nouveau/nouveau_connector.c   |1 +
 drivers/gpu/drm/radeon/radeon_connectors.c|5 +
 drivers/gpu/drm/udl/udl_connector.c   |2 ++
 drivers/staging/omapdrm/omap_connector.c  |2 ++
 include/drm/drm_crtc.h|4 
 14 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c 
b/drivers/gpu/drm/drm_crtc_helper.c
index b1d643d..8ea1c1e 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -944,7 +944,9 @@ static void output_poll_execute(struct work_struct *work)

/* Ignore HDP capable connectors and connectors where we don't
 * want any hotplug detection at all for polling. */
-   if (!connector->polled || connector->polled == 
DRM_CONNECTOR_POLL_HPD)
+   if (!connector->polled ||
+   connector->polled == DRM_CONNECTOR_POLL_FORCE ||
+   (connector->polled & DRM_CONNECTOR_POLL_HPD))
continue;

else if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | 
DRM_CONNECTOR_POLL_DISCONNECT))
@@ -1029,7 +1031,7 @@ void drm_helper_hpd_irq_event(struct drm_device *dev)
list_for_each_entry(connector, >mode_config.connector_list, head) {

/* Only handle HPD capable connectors. */
-   if (connector->polled != DRM_CONNECTOR_POLL_HPD)
+   if (!(connector->polled & DRM_CONNECTOR_POLL_HPD))
continue;

old_status = connector->status;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c 
b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index bf791fa..e5a8a27 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -327,6 +327,8 @@ struct drm_connector *exynos_drm_connector_create(struct 
drm_device *dev,
drm_connector_init(dev, connector, _connector_funcs, type);
drm_connector_helper_add(connector, _connector_helper_funcs);

+   connector->polled |= DRM_CONNECTOR_POLL_FORCE;
+
err = drm_sysfs_connector_add(connector);
if (err)
goto err_connector;
diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c 
b/drivers/gpu/drm/gma500/cdv_intel_crt.c
index 1874220..e6b2e49 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_crt.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c
@@ -313,6 +313,8 @@ void cdv_intel_crt_init(struct drm_device *dev,
drm_connector_helper_add(connector,
_intel_crt_connector_helper_funcs);

+   connector->polled |= DRM_CONNECTOR_POLL_FORCE;
+
drm_sysfs_connector_add(connector);

return;
diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c 
b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
index 88b59d4..766aec8 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
@@ -373,6 +373,8 @@ void cdv_hdmi_init(struct drm_device *dev,
hdmi_priv->hdmi_i2c_adapter =
&(psb_intel_encoder->i2c_bus->adapter);
hdmi_priv->dev = dev;
+   connector->polled |= DRM_CONNECTOR_POLL_FORCE;
+
drm_sysfs_connector_add(connector);
return;

diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c 
b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
index 5675d93..0e97a91 100644
--- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
@@ -604,6 +604,7 @@ void mdfld_dsi_output_init(struct drm_device *dev,

[PATCH 01/14] drm: extract drm_kms_helper_hotplug_event

2012-05-24 Thread Daniel Vetter
Useful if drivers want to be slightly more clever about hotplug
handling.

Signed-Off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc_helper.c |   17 +++--
 include/drm/drm_crtc_helper.h |1 +
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c 
b/drivers/gpu/drm/drm_crtc_helper.c
index 974196a..909a85c 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -918,6 +918,15 @@ int drm_helper_resume_force_mode(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_helper_resume_force_mode);

+void drm_kms_helper_hotplug_event(struct drm_device *dev)
+{
+   /* send a uevent + call fbdev */
+   drm_sysfs_hotplug_event(dev);
+   if (dev->mode_config.funcs->output_poll_changed)
+   dev->mode_config.funcs->output_poll_changed(dev);
+}
+EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
+
 #define DRM_OUTPUT_POLL_PERIOD (10*HZ)
 static void output_poll_execute(struct work_struct *work)
 {
@@ -960,12 +969,8 @@ static void output_poll_execute(struct work_struct *work)

mutex_unlock(>mode_config.mutex);

-   if (changed) {
-   /* send a uevent + call fbdev */
-   drm_sysfs_hotplug_event(dev);
-   if (dev->mode_config.funcs->output_poll_changed)
-   dev->mode_config.funcs->output_poll_changed(dev);
-   }
+   if (changed)
+   drm_kms_helper_hotplug_event(dev);

if (repoll)
queue_delayed_work(system_nrt_wq, delayed_work, 
DRM_OUTPUT_POLL_PERIOD);
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index 3add00e..9a9288d 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -141,6 +141,7 @@ extern int drm_helper_resume_force_mode(struct drm_device 
*dev);
 extern void drm_kms_helper_poll_init(struct drm_device *dev);
 extern void drm_kms_helper_poll_fini(struct drm_device *dev);
 extern void drm_helper_hpd_irq_event(struct drm_device *dev);
+extern void drm_kms_helper_hotplug_event(struct drm_device *dev);

 extern void drm_kms_helper_poll_disable(struct drm_device *dev);
 extern void drm_kms_helper_poll_enable(struct drm_device *dev);
-- 
1.7.7.6



[RFC] [PATCH 00/14] HPD/connector-polling rework

2012-05-24 Thread Daniel Vetter
Hi all,

I've got fed up with our sorry state of connector detection and rampant edid re
and rere-reading.

This patch series lays the groundwork in the drm helpers so that drivers can
avoid all this madness (at least on working hw) and properly cache the edid.

With the additional changes for drm/i915, the edid is now read _once_ per plug
event (or at boot-up/resume time). A further step would be to integrate the
hotplug handling into the driver itself and only call ->detect on the connectors
for which the irq handler received a hotplug event.

By adding POLL_FORCE drivers can get back the old behaviour of calling ->detect
every time probe_single_connector is called from userspace. I've splattered that
over all drivers where I've thought it might be required.

Note though that setting this doesn't avoid all regressions - the regular output
poll work will still ignore any connectors with POLL_HPD set. If a driver/hw
with broken hpd got away due to this, this will break stuff. But that should be
easy to fix by admitting the defeat and setting POLL_CONNECT|DISCONNECT
directly.

If other people want to convert over their drivers, the following steps are
required:
- Ensure that the connector status is unknown every time the driver could have
  missed a hpd event (e.g. after resume). drm_mode_config_reset will do that for
  you.
- Drop the POLL_FORCE flag for connectors where hdp is fully reliable.
- Implement edid caching - that's a nice way to figure out whether hpd is
  actually reliable, because if it isn't, this step will ensure that you get bug
  reports because the the edid won't ever get updated ;-)
- Optionally teach the driver some smarts about which specific connectors
  actually got a hotplug event. Mostly useful on cheap hw (like intel's) that
  can't distinguish between hdmi and dp without trying some aux channel
  transfers.

As you can guess from the patch series, I've discovered the hard way that i915
sdvo support is totally broken. Tested on most of the intel machines I have and
also quickly on my radeon hd5000.

Comments, flames, ideas and test reports highly welcome.

Cheers, Daniel

Daniel Vetter (14):
  drm: extract drm_kms_helper_hotplug_event
  drm: handle HDP and polled connectors separately
  drm: introduce DRM_CONNECTOR_POLL_FORCE
  drm/i915: set POLL_FORCE for sdvo outputs
  drm: properly init/reset connector status
  drm: kill unnecessary calls to connector->detect
  drm: don't start the poll engine in probe_single_connector
  drm: don't unnecessarily enable the polling work
  drm: don't poll forced connectors
  drm/i915: cache crt edid
  drm/i915: cache dp edid
  drm/i915: cache hdmi edid
  drm/i915/sdvo: implement correct return value for ->get_modes
  drm/i915: s/mdelay/msleep/ in the sdvo detect function

 drivers/gpu/drm/drm_crtc.c|6 ++-
 drivers/gpu/drm/drm_crtc_helper.c |   76 ++---
 drivers/gpu/drm/exynos/exynos_drm_connector.c |2 +
 drivers/gpu/drm/gma500/cdv_intel_crt.c|2 +
 drivers/gpu/drm/gma500/cdv_intel_hdmi.c   |2 +
 drivers/gpu/drm/gma500/mdfld_dsi_output.c |1 +
 drivers/gpu/drm/gma500/oaktrail_hdmi.c|2 +
 drivers/gpu/drm/gma500/psb_intel_sdvo.c   |2 +
 drivers/gpu/drm/i915/intel_crt.c  |   28 +++--
 drivers/gpu/drm/i915/intel_dp.c   |   47 +++
 drivers/gpu/drm/i915/intel_drv.h  |2 +
 drivers/gpu/drm/i915/intel_hdmi.c |   48 ++--
 drivers/gpu/drm/i915/intel_modes.c|   18 +-
 drivers/gpu/drm/i915/intel_sdvo.c |   45 +--
 drivers/gpu/drm/i915/intel_tv.c   |3 +-
 drivers/gpu/drm/nouveau/nouveau_connector.c   |1 +
 drivers/gpu/drm/radeon/radeon_connectors.c|5 ++
 drivers/gpu/drm/udl/udl_connector.c   |2 +
 drivers/staging/omapdrm/omap_connector.c  |2 +
 include/drm/drm_crtc.h|5 ++
 include/drm/drm_crtc_helper.h |1 +
 21 files changed, 208 insertions(+), 92 deletions(-)

-- 
1.7.7.6



[PATCH 5/5] drm/i915: Bad pixel formats can't reach the sprite code

2012-05-24 Thread ville.syrj...@linux.intel.com
From: Ville Syrj?l? 

The framebuffer pixel format is already checked by the common code.
So there's no way an invalid format could reach the driver. So instead
of falling back to a default format, call BUG().

Signed-off-by: Ville Syrj?l? 
---
 drivers/gpu/drm/i915/intel_sprite.c |8 ++--
 1 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sprite.c 
b/drivers/gpu/drm/i915/intel_sprite.c
index 89631ff..e2abae6 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -77,9 +77,7 @@ ivb_update_plane(struct drm_plane *plane, struct 
drm_framebuffer *fb,
sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
break;
default:
-   DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
-   sprctl |= DVS_FORMAT_RGBX888;
-   break;
+   BUG();
}

if (obj->tiling_mode != I915_TILING_NONE)
@@ -251,9 +249,7 @@ ilk_update_plane(struct drm_plane *plane, struct 
drm_framebuffer *fb,
dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
break;
default:
-   DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
-   dvscntr |= DVS_FORMAT_RGBX888;
-   break;
+   BUG();
}

if (obj->tiling_mode != I915_TILING_NONE)
-- 
1.7.3.4



[PATCH 4/5] drm/i915: pixel_size == cpp

2012-05-24 Thread ville.syrj...@linux.intel.com
From: Ville Syrj?l? 

Use drm_format_plane_cpp() to get 'pixel_size' in the sprite code.

Signed-off-by: Ville Syrj?l? 
---
 drivers/gpu/drm/i915/intel_sprite.c |   19 +++
 1 files changed, 3 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sprite.c 
b/drivers/gpu/drm/i915/intel_sprite.c
index 363a16e..89631ff 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -48,7 +48,7 @@ ivb_update_plane(struct drm_plane *plane, struct 
drm_framebuffer *fb,
struct intel_plane *intel_plane = to_intel_plane(plane);
int pipe = intel_plane->pipe;
u32 sprctl, sprscale = 0;
-   int pixel_size;
+   int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);

sprctl = I915_READ(SPRCTL(pipe));

@@ -60,32 +60,25 @@ ivb_update_plane(struct drm_plane *plane, struct 
drm_framebuffer *fb,
switch (fb->pixel_format) {
case DRM_FORMAT_XBGR:
sprctl |= SPRITE_FORMAT_RGBX888;
-   pixel_size = 4;
break;
case DRM_FORMAT_XRGB:
sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
-   pixel_size = 4;
break;
case DRM_FORMAT_YUYV:
sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
-   pixel_size = 2;
break;
case DRM_FORMAT_YVYU:
sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
-   pixel_size = 2;
break;
case DRM_FORMAT_UYVY:
sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
-   pixel_size = 2;
break;
case DRM_FORMAT_VYUY:
sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
-   pixel_size = 2;
break;
default:
DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
sprctl |= DVS_FORMAT_RGBX888;
-   pixel_size = 4;
break;
}

@@ -227,8 +220,9 @@ ilk_update_plane(struct drm_plane *plane, struct 
drm_framebuffer *fb,
struct drm_device *dev = plane->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane = to_intel_plane(plane);
-   int pipe = intel_plane->pipe, pixel_size;
+   int pipe = intel_plane->pipe;
u32 dvscntr, dvsscale;
+   int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);

dvscntr = I915_READ(DVSCNTR(pipe));

@@ -240,32 +234,25 @@ ilk_update_plane(struct drm_plane *plane, struct 
drm_framebuffer *fb,
switch (fb->pixel_format) {
case DRM_FORMAT_XBGR:
dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
-   pixel_size = 4;
break;
case DRM_FORMAT_XRGB:
dvscntr |= DVS_FORMAT_RGBX888;
-   pixel_size = 4;
break;
case DRM_FORMAT_YUYV:
dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
-   pixel_size = 2;
break;
case DRM_FORMAT_YVYU:
dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
-   pixel_size = 2;
break;
case DRM_FORMAT_UYVY:
dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
-   pixel_size = 2;
break;
case DRM_FORMAT_VYUY:
dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
-   pixel_size = 2;
break;
default:
DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
dvscntr |= DVS_FORMAT_RGBX888;
-   pixel_size = 4;
break;
}

-- 
1.7.3.4



[PATCH 3/5] drm/i915: Implement proper clipping for video sprites

2012-05-24 Thread ville.syrj...@linux.intel.com
From: Ville Syrj?l? 

Properly clip the source when the destination gets clipped
by the pipe dimensions.

Sadly the video sprite hardware is rather limited so it can't do proper
sub-pixel postitioning. Resort to a best effort approach, where the
source coordinates are rounded to the nearest (macro)pixel boundary.

Also do some additional checking against various hardware limits.

Signed-off-by: Ville Syrj?l? 
---
 drivers/gpu/drm/i915/intel_sprite.c |  170 +++
 1 files changed, 112 insertions(+), 58 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sprite.c 
b/drivers/gpu/drm/i915/intel_sprite.c
index 2a20fb0..363a16e 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -127,11 +127,14 @@ ivb_update_plane(struct drm_plane *plane, struct 
drm_framebuffer *fb,
I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
if (obj->tiling_mode != I915_TILING_NONE) {
+   y += fb->offsets[0] / fb->pitches[0];
+   x += fb->offsets[0] % fb->pitches[0] / pixel_size;
+
I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
} else {
unsigned long offset;

-   offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+   offset = fb->offsets[0] + y * fb->pitches[0] + x * pixel_size;
I915_WRITE(SPRLINOFF(pipe), offset);
}
I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
@@ -288,11 +291,14 @@ ilk_update_plane(struct drm_plane *plane, struct 
drm_framebuffer *fb,
I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
if (obj->tiling_mode != I915_TILING_NONE) {
+   y += fb->offsets[0] / fb->pitches[0];
+   x += fb->offsets[0] % fb->pitches[0] / pixel_size;
+
I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
} else {
unsigned long offset;

-   offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+   offset = fb->offsets[0] + y * fb->pitches[0] + x * pixel_size;
I915_WRITE(DVSLINOFF(pipe), offset);
}
I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
@@ -394,6 +400,20 @@ ilk_get_colorkey(struct drm_plane *plane, struct 
drm_intel_sprite_colorkey *key)
key->flags = I915_SET_COLORKEY_NONE;
 }

+static bool
+format_is_yuv(uint32_t format)
+{
+   switch (format) {
+   case DRM_FORMAT_YUYV:
+   case DRM_FORMAT_UYVY:
+   case DRM_FORMAT_VYUY:
+   case DRM_FORMAT_YVYU:
+   return true;
+   default:
+   return false;
+   }
+}
+
 static int
 intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
   struct drm_framebuffer *fb, int crtc_x, int crtc_y,
@@ -405,66 +425,98 @@ intel_update_plane(struct drm_plane *plane, struct 
drm_crtc *crtc,
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_plane *intel_plane = to_intel_plane(plane);
-   struct intel_framebuffer *intel_fb;
-   struct drm_i915_gem_object *obj, *old_obj;
+   struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+   struct drm_i915_gem_object *obj = intel_fb->obj;
+   struct drm_i915_gem_object *old_obj = intel_plane->obj;
int pipe = intel_plane->pipe;
int ret = 0;
-   int x = src_x >> 16, y = src_y >> 16;
int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay;
bool disable_primary = false;
-
-   intel_fb = to_intel_framebuffer(fb);
-   obj = intel_fb->obj;
-
-   old_obj = intel_plane->obj;
-
-   src_w = src_w >> 16;
-   src_h = src_h >> 16;
-
-   /* Pipe must be running... */
-   if (!(I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE))
-   return -EINVAL;
-
-   if (crtc_x >= primary_w || crtc_y >= primary_h)
-   return -EINVAL;
+   bool visible;
+   int hscale, vscale;
+   int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
+   struct drm_region src = {
+   .x1 = src_x,
+   .x2 = src_x + src_w,
+   .y1 = src_y,
+   .y2 = src_y + src_h,
+   };
+   struct drm_region dst = {
+   .x1 = crtc_x,
+   .x2 = crtc_x + crtc_w,
+   .y1 = crtc_y,
+   .y2 = crtc_y + crtc_h,
+   };
+   const struct drm_region clip = {
+   .x2 = crtc->mode.hdisplay,
+   .y2 = crtc->mode.vdisplay,
+   };

/* Don't modify another pipe's plane */
if (intel_plane->pipe != intel_crtc->pipe)
return -EINVAL;

-   /*
-* Clamp the width & height into the visible area.  Note we don't
-* try to scale the source if part of the visible 

[PATCH 2/5] drm: Add drm_calc_{hscale, vscale}() utility functions

2012-05-24 Thread ville.syrj...@linux.intel.com
From: Ville Syrj?l? 

Signed-off-by: Ville Syrj?l? 
---
 drivers/gpu/drm/drm_crtc.c |  102 
 include/drm/drm_crtc.h |4 ++
 2 files changed, 106 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index a14b786..d981fe2 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3992,3 +3992,105 @@ bool drm_region_clip_scaled(struct drm_region *src, 
struct drm_region *dst,
return drm_region_clip(dst, clip);
 }
 EXPORT_SYMBOL(drm_region_clip_scaled);
+
+/**
+ * drm_calc_hscale - calculate the horizontal scaling factor
+ * @src: source window region
+ * @dst: destination window region
+ * @min_hscale: minimum allowed horizontal scaling factor
+ * @max_hscale: maximum allowed horizontal scaling factor
+ *
+ * Calculate the horizontal scaling factor as
+ * (@src width) / (@dst width).
+ *
+ * If the calculated scaling factor is below @min_hscale,
+ * decrease the width of region @dst to compensate.
+ *
+ * If the calculcated scaling factor is above @max_hscale,
+ * decrease the width of region @src to compensate.
+ *
+ * RETURNS:
+ * The horizontal scaling factor.
+ */
+int drm_calc_hscale(struct drm_region *src, struct drm_region *dst,
+   int min_hscale, int max_hscale)
+{
+   int src_w = drm_region_width(src);
+   int dst_w = drm_region_width(dst);
+   int hscale;
+
+   if (dst_w <= 0)
+   return 0;
+
+   hscale = src_w / dst_w;
+
+   if (hscale < min_hscale) {
+   int max_dst_w = src_w / min_hscale;
+
+   drm_region_adjust_size(dst, max_dst_w - dst_w, 0);
+
+   return min_hscale;
+   }
+
+   if (hscale > max_hscale) {
+   int max_src_w = dst_w * max_hscale;
+
+   drm_region_adjust_size(src, max_src_w - src_w, 0);
+
+   return max_hscale;
+   }
+
+   return hscale;
+}
+EXPORT_SYMBOL(drm_calc_hscale);
+
+/**
+ * drm_calc_vscale - calculate the vertical scaling factor
+ * @src: source window region
+ * @dst: destination window region
+ * @min_vscale: minimum allowed vertical scaling factor
+ * @max_vscale: maximum allowed vertical scaling factor
+ *
+ * Calculate the vertical scaling factor as
+ * (@src height) / (@dst height).
+ *
+ * If the calculated scaling factor is below @min_vscale,
+ * decrease the height of region @dst to compensate.
+ *
+ * If the calculcated scaling factor is above @max_vscale,
+ * decrease the height of region @src to compensate.
+ *
+ * RETURNS:
+ * The vertical scaling factor.
+ */
+int drm_calc_vscale(struct drm_region *src, struct drm_region *dst,
+   int min_vscale, int max_vscale)
+{
+   int src_h = drm_region_height(src);
+   int dst_h = drm_region_height(dst);
+   int vscale;
+
+   if (dst_h <= 0)
+   return 0;
+
+   vscale = src_h / dst_h;
+
+   if (vscale < min_vscale) {
+   int max_dst_h = src_h / min_vscale;
+
+   drm_region_adjust_size(dst, 0, max_dst_h - dst_h);
+
+   return min_vscale;
+   }
+
+   if (vscale > max_vscale) {
+   int max_src_h = dst_h * max_vscale;
+
+   drm_region_adjust_size(src, 0, max_src_h - src_h);
+
+   return max_vscale;
+   }
+
+   return vscale;
+}
+EXPORT_SYMBOL(drm_calc_vscale);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index c735520..8a17cce 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1085,5 +1085,9 @@ extern bool drm_region_clip_scaled(struct drm_region *src,
   struct drm_region *dst,
   const struct drm_region *clip,
   int hscale, int vscale);
+extern int drm_calc_hscale(struct drm_region *src, struct drm_region *dst,
+  int min_hscale, int max_hscale);
+extern int drm_calc_vscale(struct drm_region *src, struct drm_region *dst,
+  int min_vscale, int max_vscale);

 #endif /* __DRM_CRTC_H__ */
-- 
1.7.3.4



[PATCH 1/5] drm: Add struct drm_region and assorted utility functions

2012-05-24 Thread ville.syrj...@linux.intel.com
From: Ville Syrj?l? 

struct drm_region represents a two dimensional region. The utility
functions are there to help driver writers.

Signed-off-by: Ville Syrj?l? 
---
 drivers/gpu/drm/drm_crtc.c |  155 
 include/drm/drm_crtc.h |   24 +++
 2 files changed, 179 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 5fc198d..a14b786 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3837,3 +3837,158 @@ int drm_format_vert_chroma_subsampling(uint32_t format)
}
 }
 EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
+
+/**
+ * drm_region_adjust_size - adjust the size of the region
+ * @r: region to be adjusted
+ * @x: horizontal adjustment
+ * @y: vertical adjustment
+ *
+ * Change the size of region @r by @x in the horizontal direction,
+ * and by @y in the vertical direction, while keeping the center
+ * of @r stationary.
+ *
+ * Positive @x and @y increase the size, negative values decrease it.
+ */
+void drm_region_adjust_size(struct drm_region *r, int x, int y)
+{
+   r->x1 -= x >> 1;
+   r->y1 -= y >> 1;
+   r->x2 += (x + 1) >> 1;
+   r->y2 += (y + 1) >> 1;
+}
+EXPORT_SYMBOL(drm_region_adjust_size);
+
+/**
+ * drm_region_translate - translate the region
+ * @r: region to be tranlated
+ * @x: horizontal translation
+ * @y: vertical translation
+ *
+ * Move region @r by @x in the horizontal direction,
+ * and by @y in the vertical direction.
+ */
+void drm_region_translate(struct drm_region *r, int x, int y)
+{
+   r->x1 += x;
+   r->y1 += y;
+   r->x2 += x;
+   r->y2 += y;
+}
+EXPORT_SYMBOL(drm_region_translate);
+
+/**
+ * drm_region_subsample - subsample a region
+ * @r: region to be subsampled
+ * @hsub: horizontal subsampling factor
+ * @vsub: vertical subsampling factor
+ *
+ * Divide the coordinates of region @r by @hsub and @vsub.
+ */
+void drm_region_subsample(struct drm_region *r, int hsub, int vsub)
+{
+   r->x1 /= hsub;
+   r->y1 /= vsub;
+   r->x2 /= hsub;
+   r->y2 /= vsub;
+}
+EXPORT_SYMBOL(drm_region_subsample);
+
+/**
+ * drm_region_width - determine the region width
+ * @r: region whose width is returned
+ *
+ * RETURNS:
+ * The width of the region.
+ */
+int drm_region_width(const struct drm_region *r)
+{
+   return r->x2 - r->x1;
+}
+EXPORT_SYMBOL(drm_region_width);
+
+/**
+ * drm_region_height - determine the region height
+ * @r: region whose height is returned
+ *
+ * RETURNS:
+ * The height of the region.
+ */
+int drm_region_height(const struct drm_region *r)
+{
+   return r->y2 - r->y1;
+}
+EXPORT_SYMBOL(drm_region_height);
+
+/**
+ * drm_region_visible - determine if the the region is visible
+ * @r: region whose visibility is returned
+ *
+ * RETURNS:
+ * @true if the region is visible, @false otherwise.
+ */
+bool drm_region_visible(const struct drm_region *r)
+{
+   return drm_region_width(r) > 0 && drm_region_height(r) > 0;
+}
+EXPORT_SYMBOL(drm_region_visible);
+
+/**
+ * drm_region_clip - clip one region by another region
+ * @r: region to be clipped
+ * @clip: clip region
+ *
+ * Clip region @r by region @clip.
+ *
+ * RETURNS:
+ * @true if the region is still visible after being clipped,
+ * @false otherwise.
+ */
+bool drm_region_clip(struct drm_region *r, const struct drm_region *clip)
+{
+   r->x1 = max(r->x1, clip->x1);
+   r->y1 = max(r->y1, clip->y1);
+   r->x2 = min(r->x2, clip->x2);
+   r->y2 = min(r->y2, clip->y2);
+
+   return drm_region_visible(r);
+}
+EXPORT_SYMBOL(drm_region_clip);
+
+/**
+ * drm_region_clip_scaled - perform a scaled clip operation
+ * @src: source window region
+ * @dst: destination window region
+ * @clip: clip region
+ * @hscale: horizontal scaling factor
+ * @vscale: vertical scaling factor
+ *
+ * Clip region @dst by region @clip. Clip region @src by the same
+ * amounts multiplied by @hscale and @vscale.
+ *
+ * RETUTRNS:
+ * @true if region @dst is still visible after being clipped,
+ * @false otherwise
+ */
+bool drm_region_clip_scaled(struct drm_region *src, struct drm_region *dst,
+   const struct drm_region *clip,
+   int hscale, int vscale)
+{
+   int diff;
+
+   diff = clip->x1 - dst->x1;
+   if (diff > 0)
+   src->x1 += diff * hscale;
+   diff = clip->y1 - dst->y1;
+   if (diff > 0)
+   src->y1 += diff * vscale;
+   diff = dst->x2 - clip->x2;
+   if (diff > 0)
+   src->x2 -= diff * hscale;
+   diff = dst->y2 - clip->y2;
+   if (diff > 0)
+   src->y2 -= diff * vscale;
+
+   return drm_region_clip(dst, clip);
+}
+EXPORT_SYMBOL(drm_region_clip_scaled);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 73e4560..c735520 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1062,4 +1062,28 @@ extern int 

[PATCH 0/5] drm/i915: Clip video sprites properly

2012-05-24 Thread ville.syrj...@linux.intel.com
First add a bit of helper functions to aid in the clipping duties
(those patches were already posted a long time ago) and then utilize
them to properly clip the video sprites to the pipe dimensions.

I also threw in a few small cleanup patches dealing with the sprite code.


[PATCH 6/6] drm/i915: Reject page flips with changed format/offset/pitch

2012-05-24 Thread ville.syrj...@linux.intel.com
From: Ville Syrj?l? 

MI display flips can't handle some changes in the framebuffer
format or layout. Return an error in such cases.

Signed-off-by: Ville Syrj?l? 
---
 drivers/gpu/drm/i915/intel_display.c |   13 +
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index f4338cb..72ac2f9 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6217,6 +6217,19 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
unsigned long flags;
int ret;

+   /* Can't change pixel format via MI display flips. */
+   if (fb->pixel_format != crtc->fb->pixel_format)
+   return -EINVAL;
+
+   /*
+* TILEOFF/LINOFF registers can't be changed via MI display flips.
+* Note that pitch changes could also affect these register.
+*/
+   if (INTEL_INFO(dev)->gen > 3 &&
+   (fb->offsets[0] != crtc->fb->offsets[0] ||
+fb->pitches[0] != crtc->fb->pitches[0]))
+   return -EINVAL;
+
work = kzalloc(sizeof *work, GFP_KERNEL);
if (work == NULL)
return -ENOMEM;
-- 
1.7.3.4



[PATCH 5/6] drm/i915: Handle framebuffer offsets[]

2012-05-24 Thread ville.syrj...@linux.intel.com
From: Ville Syrj?l? 

Take fb->offset[0] into account when calculating the linear and tile x/y
offsets.

For non-tiled surfaces fb->offset[0] is simply added to the linear
byte offset.

For tiled surfaces treat fb->offsets[0] as a byte offset into the
linearized view of the surface. So we end up converting fb->offsets[0]
into additional x and y offsets.

Signed-off-by: Ville Syrj?l? 
---
 drivers/gpu/drm/i915/intel_display.c |   15 +++
 1 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 9df15ee..f4338cb 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1826,6 +1826,7 @@ static int i9xx_update_plane(struct drm_crtc *crtc, 
struct drm_framebuffer *fb,
unsigned long Start, Offset;
u32 dspcntr;
u32 reg;
+   unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);

switch (plane) {
case 0:
@@ -1885,12 +1886,14 @@ static int i9xx_update_plane(struct drm_crtc *crtc, 
struct drm_framebuffer *fb,
I915_WRITE(reg, dspcntr);

Start = obj->gtt_offset;
-   Offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+   Offset = fb->offsets[0] + y * fb->pitches[0] + x * cpp;

DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
  Start, Offset, x, y, fb->pitches[0]);
I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
if (INTEL_INFO(dev)->gen >= 4) {
+   y += fb->offsets[0] / fb->pitches[0];
+   x += fb->offsets[0] % fb->pitches[0] / cpp;
I915_MODIFY_DISPBASE(DSPSURF(plane), Start);
I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
I915_WRITE(DSPADDR(plane), Offset);
@@ -1913,6 +1916,7 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
unsigned long Start, Offset;
u32 dspcntr;
u32 reg;
+   unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);

switch (plane) {
case 0:
@@ -1970,7 +1974,10 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
I915_WRITE(reg, dspcntr);

Start = obj->gtt_offset;
-   Offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+   Offset = fb->offsets[0] + y * fb->pitches[0] + x * cpp;
+
+   y += fb->offsets[0] / fb->pitches[0];
+   x += fb->offsets[0] % fb->pitches[0] / cpp;

DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
  Start, Offset, x, y, fb->pitches[0]);
@@ -5993,7 +6000,7 @@ static int intel_gen2_queue_flip(struct drm_device *dev,
goto err;

/* Offset into the new buffer for cases of shared fbs between CRTCs */
-   offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8;
+   offset = fb->offsets[0] + crtc->y * fb->pitches[0] + crtc->x * 
fb->bits_per_pixel/8;

ret = intel_ring_begin(ring, 6);
if (ret)
@@ -6039,7 +6046,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev,
goto err;

/* Offset into the new buffer for cases of shared fbs between CRTCs */
-   offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8;
+   offset = fb->offsets[0] + crtc->y * fb->pitches[0] + crtc->x * 
fb->bits_per_pixel/8;

ret = intel_ring_begin(ring, 6);
if (ret)
-- 
1.7.3.4



[PATCH 4/6] drm/i915: Check the framebuffer offset

2012-05-24 Thread ville.syrj...@linux.intel.com
From: Ville Syrj?l? 

The framebuffer offset must be aligned to (macro)pixel size.

Signed-off-by: Ville Syrj?l? 
---
 drivers/gpu/drm/i915/intel_display.c |5 +
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 8fea475..9df15ee 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6660,6 +6660,7 @@ int intel_framebuffer_init(struct drm_device *dev,
   struct drm_i915_gem_object *obj)
 {
int ret;
+   unsigned int align = drm_format_plane_cpp(mode_cmd->pixel_format, 0);

if (obj->tiling_mode == I915_TILING_Y)
return -EINVAL;
@@ -6699,6 +6700,7 @@ int intel_framebuffer_init(struct drm_device *dev,
case DRM_FORMAT_UYVY:
case DRM_FORMAT_YVYU:
case DRM_FORMAT_VYUY:
+   align <<= 1;
if (INTEL_INFO(dev)->gen < 6)
return -EINVAL;
break;
@@ -6707,6 +6709,9 @@ int intel_framebuffer_init(struct drm_device *dev,
return -EINVAL;
}

+   if (mode_cmd->offsets[0] % align)
+   return -EINVAL;
+
ret = drm_framebuffer_init(dev, _fb->base, _fb_funcs);
if (ret) {
DRM_ERROR("framebuffer init failed %d\n", ret);
-- 
1.7.3.4



[PATCH 3/6] drm/i915: Zero initialize mode_cmd

2012-05-24 Thread ville.syrj...@linux.intel.com
From: Ville Syrj?l? 

Zero initialize the mode_cmd structure when creating the kernel
framebuffer. Avoids having uninitialized data in offsets[0] for
instance.

Signed-off-by: Ville Syrj?l? 
---
 drivers/gpu/drm/i915/intel_fb.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index bf86907..07404ac 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -65,7 +65,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
struct drm_i915_private *dev_priv = dev->dev_private;
struct fb_info *info;
struct drm_framebuffer *fb;
-   struct drm_mode_fb_cmd2 mode_cmd;
+   struct drm_mode_fb_cmd2 mode_cmd = {};
struct drm_i915_gem_object *obj;
struct device *device = >pdev->dev;
int size, ret;
-- 
1.7.3.4



[PATCH 2/6] drm/i915: Check framebuffer stride more thoroughly

2012-05-24 Thread ville.syrj...@linux.intel.com
From: Ville Syrj?l? 

Make sure the the framebuffer stride is smaller than the maximum
accepted by any plane.

Also when using a tiled memory make sure the object stride matches
the framebuffer stride.

Signed-off-by: Ville Syrj?l? 
---
 drivers/gpu/drm/i915/intel_display.c |   18 ++
 1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 7cf639c..8fea475 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6643,6 +6643,17 @@ static const struct drm_framebuffer_funcs intel_fb_funcs 
= {
.create_handle = intel_user_framebuffer_create_handle,
 };

+static unsigned int intel_max_fb_stride(const struct drm_device *dev)
+{
+   /* FIXME: BSpec for pre-Gen5 is a bit unclear on stride limits */
+   if (INTEL_INFO(dev)->gen <= 3)
+   return 8192;
+   else if (INTEL_INFO(dev)->gen <= 4)
+   return 16384;
+   else
+   return 32768;
+}
+
 int intel_framebuffer_init(struct drm_device *dev,
   struct intel_framebuffer *intel_fb,
   struct drm_mode_fb_cmd2 *mode_cmd,
@@ -6656,6 +6667,13 @@ int intel_framebuffer_init(struct drm_device *dev,
if (mode_cmd->pitches[0] & 63)
return -EINVAL;

+   if (mode_cmd->pitches[0] > intel_max_fb_stride(dev))
+   return -EINVAL;
+
+   if (obj->tiling_mode != I915_TILING_NONE &&
+   mode_cmd->pitches[0] != obj->stride)
+   return -EINVAL;
+
/* Reject formats not supported by any plane early. */
switch (mode_cmd->pixel_format) {
case DRM_FORMAT_C8:
-- 
1.7.3.4



[PATCH 1/6] drm/i915: Fix display pixel format handling

2012-05-24 Thread ville.syrj...@linux.intel.com
From: Ville Syrj?l? 

Fix support for all RGB/BGR pixel formats (except the 16:16:16:16 float
format).

Fix intel_init_framebuffer() to match hardware and driver limitations:
* RGB332 is not supported at all
* CI8 is supported
* XRGB1555 & co. are supported on Gen3 and earlier
* XRGB210101010 & co. are supported from Gen4 onwards
* BGR formats are supported from Gen4 onwards
* YUV formats are supported from Gen6 onwards (driver limitation)

Signed-off-by: Ville Syrj?l? 
---
 drivers/gpu/drm/i915/i915_reg.h  |   17 --
 drivers/gpu/drm/i915/intel_display.c |   98 ++
 2 files changed, 76 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2d49b95..845e5cb 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2855,12 +2855,19 @@
 #define   DISPPLANE_GAMMA_ENABLE   (1<<30)
 #define   DISPPLANE_GAMMA_DISABLE  0
 #define   DISPPLANE_PIXFORMAT_MASK (0xf<<26)
+#define   DISPPLANE_YUV422 (0x0<<26)
 #define   DISPPLANE_8BPP   (0x2<<26)
-#define   DISPPLANE_15_16BPP   (0x4<<26)
-#define   DISPPLANE_16BPP  (0x5<<26)
-#define   DISPPLANE_32BPP_NO_ALPHA (0x6<<26)
-#define   DISPPLANE_32BPP  (0x7<<26)
-#define   DISPPLANE_32BPP_30BIT_NO_ALPHA   (0xa<<26)
+#define   DISPPLANE_BGRA555(0x3<<26)
+#define   DISPPLANE_BGRX555(0x4<<26)
+#define   DISPPLANE_BGRX565(0x5<<26)
+#define   DISPPLANE_BGRX888(0x6<<26)
+#define   DISPPLANE_BGRA888(0x7<<26)
+#define   DISPPLANE_RGBX101010 (0x8<<26)
+#define   DISPPLANE_RGBA101010 (0x9<<26)
+#define   DISPPLANE_BGRX101010 (0xa<<26)
+#define   DISPPLANE_RGBX161616 (0xc<<26)
+#define   DISPPLANE_RGBX888(0xe<<26)
+#define   DISPPLANE_RGBA888(0xf<<26)
 #define   DISPPLANE_STEREO_ENABLE  (1<<25)
 #define   DISPPLANE_STEREO_DISABLE 0
 #define   DISPPLANE_SEL_PIPE_SHIFT 24
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index ee61ad1..7cf639c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1843,24 +1843,38 @@ static int i9xx_update_plane(struct drm_crtc *crtc, 
struct drm_framebuffer *fb,
dspcntr = I915_READ(reg);
/* Mask out pixel format bits in case we change it */
dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
-   switch (fb->bits_per_pixel) {
-   case 8:
+   switch (fb->pixel_format) {
+   case DRM_FORMAT_C8:
dspcntr |= DISPPLANE_8BPP;
break;
-   case 16:
-   if (fb->depth == 15)
-   dspcntr |= DISPPLANE_15_16BPP;
-   else
-   dspcntr |= DISPPLANE_16BPP;
-   break;
-   case 24:
-   case 32:
-   dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+   case DRM_FORMAT_XRGB1555:
+   case DRM_FORMAT_ARGB1555:
+   dspcntr |= DISPPLANE_BGRX555;
+   break;
+   case DRM_FORMAT_RGB565:
+   dspcntr |= DISPPLANE_BGRX565;
+   break;
+   case DRM_FORMAT_XRGB:
+   case DRM_FORMAT_ARGB:
+   dspcntr |= DISPPLANE_BGRX888;
+   break;
+   case DRM_FORMAT_XBGR:
+   case DRM_FORMAT_ABGR:
+   dspcntr |= DISPPLANE_RGBX888;
+   break;
+   case DRM_FORMAT_XRGB2101010:
+   case DRM_FORMAT_ARGB2101010:
+   dspcntr |= DISPPLANE_BGRX101010;
+   break;
+   case DRM_FORMAT_XBGR2101010:
+   case DRM_FORMAT_ABGR2101010:
+   dspcntr |= DISPPLANE_RGBX101010;
break;
default:
-   DRM_ERROR("Unknown color depth %d\n", fb->bits_per_pixel);
+   DRM_ERROR("Unknown pixel format 0x%08x\n", fb->pixel_format);
return -EINVAL;
}
+
if (INTEL_INFO(dev)->gen >= 4) {
if (obj->tiling_mode != I915_TILING_NONE)
dspcntr |= DISPPLANE_TILED;
@@ -1917,27 +1931,31 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
dspcntr = I915_READ(reg);
/* Mask out pixel format bits in case we change it */
dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
-   switch (fb->bits_per_pixel) {
-   case 8:
+   switch (fb->pixel_format) {
+   case DRM_FORMAT_C8:
dspcntr |= DISPPLANE_8BPP;
break;
-   case 16:
-   if (fb->depth != 16)
-   return -EINVAL;
-
-   dspcntr |= DISPPLANE_16BPP;
-   break;
-   case 24:
-   case 32:
-   if 

[PATCH 0/6] drm/i915: Framebuffer layout fixes and sanity checks

2012-05-24 Thread ville.syrj...@linux.intel.com
Add all kinds of framebuffer layout sanity checks to the code.

Also the framebuffer offset wasn't properly handled, and code dealing
with the primary plane pixel format was quite broken.


[PATCH 2/3] drm: Be more paranoid with integer overflows

2012-05-24 Thread Daniel Vetter
On Thu, May 24, 2012 at 09:54:37PM +0300, Ville Syrj?l? wrote:
> On Thu, May 24, 2012 at 08:30:23PM +0200, Daniel Vetter wrote:
> > On Thu, May 24, 2012 at 08:53:59PM +0300, ville.syrjala at linux.intel.com 
> > wrote:
> > > From: Ville Syrj?l? 
> > > 
> > > Make sure 'width * cpp' and 'height * pitch + offset' don't exceed
> > > UINT_MAX.
> > > 
> > > Signed-off-by: Ville Syrj?l? 
> > > ---
> > >  drivers/gpu/drm/drm_crtc.c |   10 +-
> > >  1 files changed, 9 insertions(+), 1 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> > > index 80a34e7..e1b53fb 100644
> > > --- a/drivers/gpu/drm/drm_crtc.c
> > > +++ b/drivers/gpu/drm/drm_crtc.c
> > > @@ -2211,13 +2211,21 @@ static int framebuffer_check(struct 
> > > drm_mode_fb_cmd2 *r)
> > >  
> > >   for (i = 0; i < num_planes; i++) {
> > >   unsigned int width = r->width / (i != 0 ? hsub : 1);
> > > + unsigned int height = r->height / (i != 0 ? vsub : 1);
> > > + unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
> > >  
> > >   if (!r->handles[i]) {
> > >   DRM_DEBUG_KMS("no buffer object handle for plane %d\n", 
> > > i);
> > >   return -EINVAL;
> > >   }
> > >  
> > > - if (r->pitches[i] < drm_format_plane_cpp(r->pixel_format, i) * 
> > > width) {
> > > + if ((uint64_t) width * cpp > UINT_MAX)
> > > + return -ERANGE;
> > > +
> > 
> > iirc that blows up on 32bit because gcc likes to use a compiler built-in.
> 
> I think that problem only happens w/ 64bit divs, which is why you have 
> do_div()
> and friends. At least with a small test app 'gcc -O2 -m32' generates the 
> obvious
> mul+cmp code, and mul+add+adc+cmp for the case w/ offsets[i] added. Maybe 
> other
> archs can't do it so neatly though.

Ah right, I've mixed things up. Sorry for the noise.
-Daniel
-- 
Daniel Vetter
Mail: daniel at ffwll.ch
Mobile: +41 (0)79 365 57 48


[Intel-gfx] [PATCH 5/6] drm/i915: Handle framebuffer offsets[]

2012-05-24 Thread Daniel Vetter
On Thu, May 24, 2012 at 09:49:15PM +0300, Ville Syrj?l? wrote:
> On Thu, May 24, 2012 at 11:31:32AM -0700, Jesse Barnes wrote:
> > On Thu, 24 May 2012 21:08:58 +0300
> > ville.syrjala at linux.intel.com wrote:
> > 
> > > From: Ville Syrj?l? 
> > > 
> > > Take fb->offset[0] into account when calculating the linear and tile x/y
> > > offsets.
> > > 
> > > For non-tiled surfaces fb->offset[0] is simply added to the linear
> > > byte offset.
> > > 
> > > For tiled surfaces treat fb->offsets[0] as a byte offset into the
> > > linearized view of the surface. So we end up converting fb->offsets[0]
> > > into additional x and y offsets.
> > 
> > Do you have code using a non-zero offsets[0]?  At least for current
> > code that would indicate some kind of problem... though hopefully we'll
> > be adding planar support back again sometime soon.
> 
> I did have some test app that used offsets[] at some point, but tbh I
> didn't excercise these changes with it.
> 
> I have a sort of semi working skeleton of a test app which I just modify
> for various use cases as need arises. I really should try to clean it up
> a bit and generalize it so that it wouldn't need constant code changes
> to test different scenarios.

Yeah, I want these little test apps as testcases in i-g-t.
-Daniel
-- 
Daniel Vetter
Mail: daniel at ffwll.ch
Mobile: +41 (0)79 365 57 48


[PATCH 3/3] drm: Constify params to format_check() and framebuffer_checks()

2012-05-24 Thread ville.syrj...@linux.intel.com
From: Ville Syrj?l? 

Signed-off-by: Ville Syrj?l? 
---
 drivers/gpu/drm/drm_crtc.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index e1b53fb..5fc198d 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2116,7 +2116,7 @@ out:
return ret;
 }

-static int format_check(struct drm_mode_fb_cmd2 *r)
+static int format_check(const struct drm_mode_fb_cmd2 *r)
 {
uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;

@@ -2185,7 +2185,7 @@ static int format_check(struct drm_mode_fb_cmd2 *r)
}
 }

-static int framebuffer_check(struct drm_mode_fb_cmd2 *r)
+static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
 {
int ret, hsub, vsub, num_planes, i;

-- 
1.7.3.4



[PATCH 2/3] drm: Be more paranoid with integer overflows

2012-05-24 Thread ville.syrj...@linux.intel.com
From: Ville Syrj?l? 

Make sure 'width * cpp' and 'height * pitch + offset' don't exceed
UINT_MAX.

Signed-off-by: Ville Syrj?l? 
---
 drivers/gpu/drm/drm_crtc.c |   10 +-
 1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 80a34e7..e1b53fb 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2211,13 +2211,21 @@ static int framebuffer_check(struct drm_mode_fb_cmd2 *r)

for (i = 0; i < num_planes; i++) {
unsigned int width = r->width / (i != 0 ? hsub : 1);
+   unsigned int height = r->height / (i != 0 ? vsub : 1);
+   unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);

if (!r->handles[i]) {
DRM_DEBUG_KMS("no buffer object handle for plane %d\n", 
i);
return -EINVAL;
}

-   if (r->pitches[i] < drm_format_plane_cpp(r->pixel_format, i) * 
width) {
+   if ((uint64_t) width * cpp > UINT_MAX)
+   return -ERANGE;
+
+   if ((uint64_t) height * r->pitches[i] + r->offsets[i] > 
UINT_MAX)
+   return -ERANGE;
+
+   if (r->pitches[i] < width * cpp) {
DRM_DEBUG_KMS("bad pitch %u for plane %d\n", 
r->pitches[i], i);
return -EINVAL;
}
-- 
1.7.3.4



[PATCH 1/3] drm: Use stdint types for consistency

2012-05-24 Thread ville.syrj...@linux.intel.com
From: Ville Syrj?l? 

The rest of the code uses stdint types, so use them in
drm_property_change_is_valid() as well.

Signed-off-by: Ville Syrj?l? 
---
 drivers/gpu/drm/drm_crtc.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 92cea9d..80a34e7 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3126,7 +3126,7 @@ int drm_mode_connector_update_edid_property(struct 
drm_connector *connector,
 EXPORT_SYMBOL(drm_mode_connector_update_edid_property);

 static bool drm_property_change_is_valid(struct drm_property *property,
-__u64 value)
+uint64_t value)
 {
if (property->flags & DRM_MODE_PROP_IMMUTABLE)
return false;
@@ -3136,7 +3136,7 @@ static bool drm_property_change_is_valid(struct 
drm_property *property,
return true;
} else if (property->flags & DRM_MODE_PROP_BITMASK) {
int i;
-   __u64 valid_mask = 0;
+   uint64_t valid_mask = 0;
for (i = 0; i < property->num_values; i++)
valid_mask |= (1ULL << property->values[i]);
return !(value & ~valid_mask);
-- 
1.7.3.4



[PATCH 0/3] drm: A few misc patches

2012-05-24 Thread ville.syrj...@linux.intel.com
Just a few small items caught in my net while trawling the code.


[PATCH 0/4] drm/i915: Make video sprites survive a modeset

2012-05-24 Thread Daniel Vetter
On Thu, May 24, 2012 at 11:35:35AM -0700, Jesse Barnes wrote:
> On Thu, 24 May 2012 21:29:46 +0300
> ville.syrjala at linux.intel.com wrote:
> 
> > Currently the video sprites appear to get disabled on modeset more by
> > accient than by design.
> > 
> > With the current API that behaviour makes very little sense to me.
> > You first enable some plane, and then it can get disabled due to some
> > unrelated operation.
> > 
> > So these patches change the behaviour so that planes survive a modeset.
> > There's a new hook to make sure they get disabled when swithing
> > back to fbdev to show a panic oops.
> 
> Yeah that's not really a design requirement; the assumption was that
> the display manager would do the right thing in any case (both mode
> sets and plane sets are privileged ops).  When doing a mode set, the
> plane parameters will probably need to be changed anyway...
> 
> But keeping it on with some kind of sensible behavior makes the simple
> cases easier.

tbh I don't see the use-case. If you issue a modeset from userspace, you
better start out with something sensible (like a black screeen) and fade
in nicely whatever you want to show. And if you change the layout, you
have to reorg everything anyway.

We do though do a few modesets from within the kernel (e.g. audio property
on hdmi/dp), and I guess these should forget about any currently visible
planes. Dunno what to do here.
-Daniel
-- 
Daniel Vetter
Mail: daniel at ffwll.ch
Mobile: +41 (0)79 365 57 48


[PATCH 2/3] drm: Be more paranoid with integer overflows

2012-05-24 Thread Daniel Vetter
On Thu, May 24, 2012 at 08:53:59PM +0300, ville.syrjala at linux.intel.com 
wrote:
> From: Ville Syrj?l? 
> 
> Make sure 'width * cpp' and 'height * pitch + offset' don't exceed
> UINT_MAX.
> 
> Signed-off-by: Ville Syrj?l? 
> ---
>  drivers/gpu/drm/drm_crtc.c |   10 +-
>  1 files changed, 9 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 80a34e7..e1b53fb 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -2211,13 +2211,21 @@ static int framebuffer_check(struct drm_mode_fb_cmd2 
> *r)
>  
>   for (i = 0; i < num_planes; i++) {
>   unsigned int width = r->width / (i != 0 ? hsub : 1);
> + unsigned int height = r->height / (i != 0 ? vsub : 1);
> + unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
>  
>   if (!r->handles[i]) {
>   DRM_DEBUG_KMS("no buffer object handle for plane %d\n", 
> i);
>   return -EINVAL;
>   }
>  
> - if (r->pitches[i] < drm_format_plane_cpp(r->pixel_format, i) * 
> width) {
> + if ((uint64_t) width * cpp > UINT_MAX)
> + return -ERANGE;
> +

iirc that blows up on 32bit because gcc likes to use a compiler built-in.
And the usual pattern I've seen is if (UINT_MAX / a < b) return -ERANGE;
-Daniel

> + if ((uint64_t) height * r->pitches[i] + r->offsets[i] > 
> UINT_MAX)
> + return -ERANGE;
> +
> + if (r->pitches[i] < width * cpp) {
>   DRM_DEBUG_KMS("bad pitch %u for plane %d\n", 
> r->pitches[i], i);
>   return -EINVAL;
>   }
> -- 
> 1.7.3.4
> 
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Mail: daniel at ffwll.ch
Mobile: +41 (0)79 365 57 48


[Bug 50232] screen redraw is wrong in sauerbraten with the llvm compiler

2012-05-24 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=50232

--- Comment #2 from almos  2012-05-24 13:25:38 PDT ---
(In reply to comment #1)
> Please test with the first patch from bug 50230.
The revert patch fixes the ghost image problem. The warning is still printed,
but the visuals seem to be good now.

-- 
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are the assignee for the bug.


[Bug 50230] offset mapping in nexuiz results in bad texturing with the llvm compiler

2012-05-24 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=50230

--- Comment #10 from almos  2012-05-24 13:25:32 PDT ---
(In reply to comment #9)
> Created attachment 62057 [details] [review]
> [PATCH] radeon/llvm: fix sampler index in llvm_emit_tex
> 
> Does this patch help?
Yes, the patch fixes it. I also tried the revert patch, and that fixes the
lightmap flickering.

-- 
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are the assignee for the bug.


drm/nouveau: NULL pointer deref in drm_handle_vblank() on rebind

2012-05-24 Thread Bruno Prémont
I can easily trigger a crash in nouveau interrupt handler by unbinding
and rebinding the GPU.

The command used:
  echo $pci_device > nouveau/unbind && \
sleep 5 && \
echo $pci_device > nouveau/bind


Kernel is 3.4.0 with modular drm/nouveau.
GPU is NVidia nForce IGP (NV11)


Unbinding seems to work fine, display switching back to VGA text mode.
Rebinding the GPU slightly later causes the below trace:

Bruno

(analysis following below trace)

[ 1432.012832] Console: switching to colour VGA+ 80x25
[ 1432.014796] drm: unregistered panic notifier
[ 1432.014905] [drm] nouveau :02:00.0: Setting dpms mode 3 on vga encoder 
(output 0)
[ 1432.026324] [drm] nouveau :02:00.0: 0xAFD8: Parsing digital output 
script table
[ 1432.026611] [drm] nouveau :02:00.0: Restoring VGA fonts
[ 1432.028353] [TTM] Finalizing pool allocator
[ 1432.029325] [TTM] Zone  kernel: Used memory at exit: 0 kiB
[ 1437.066950] [drm] nouveau :02:00.0: Detected an NV10 generation card 
(0x01a000b1)
[ 1437.068909] [drm] nouveau :02:00.0: Checking PRAMIN for VBIOS
[ 1437.103400] [drm] nouveau :02:00.0: ... BIOS checksum invalid
[ 1437.103459] [drm] nouveau :02:00.0: Checking PROM for VBIOS
[ 1437.103638] [drm] nouveau :02:00.0: ... BIOS checksum invalid
[ 1437.103694] [drm] nouveau :02:00.0: Checking ACPI for VBIOS
[ 1437.103859] [drm] nouveau :02:00.0: ... BIOS checksum invalid
[ 1437.103915] [drm] nouveau :02:00.0: Checking PCIROM for VBIOS
[ 1437.105143] [drm] nouveau :02:00.0: ... appears to be valid
[ 1437.105217] [drm] nouveau :02:00.0: Using VBIOS from PCIROM
[ 1437.105507] [drm] nouveau :02:00.0: BMP BIOS found
[ 1437.105562] [drm] nouveau :02:00.0: BMP version 5.20
[ 1437.105624] [drm] nouveau :02:00.0: Bios version 03.1a.01.03
[ 1437.107663] [drm] nouveau :02:00.0: MXM: no VBIOS data, nothing to do
[ 1437.109053] [drm] nouveau :02:00.0: Parsing VBIOS init table 0 at offset 
0xA850
[ 1437.109120] [drm] nouveau :02:00.0: Parsing VBIOS init table 1 at offset 
0xADC5
[ 1437.109197] [drm] nouveau :02:00.0: Parsing VBIOS init table 2 at offset 
0xA851
[ 1437.109268] [drm] nouveau :02:00.0: Parsing VBIOS init table 3 at offset 
0xADC4
[ 1437.109337] [drm] nouveau :02:00.0: Parsing VBIOS init table 4 at offset 
0xA875
[ 1437.109405] [drm] nouveau :02:00.0: Parsing VBIOS init table 5 at offset 
0xA931
[ 1437.109494] [drm] nouveau :02:00.0: Parsing VBIOS init table 6 at offset 
0xA876
[ 1437.109572] [drm] nouveau :02:00.0: Parsing VBIOS init table 7 at offset 
0xA8CC
[ 1437.109985] [TTM] Zone  kernel: Available graphics memory: 240004 kiB
[ 1437.110079] [TTM] Initializing pool allocator
[ 1437.110177] [drm] nouveau :02:00.0: Detected 32MiB VRAM (unknown type)
[ 1437.110424] agpgart-nvidia :00:00.0: AGP 2.0 bridge
[ 1437.110566] agpgart-nvidia :00:00.0: putting AGP V2 device into 4x mode
[ 1437.110717] nouveau :02:00.0: putting AGP V2 device into 4x mode
[ 1437.110783] agpgart-nvidia :00:00.0: AGP 2.0 bridge
[ 1437.110865] agpgart-nvidia :00:00.0: putting AGP V2 device into 4x mode
[ 1437.111010] nouveau :02:00.0: putting AGP V2 device into 4x mode
[ 1437.111070] [drm] nouveau :02:00.0: 32 MiB GART (aperture)
[ 1437.111233] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.111298] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.111363] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.111427] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.111489] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.111551] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.111613] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.111676] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.111737] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.111800] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.111862] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.111924] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.111986] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.112048] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.112110] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.112172] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.112233] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.112296] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.112357] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.112420] [drm] nouveau :02:00.0: PMC - unhandled INTR 0x0100
[ 1437.112577] [drm] nouveau :02:00.0: Saving VGA fonts
[ 1437.175978] BUG: unable to handle kernel NULL pointer dereference at   (null)
[ 1437.176134] IP: [] drm_handle_vblank+0x3c/0x1d0
[ 1437.176314] *pde =  
[ 

[git pull] drm merge window pull

2012-05-24 Thread Dave Airlie

Hi Linus,

this is the main merge window request for the drm,

Its big, but jam packed will lots of features and of course 0 regressions. 
(okay maybe there'll be one).

Highlights:
new KMS drivers for server GPU chipsets: ast, mgag200 and cirrus (qemu 
only). These drivers use the generic modesetting drivers.
initial prime/dma-buf support for i915, nouveau, radeon, udl and exynos

switcheroo audio support: so GPUs with HDMI can turn off the sound driver
without crashing stuff.

There are some patches drifting outside drivers/gpu into x86 and EFI for 
better handling of multiple video adapters in Apple Macs, they've got 
correct acks except one trivial fixup.

Core:
edid parser has better DMT and reduced blanking support,
crtc properties,
plane properties,

Drivers:
exynos: add 2D core accel support, prime support, hdmi features
intel: more Haswell support, initial Valleyview support, more hdmi 
infoframe fixes, update MAINTAINERS for Daniel, lots of cleanups and fixes
radeon: more HDMI audio support, improved GPU lockup recovery support, 
remove nested mutexes, less memory copying on PCIE, fix bus master enable 
race (kexec), improved fence handling
gma500: cleanups, 1080p support, acpi fixes
nouveau: better nva3 memory reclocking, kepler accel (needs external 
firmware rip), async buffer moves on nv84+ hw.

I've some more dma-buf patches that rely on the dma-buf merge for vmap 
stuff, and I've a few fixes building up, but I'd decided I'd better get 
rid of the main pull sooner rather than later, so the audio guys are also 
unblocked.

Dave.

The following changes since commit d48b97b403d23f6df0b990cee652bdf9a52337a3:

  Linux 3.4-rc6 (2012-05-06 15:07:32 -0700)

are available in the git repository at:
  git://people.freedesktop.org/~airlied/linux drm-core-next

Adam Jackson (20):
  drm/i915: Pull MTRR setup to its own function
  drm/i915: Don't do MTRR setup if PAT is enabled
  drm/edid: Document drm_mode_find_dmt
  drm/edid: Rewrite drm_mode_find_dmt search loop
  drm/edid: Allow drm_mode_find_dmt to hunt for reduced-blanking modes
  drm/edid: Remove a misleading comment
  drm/edid: s/drm_gtf_modes_for_range/drm_dmt_modes_for_range/
  drm/edid: Add the reduced blanking DMT modes to the DMT list
  drm/edid: Fix some comment typos in the DMT mode list
  drm/edid: Do drm_dmt_modes_for_range() for all range descriptor types
  drm/edid: Update range descriptor struct for EDID 1.4
  drm/edid: Give the est3 mode struct a real name
  drm/edid: Add extra_modes
  drm/edid: Generate modes from extra_modes for range descriptors
  drm/edid: Try harder to fix up base EDID blocks
  drm/dp: Add DPCD OUI register defines
  drm/dp: Add DPCD defines for register 0x007
  drm/i915/dp: Probe branch/sink OUIs
  drm/radeon/dp: Probe branch/sink OUIs
  drm/nouveau/dp: Probe branch/sink OUIs (v2)

Alan Cox (31):
  gma500: Fix leak of uncached page
  gma500: read the PLL bits
  gma500: Update the Cedarview clock handling
  gma500: mark framebuffer pages write combining
  gma500: intel_bios updates
  gma500: panel presence check
  gma500: support 1080p
  gma500: Clean up weirdness in the cdv mode test code
  cdv: continue synching up with updated reference code
  gma500: Add ops for hotplug support.
  gma500: Add the base elements of CDV hotplug support
  gma500: Set the mapping mask
  gma500: don't register the ACPI video bus
  gma500: Sync up Oaktrail HDMI
  gma500: wide framebuffer memory
  gma500: implement backlight functionality for Cedartrail devices
  gma500: opregion and ACPI
  gma500: address the lid code
  gma500: Fix build without ACPI
  gma500: introduce a structure describing each pipe
  gma500: Clean up from the psb_pipe structure
  gma500: introduce some register maps
  gma500: use the register map to clean up
  gma500: Clean up some of the noise
  cdv: Add all cedarview pci ids
  gma500: clean up some more checks
  gma500: Turn on the IRQ for everything
  gma500: Fix crash on D2700MUD and various other boards
  gma500: unload fixes
  gma500: Prevent endless loop in panel power up sequence
  gma500: Fix Poulsbo suspend/resume crash on devices with SDVO ports

Alex Deucher (7):
  drm/radeon/kms: improve bpc handling (v2)
  drm/radeon/kms: add register definitions for audio
  drm/radeon/kms: fix up audio interrupt handling
  drm/radeon: add connector table for SAM440ep embedded board
  drm/radeon: make use of radeon_gem_init() consistent
  drm/radeon/hdmi: store info about all AFMT blocks
  drm/radeon: add PRIME support (v2)

Andreas Heider (2):
  drm/nouveau: Check dsm on switcheroo unregister
  drm/nouveau: Unregister switcheroo client on exit

Armin Reese (1):
  drm/i915: Mask reserved bits in display/sprite address registers

Ben Skeggs (53):
  drm/nva3/pm: introduce 

drm/i915 3.5 merge window: gen6_sanitize_pm errors

2012-05-24 Thread Linus Torvalds
These guys seem to be recently introduced:

  [drm:gen6_sanitize_pm] *ERROR* Power management discrepancy:
GEN6_RP_INTERRUPT_LIMITS expected 1700, was 1206
  [drm:gen6_sanitize_pm] *ERROR* Power management discrepancy:
GEN6_RP_INTERRUPT_LIMITS expected 1707, was 1700

This is on my SNB Macbook Air.

Everything seems to *work*, which makes me think:

 - that error isn't really so big a deal that you have to *SHOUT* about it.

 - I wonder how valid the discrepancy checking code is to begin with.

Hmm?

  Linus


[Bug 43207] radeon driver on HD6570 shows pixel noise

2012-05-24 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=43207





--- Comment #8 from J?r?me Glisse   2012-05-24 
19:13:23 ---
Created an attachment (id=73382)
 --> (https://bugzilla.kernel.org/attachment.cgi?id=73382)
Fix backend map

This patch should fix your issue

-- 
Configure bugmail: https://bugzilla.kernel.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are watching the assignee of the bug.


[PATCH] omap2+: add drm device

2012-05-24 Thread Tomi Valkeinen
On Thu, 2012-05-24 at 10:09 -0500, Gross, Andy wrote:
> On Thu, May 24, 2012 at 7:13 AM, Tomi Valkeinen  
> wrote:
> > On Thu, 2012-05-24 at 02:44 -0600, Rob Clark wrote:
> >
> >> but other drivers *can* use tiler, thanks to dmabuf.. I have omap4iss
> >> v4l2 camera working w/ tiler buffers on my pandaboard, for example.
> >>
> >> Maybe fbdev is an exception to the rule because it has no way for
> >> userspace to pass it a buffer to use.  But on the other hand it is a
> >> legacy API so I'm not sure if it is worth loosing too much sleep over
> >> that.
> >
> > I'm not that familiar with dmabuf, but are you saying it's not possible
> > for a kernel driver to request the buffers? They _must_ come from the
> > userspace?
> >
> > Anyway, even if it would be possible, if the tiler is a part of omapdrm
> > we need omapdrm to get and use the tiler buffers. And we can't have
> > omapdrm running when using omapfb, because they both use omapdss.
> 
> And that is a good point.  The DSS is kind of a sticking point to anyone
> having to enable DRM to get Tiler.  However, omapfb doesn't currently utilize
> DMM/Tiler features.  Can't we defer generalizing until there is a
> requirement for it?

Sure. I just brought it up because it'd be nice and it'd be better
architecturally. However, as I said, I'm not familiar with the related
problems, so I take your word that it's not simple =).

 Tomi

-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20120524/e3c5d6b2/attachment.pgp>


[pull] drm-intel-fixes for 3.5

2012-05-24 Thread Daniel Vetter
Hi Dave,

A set of fixes for 3.5:
- Fixes for regressions in 3.5: fix spurious gmbus NAK, fix module unload,
  fix pch pll asserts.
- Fix up eDP panel power sequencing - turns out we need to keep vdd on
  while switching everything off.
- Reject doubleclocked modes on dp.
- Fixup sdvo interlaced handling. It never worked, but the missing bits
  are just a tiny patch.
- Re-add some accidentally killed tv modes, also re-add
  a vblank wait in the tv detect code that we've lost somewhere around
  2.6.36.
- Preliminary ducttape for gpu turbo on snb+ - we're working the hw guys
  to figure out what's missing, because this code /should/ be the same the
  windows driver does. But that usually takes a while ...
- Fixup turbo for media workloads on snb+.
- And a no-lvds quirk.

Most of the patches are cc: stable.

Yours, Daniel


The following changes since commit f15b4ca2ccbc0a4661c35a744d254e1e32dd1e15:

  Merge tag 'drm-intel-next-2012-05-20' of 
git://people.freedesktop.org/~danvet/drm-intel into drm-core-next (2012-05-21 
08:17:42 +0100)

are available in the git repository at:


  git://people.freedesktop.org/~danvet/drm-intel drm-intel-fixes

for you to fetch changes up to 89ba829e38bd500f438bc08af4229204c8ed7f35:

  drm/i915: always use RPNSWREQ for turbo change requests (2012-05-24 17:54:15 
+0200)


Chris Wilson (2):
  drm/i915: Always update RPS interrupts thresholds along with frequency
  drm/i915: Fix PCH PLL assertions to not assume CRTC:PLL relationship

Daniel Vetter (6):
  drm/i915: be more careful when returning -ENXIO in gmbus transfer
  drm/i915: fix module unload since error_state rework
  drm/i915: properly handle interlaced bit for sdvo dtd conversion
  drm/i915: enable vdd when switching off the eDP panel
  drm/i915: wait for a vblank to pass after tv detect
  drm/i915: reject doubleclocked cea modes on dp

Jan-Benedict Glaw (1):
  drm/i915: no lvds quirk for HP t5740e Thin Client

Jesse Barnes (1):
  drm/i915: always use RPNSWREQ for turbo change requests

Rodrigo Vivi (1):
  drm/i915: Adding TV Out Missing modes.

 drivers/gpu/drm/i915/i915_debugfs.c|2 ++
 drivers/gpu/drm/i915/i915_irq.c|   37 
 drivers/gpu/drm/i915/intel_display.c   |   56 +-
 drivers/gpu/drm/i915/intel_dp.c|   24 +++--
 drivers/gpu/drm/i915/intel_i2c.c   |   21 +++-
 drivers/gpu/drm/i915/intel_lvds.c  |8 +
 drivers/gpu/drm/i915/intel_pm.c|   59 ++--
 drivers/gpu/drm/i915/intel_sdvo.c  |   12 ---
 drivers/gpu/drm/i915/intel_sdvo_regs.h |5 +++
 drivers/gpu/drm/i915/intel_tv.c|   53 
 10 files changed, 183 insertions(+), 94 deletions(-)
-- 
Daniel Vetter
Mail: daniel at ffwll.ch
Mobile: +41 (0)79 365 57 48


[Linaro-mm-sig] New "xf86-video-armsoc" DDX driver

2012-05-24 Thread Tom Cooksey


> -Original Message-
> From: Daniel Vetter [mailto:daniel.vetter at ffwll.ch] On Behalf Of Daniel
> Vetter
> Sent: 21 May 2012 10:04
> To: Dave Airlie
> Cc: Tom Cooksey; linaro-mm-sig at lists.linaro.org; xorg-
> devel at lists.x.org; dri-devel at lists.freedesktop.org
> Subject: Re: [Linaro-mm-sig] New "xf86-video-armsoc" DDX driver
> 
> On Mon, May 21, 2012 at 09:55:06AM +0100, Dave Airlie wrote:
> > > * Define a new x-server sub-module interface to allow a seperate
> > > > .so 2D driver to be loaded (this is the approach the current
> > > > OMAP DDX uses).
> >
> > This seems the sanest.
> 
> Or go the intel glamour route and stitch together a somewhat generic 2d
> accel code on top of GL. That should give you reasonable (albeit likely
> not stellar) X render performance.
> -Daniel

I'm not sure that would perform well on a tile-based deferred renderer
like Mali. To perform well, we need to gather an entire frame's worth
of rendering/draw-calls before passing them to the GPU to render. I
believe this is not the typical use-case of EXA? How much of the
framebuffer is re-drawn between flushes?


Cheers,

Tom







[Bug 43207] radeon driver on HD6570 shows pixel noise

2012-05-24 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=43207





--- Comment #7 from Vladislav Tcendrovskii   2012-05-24 
16:30:46 ---
I have tested kernel 3.4.

Results look a bit strange:

When i use modprobe radeon, I have the same pixel noise, which I had before.

If I start X, I have screen with windows and noise.

When I return to console, noise disappers. 

If I return to X, it also works fine.

-- 
Configure bugmail: https://bugzilla.kernel.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are watching the assignee of the bug.


[PATCH 08/10] drm/radeon: replace pflip and sw_int counters with atomics

2012-05-24 Thread Sylvain BERTRAND
> Does the linux API mandates atomic_t to be a 32bits word?

 AFAIK it is, at least for the platforms we care about.
 ...
>>>
>>> Then, the proper course of action would be to add to the linux API, sized
>>> atomic operation first, wouldn't it?
>>
>> No, atomic is fine for this, I think only sparc32 had 24-bit atomics,
>> and if you can get sparc32 + a radeon,
>> then you can keep both halves.
> 
> And even that is a lie now :-)
> 
> http://lwn.net/Articles/71732/

Ok then: atomic_t means exactly 32 bits!

-- 
Sylvain


[Bug 50232] screen redraw is wrong in sauerbraten with the llvm compiler

2012-05-24 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=50232

--- Comment #1 from Vadim Girlin  2012-05-24 08:50:00 PDT 
---
Please test with the first patch from bug 50230.

-- 
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are the assignee for the bug.


[PATCH] omap2+: add drm device

2012-05-24 Thread Tomi Valkeinen
On Thu, 2012-05-24 at 02:44 -0600, Rob Clark wrote:

> but other drivers *can* use tiler, thanks to dmabuf.. I have omap4iss
> v4l2 camera working w/ tiler buffers on my pandaboard, for example.
> 
> Maybe fbdev is an exception to the rule because it has no way for
> userspace to pass it a buffer to use.  But on the other hand it is a
> legacy API so I'm not sure if it is worth loosing too much sleep over
> that.

I'm not that familiar with dmabuf, but are you saying it's not possible
for a kernel driver to request the buffers? They _must_ come from the
userspace?

Anyway, even if it would be possible, if the tiler is a part of omapdrm
we need omapdrm to get and use the tiler buffers. And we can't have
omapdrm running when using omapfb, because they both use omapdss.

 Tomi

-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20120524/2af85523/attachment.pgp>


[PATCH] omap2+: add drm device

2012-05-24 Thread Tomi Valkeinen
Can omapdrm be used from inside the
> > kernel by another driver?
> 
> Hmm, I'm not quite sure what you have in mind, but it sounds a bit
> hacky..  I'd guess if you need 100% backwards compatibility even down
> to kernel cmdline / module params, then you probably want to use
> omapfb.  But there isn't really need to add new features to omapfb in
> that case.

I was thinking of making omapfb use omapdrm, instead of omapdss. I mean,
not planning to do that, just wondering if that would be possible.

> Off the top of my head, I guess that 80-90% compatibility would
> probably be reasonable to add to omapdrm's fbdev..  and that the last
> 10-20% would be too hacky/invasive to justify adding to omapdrm.

I think it should be 99.9% - 100% or nothing. If it's only 80-90%
compatible, then it's not compatible =).

 Tomi

-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20120524/c8ad9dc8/attachment-0001.pgp>


[PATCH 08/10] drm/radeon: replace pflip and sw_int counters with atomics

2012-05-24 Thread Sylvain BERTRAND
>> Does the linux API mandates atomic_t to be a 32bits word?
> 
> AFAIK it is, at least for the platforms we care about.
> ...

Then, the proper course of action would be to add to the linux API, sized
atomic operation first, wouldn't it?

-- 
Sylvain


[Bug 50230] offset mapping in nexuiz results in bad texturing with the llvm compiler

2012-05-24 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=50230

--- Comment #9 from Vadim Girlin  2012-05-24 07:38:10 PDT 
---
Created attachment 62057
  --> https://bugs.freedesktop.org/attachment.cgi?id=62057
[PATCH] radeon/llvm: fix sampler index in llvm_emit_tex

Does this patch help?

-- 
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are the assignee for the bug.


[PATCH 0/3] drm: A few misc patches

2012-05-24 Thread Alex Deucher
On Thu, May 24, 2012 at 1:53 PM,   wrote:
> Just a few small items caught in my net while trawling the code.

for the series:

Reviewed-by: Alex Deucher 

> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


[Bug 12434] Resume from suspend to RAM broken on ThinkPad R500

2012-05-24 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=12434


Alan  changed:

   What|Removed |Added

 Status|RESOLVED|CLOSED




-- 
Configure bugmail: https://bugzilla.kernel.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are watching the assignee of the bug.


[Bug 12434] Resume from suspend to RAM broken on ThinkPad R500

2012-05-24 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=12434


Alan  changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 CC||alan at lxorguk.ukuu.org.uk
 Resolution||OBSOLETE
 Regression|--- |No




--- Comment #18 from Alan   2012-05-24 14:15:32 ---
Closing as obsolete, if this is incorrect please update the bug having tested
versus a recent kernel

-- 
Configure bugmail: https://bugzilla.kernel.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are watching the assignee of the bug.


[Bug 12342] drm_pci_alloc needs to error when alignment constraints not met

2012-05-24 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=12342


Alan  changed:

   What|Removed |Added

 Status|RESOLVED|CLOSED




-- 
Configure bugmail: https://bugzilla.kernel.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are watching the assignee of the bug.


[Bug 12342] drm_pci_alloc needs to error when alignment constraints not met

2012-05-24 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=12342


Alan  changed:

   What|Removed |Added

 Status|NEEDINFO|RESOLVED
 CC||alan at lxorguk.ukuu.org.uk
 Resolution||OBSOLETE




-- 
Configure bugmail: https://bugzilla.kernel.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are watching the assignee of the bug.


[PATCH] drm: fix case where panic notifier isn't unregistered

2012-05-24 Thread Dave Airlie
On Thu, May 24, 2012 at 10:50 AM, Frank Binns  wrote:
> Hi,
> I don't know if this patch got missed in the list traffic or if I did 
> something wrong but it doesn't appear to have been picked up. This is my 
> first time contributing so if I did anything wrong some pointers would be 
> appreciated.
>

The patch is whitespace damaged, probably whatever you used to send mail.

Can you check it still applies to drm-next, and resend, with git
send-email if possible or as an attachment if nothing else works.

Dave.


[patch] drm/udl: unlock before returning in udl_gem_mmap()

2012-05-24 Thread Dan Carpenter
On Thu, Mar 22, 2012 at 09:30:56AM +0300, Dan Carpenter wrote:
> If we hit an error here, then we should unlock and unreference obj
> before returning.
> 

This is still present in linux-next.

regards,
dan carpenter

> Signed-off-by: Dan Carpenter 
> 
> diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c
> index 852642d..6de6130 100644
> --- a/drivers/gpu/drm/udl/udl_gem.c
> +++ b/drivers/gpu/drm/udl/udl_gem.c
> @@ -210,7 +210,7 @@ int udl_gem_mmap(struct drm_file *file, struct drm_device 
> *dev,
>  
>   ret = udl_gem_get_pages(gobj, GFP_KERNEL);
>   if (ret)
> - return ret;
> + goto out;
>   if (!gobj->base.map_list.map) {
>   ret = drm_gem_create_mmap_offset(obj);
>   if (ret)


[PATCH 08/10] drm/radeon: replace pflip and sw_int counters with atomics

2012-05-24 Thread Sylvain BERTRAND
> + atomic_tring_int[RADEON_NUM_RINGS];
>   boolcrtc_vblank_int[RADEON_MAX_CRTCS];
> - boolpflip[RADEON_MAX_CRTCS];
> - int pflip_refcount[RADEON_MAX_CRTCS];
> + atomic_tpflip[RADEON_MAX_CRTCS];

Hi,

Does the linux API mandates atomic_t to be a 32bits word?

Regards,

-- 
Sylvain


[PATCH 08/10] drm/radeon: replace pflip and sw_int counters with atomics

2012-05-24 Thread Dave Airlie
On Thu, May 24, 2012 at 1:53 PM, Dave Airlie  wrote:
> On Thu, May 24, 2012 at 1:46 PM, Sylvain BERTRAND  
> wrote:
 Does the linux API mandates atomic_t to be a 32bits word?
>>>
>>> AFAIK it is, at least for the platforms we care about.
>>> ...
>>
>> Then, the proper course of action would be to add to the linux API, sized
>> atomic operation first, wouldn't it?
>>
>
> No, atomic is fine for this, I think only sparc32 had 24-bit atomics,
> and if you can get sparc32 + a radeon,
> then you can keep both halves.

And even that is a lie now :-)

http://lwn.net/Articles/71732/

Dave.


[PATCH 08/10] drm/radeon: replace pflip and sw_int counters with atomics

2012-05-24 Thread Dave Airlie
On Thu, May 24, 2012 at 1:46 PM, Sylvain BERTRAND  wrote:
>>> Does the linux API mandates atomic_t to be a 32bits word?
>>
>> AFAIK it is, at least for the platforms we care about.
>> ...
>
> Then, the proper course of action would be to add to the linux API, sized
> atomic operation first, wouldn't it?
>

No, atomic is fine for this, I think only sparc32 had 24-bit atomics,
and if you can get sparc32 + a radeon,
then you can keep both halves.

Dave.


[Bug 12333] Radeon DRM produces kernel BUG at mm/vmalloc.c:292

2012-05-24 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=12333


Alan  changed:

   What|Removed |Added

 Status|RESOLVED|CLOSED




-- 
Configure bugmail: https://bugzilla.kernel.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are watching the assignee of the bug.


[Bug 12333] Radeon DRM produces kernel BUG at mm/vmalloc.c:292

2012-05-24 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=12333


Alan  changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 CC||alan at lxorguk.ukuu.org.uk
 Resolution||OBSOLETE




-- 
Configure bugmail: https://bugzilla.kernel.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are watching the assignee of the bug.


[PATCH RESEND] drm: fix case where panic notifier isn't unregistered

2012-05-24 Thread Frank Binns
The framebuffer helper panic notifier is unregistered, in drm_fb_helper_fini(), 
when kernel_fb_helper_list goes from being non-empty to empty. However, in 
drm_fb_helper_single_fb_probe(), it's possible for the panic notifier to be 
registered without an element being added to this list if a driver's probe 
function returns 0. Make sure that an attempt to add the panic notifier is made 
only when adding an element to kernel_fb_helper_list.

Signed-off-by: Frank Binns 
---
This should hopefully have none of the whitespace damage introduced by my email 
client last time.

 drivers/gpu/drm/drm_fb_helper.c |   21 ++---
 1 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index a0d6e89..d3764b3 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -807,21 +807,20 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper 
*fb_helper,
printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
   info->fix.id);

+   /* Switch back to kernel console on panic */
+   /* multi card linked list maybe */
+   if (list_empty(_fb_helper_list)) {
+   printk(KERN_INFO "drm: registered panic notifier\n");
+   atomic_notifier_chain_register(_notifier_list,
+  );
+   register_sysrq_key('v', 
_drm_fb_helper_restore_op);
+   }
+
+   list_add(_helper->kernel_fb_list, _fb_helper_list);
} else {
drm_fb_helper_set_par(info);
}

-   /* Switch back to kernel console on panic */
-   /* multi card linked list maybe */
-   if (list_empty(_fb_helper_list)) {
-   printk(KERN_INFO "drm: registered panic notifier\n");
-   atomic_notifier_chain_register(_notifier_list,
-  );
-   register_sysrq_key('v', _drm_fb_helper_restore_op);
-   }
-   if (new_fb)
-   list_add(_helper->kernel_fb_list, _fb_helper_list);
-
return 0;
 }
 EXPORT_SYMBOL(drm_fb_helper_single_fb_probe);
-- 
1.7.5.4




[PATCH] staging: omapdrm: fix crash when freeing bad fb

2012-05-24 Thread Rob Clark
On Thu, May 24, 2012 at 10:44 AM, Andy Gross  wrote:
> During unload, don't cleanup the framebuffer if it is not valid.
>
> Signed-off-by: Andy Gross 

Reviewed-by: Rob Clark 

> ---
> ?drivers/staging/omapdrm/omap_fbdev.c | ? 10 +++---
> ?1 files changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/staging/omapdrm/omap_fbdev.c 
> b/drivers/staging/omapdrm/omap_fbdev.c
> index 11acd4c..8c6ed3b 100644
> --- a/drivers/staging/omapdrm/omap_fbdev.c
> +++ b/drivers/staging/omapdrm/omap_fbdev.c
> @@ -208,7 +208,8 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
> ? ? ? ? */
> ? ? ? ?ret = omap_gem_get_paddr(fbdev->bo, , true);
> ? ? ? ?if (ret) {
> - ? ? ? ? ? ? ? dev_err(dev->dev, "could not map (paddr)!\n");
> + ? ? ? ? ? ? ? dev_err(dev->dev,
> + ? ? ? ? ? ? ? ? ? ? ? "could not map (paddr)! ?Skipping framebuffer 
> alloc\n");
> ? ? ? ? ? ? ? ?ret = -ENOMEM;
> ? ? ? ? ? ? ? ?goto fail;
> ? ? ? ?}
> @@ -388,8 +389,11 @@ void omap_fbdev_free(struct drm_device *dev)
>
> ? ? ? ?fbi = helper->fbdev;
>
> - ? ? ? unregister_framebuffer(fbi);
> - ? ? ? framebuffer_release(fbi);
> + ? ? ? /* only cleanup framebuffer if it is present */
> + ? ? ? if (fbi) {
> + ? ? ? ? ? ? ? unregister_framebuffer(fbi);
> + ? ? ? ? ? ? ? framebuffer_release(fbi);
> + ? ? ? }
>
> ? ? ? ?drm_fb_helper_fini(helper);
>
> --
> 1.7.5.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html


[PATCH] staging: omapdrm: fix crash when freeing bad fb

2012-05-24 Thread Rob Clark
On Thu, May 24, 2012 at 10:44 AM, Andy Gross  wrote:
> During unload, don't cleanup the framebuffer if it is not valid.
>
> Signed-off-by: Andy Gross 

Reviewed-by: Rob Clark 

> ---
> ?drivers/staging/omapdrm/omap_fbdev.c | ? 10 +++---
> ?1 files changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/staging/omapdrm/omap_fbdev.c 
> b/drivers/staging/omapdrm/omap_fbdev.c
> index 11acd4c..8c6ed3b 100644
> --- a/drivers/staging/omapdrm/omap_fbdev.c
> +++ b/drivers/staging/omapdrm/omap_fbdev.c
> @@ -208,7 +208,8 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
> ? ? ? ? */
> ? ? ? ?ret = omap_gem_get_paddr(fbdev->bo, , true);
> ? ? ? ?if (ret) {
> - ? ? ? ? ? ? ? dev_err(dev->dev, "could not map (paddr)!\n");
> + ? ? ? ? ? ? ? dev_err(dev->dev,
> + ? ? ? ? ? ? ? ? ? ? ? "could not map (paddr)! ?Skipping framebuffer 
> alloc\n");
> ? ? ? ? ? ? ? ?ret = -ENOMEM;
> ? ? ? ? ? ? ? ?goto fail;
> ? ? ? ?}
> @@ -388,8 +389,11 @@ void omap_fbdev_free(struct drm_device *dev)
>
> ? ? ? ?fbi = helper->fbdev;
>
> - ? ? ? unregister_framebuffer(fbi);
> - ? ? ? framebuffer_release(fbi);
> + ? ? ? /* only cleanup framebuffer if it is present */
> + ? ? ? if (fbi) {
> + ? ? ? ? ? ? ? unregister_framebuffer(fbi);
> + ? ? ? ? ? ? ? framebuffer_release(fbi);
> + ? ? ? }
>
> ? ? ? ?drm_fb_helper_fini(helper);
>
> --
> 1.7.5.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html


[PATCH] staging: omapdrm: Fix error paths during dmm init

2012-05-24 Thread Rob Clark
On Thu, May 24, 2012 at 10:43 AM, Andy Gross  wrote:
> Failures during the dmm probe can cause the kernel to crash. ?Moved
> the spinlock to a global and moved list initializations immediately
> after the allocation of the dmm private structure.
>
> Signed-off-by: Andy Gross 

Reviewed-by: Rob Clark 

> ---
> ?drivers/staging/omapdrm/omap_dmm_priv.h ?| ? ?1 -
> ?drivers/staging/omapdrm/omap_dmm_tiler.c | ? 44 -
> ?2 files changed, 24 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/staging/omapdrm/omap_dmm_priv.h 
> b/drivers/staging/omapdrm/omap_dmm_priv.h
> index 2f529ab..08b22e9 100644
> --- a/drivers/staging/omapdrm/omap_dmm_priv.h
> +++ b/drivers/staging/omapdrm/omap_dmm_priv.h
> @@ -181,7 +181,6 @@ struct dmm {
>
> ? ? ? ?/* allocation list and lock */
> ? ? ? ?struct list_head alloc_head;
> - ? ? ? spinlock_t list_lock;
> ?};
>
> ?#endif
> diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c 
> b/drivers/staging/omapdrm/omap_dmm_tiler.c
> index 1ecb6a7..3bc715d 100644
> --- a/drivers/staging/omapdrm/omap_dmm_tiler.c
> +++ b/drivers/staging/omapdrm/omap_dmm_tiler.c
> @@ -40,6 +40,9 @@
> ?static struct tcm *containers[TILFMT_NFORMATS];
> ?static struct dmm *omap_dmm;
>
> +/* global spinlock for protecting lists */
> +static DEFINE_SPINLOCK(list_lock);
> +
> ?/* Geometry table */
> ?#define GEOM(xshift, yshift, bytes_per_pixel) { \
> ? ? ? ? ? ? ? ?.x_shft = (xshift), \
> @@ -147,13 +150,13 @@ static struct dmm_txn *dmm_txn_init(struct dmm *dmm, 
> struct tcm *tcm)
> ? ? ? ?down(>engine_sem);
>
> ? ? ? ?/* grab an idle engine */
> - ? ? ? spin_lock(>list_lock);
> + ? ? ? spin_lock(_lock);
> ? ? ? ?if (!list_empty(>idle_head)) {
> ? ? ? ? ? ? ? ?engine = list_entry(dmm->idle_head.next, struct refill_engine,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?idle_node);
> ? ? ? ? ? ? ? ?list_del(>idle_node);
> ? ? ? ?}
> - ? ? ? spin_unlock(>list_lock);
> + ? ? ? spin_unlock(_lock);
>
> ? ? ? ?BUG_ON(!engine);
>
> @@ -256,9 +259,9 @@ static int dmm_txn_commit(struct dmm_txn *txn, bool wait)
> ? ? ? ?}
>
> ?cleanup:
> - ? ? ? spin_lock(>list_lock);
> + ? ? ? spin_lock(_lock);
> ? ? ? ?list_add(>idle_node, >idle_head);
> - ? ? ? spin_unlock(>list_lock);
> + ? ? ? spin_unlock(_lock);
>
> ? ? ? ?up(_dmm->engine_sem);
> ? ? ? ?return ret;
> @@ -351,9 +354,9 @@ struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, 
> uint16_t w,
> ? ? ? ?}
>
> ? ? ? ?/* add to allocation list */
> - ? ? ? spin_lock(_dmm->list_lock);
> + ? ? ? spin_lock(_lock);
> ? ? ? ?list_add(>alloc_node, _dmm->alloc_head);
> - ? ? ? spin_unlock(_dmm->list_lock);
> + ? ? ? spin_unlock(_lock);
>
> ? ? ? ?return block;
> ?}
> @@ -374,9 +377,9 @@ struct tiler_block *tiler_reserve_1d(size_t size)
> ? ? ? ? ? ? ? ?return 0;
> ? ? ? ?}
>
> - ? ? ? spin_lock(_dmm->list_lock);
> + ? ? ? spin_lock(_lock);
> ? ? ? ?list_add(>alloc_node, _dmm->alloc_head);
> - ? ? ? spin_unlock(_dmm->list_lock);
> + ? ? ? spin_unlock(_lock);
>
> ? ? ? ?return block;
> ?}
> @@ -389,9 +392,9 @@ int tiler_release(struct tiler_block *block)
> ? ? ? ?if (block->area.tcm)
> ? ? ? ? ? ? ? ?dev_err(omap_dmm->dev, "failed to release block\n");
>
> - ? ? ? spin_lock(_dmm->list_lock);
> + ? ? ? spin_lock(_lock);
> ? ? ? ?list_del(>alloc_node);
> - ? ? ? spin_unlock(_dmm->list_lock);
> + ? ? ? spin_unlock(_lock);
>
> ? ? ? ?kfree(block);
> ? ? ? ?return ret;
> @@ -479,13 +482,13 @@ static int omap_dmm_remove(struct platform_device *dev)
>
> ? ? ? ?if (omap_dmm) {
> ? ? ? ? ? ? ? ?/* free all area regions */
> - ? ? ? ? ? ? ? spin_lock(_dmm->list_lock);
> + ? ? ? ? ? ? ? spin_lock(_lock);
> ? ? ? ? ? ? ? ?list_for_each_entry_safe(block, _block, _dmm->alloc_head,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?alloc_node) {
> ? ? ? ? ? ? ? ? ? ? ? ?list_del(>alloc_node);
> ? ? ? ? ? ? ? ? ? ? ? ?kfree(block);
> ? ? ? ? ? ? ? ?}
> - ? ? ? ? ? ? ? spin_unlock(_dmm->list_lock);
> + ? ? ? ? ? ? ? spin_unlock(_lock);
>
> ? ? ? ? ? ? ? ?for (i = 0; i < omap_dmm->num_lut; i++)
> ? ? ? ? ? ? ? ? ? ? ? ?if (omap_dmm->tcm && omap_dmm->tcm[i])
> @@ -503,7 +506,7 @@ static int omap_dmm_remove(struct platform_device *dev)
>
> ? ? ? ? ? ? ? ?vfree(omap_dmm->lut);
>
> - ? ? ? ? ? ? ? if (omap_dmm->irq != -1)
> + ? ? ? ? ? ? ? if (omap_dmm->irq > 0)
> ? ? ? ? ? ? ? ? ? ? ? ?free_irq(omap_dmm->irq, omap_dmm);
>
> ? ? ? ? ? ? ? ?iounmap(omap_dmm->base);
> @@ -527,6 +530,10 @@ static int omap_dmm_probe(struct platform_device *dev)
> ? ? ? ? ? ? ? ?goto fail;
> ? ? ? ?}
>
> + ? ? ? /* initialize lists */
> + ? ? ? INIT_LIST_HEAD(_dmm->alloc_head);
> + ? ? ? INIT_LIST_HEAD(_dmm->idle_head);
> +
> ? ? ? ?/* lookup hwmod data - base address and irq */
> ? ? ? ?mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
> ? ? ? ?if (!mem) {
> @@ -629,7 +636,6 @@ static int omap_dmm_probe(struct platform_device *dev)
> ? ? ? ?}
>
> ? ? ? ?sema_init(_dmm->engine_sem, omap_dmm->num_engines);
> - ? ? ? INIT_LIST_HEAD(_dmm->idle_head);
> ? ? ? ?for (i = 0; i < omap_dmm->num_engines; i++) {
> ? ? 

[PATCH 08/10] drm/radeon: replace pflip and sw_int counters with atomics

2012-05-24 Thread Koenig, Christian
> -Original Message-
> From: Sylvain BERTRAND [mailto:sylware at legeek.net]
> Sent: Thursday, May 24, 2012 1:59 PM
> To: Christian K?nig
> Cc: j.glisse at gmail.com; Koenig, Christian; dri-devel at 
> lists.freedesktop.org
> Subject: Re: [PATCH 08/10] drm/radeon: replace pflip and sw_int counters
> with atomics
> 
> > +   atomic_tring_int[RADEON_NUM_RINGS];
> > bool
>   crtc_vblank_int[RADEON_MAX_CRTCS];
> > -   boolpflip[RADEON_MAX_CRTCS];
> > -   int
>   pflip_refcount[RADEON_MAX_CRTCS];
> > +   atomic_tpflip[RADEON_MAX_CRTCS];
> 
> Hi,
> 
> Does the linux API mandates atomic_t to be a 32bits word?

AFAIK it is, at least for the platforms we care about. But since this depends 
on the vertical refresh frequency even a 8bit counter should do fine.

On the other hand it was an accident that those patches hit the maillinglist in 
the first place, cause only the first four where supposed to be send out (my 
fault, sorry). This one isn't tested beside compiling, and I don't think it 
will work out of the box.

Cheers,
Christian.



[PATCH 06/10] drm/radeon: fix & improve ih ring handling

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:10AM +0200, Christian K?nig wrote:
> From: Christian Koenig 
> 
> The spinlock was actually there to protect the
> rptr, but rptr was read outside of the locked area.
> 
> Also we don't really need a spinlock here, an
> atomic should to quite fine since we only need to
> prevent it from being reentrant.
> 
> Signed-off-by: Christian Koenig 

Reviewed-by: Jerome Glisse 

> ---
>  drivers/gpu/drm/radeon/evergreen.c |   29 -
>  drivers/gpu/drm/radeon/r600.c  |   30 +++---
>  drivers/gpu/drm/radeon/radeon.h|3 +--
>  drivers/gpu/drm/radeon/radeon_device.c |3 +--
>  drivers/gpu/drm/radeon/si.c|   30 --
>  5 files changed, 49 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/gpu/drm/radeon/evergreen.c 
> b/drivers/gpu/drm/radeon/evergreen.c
> index dd3cea4..bfcb39e 100644
> --- a/drivers/gpu/drm/radeon/evergreen.c
> +++ b/drivers/gpu/drm/radeon/evergreen.c
> @@ -2943,7 +2943,6 @@ int evergreen_irq_process(struct radeon_device *rdev)
>   u32 rptr;
>   u32 src_id, src_data;
>   u32 ring_index;
> - unsigned long flags;
>   bool queue_hotplug = false;
>   bool queue_hdmi = false;
>  
> @@ -2951,22 +2950,24 @@ int evergreen_irq_process(struct radeon_device *rdev)
>   return IRQ_NONE;
>  
>   wptr = evergreen_get_ih_wptr(rdev);
> +
> +restart_ih:
> + /* is somebody else already processing irqs? */
> + if (atomic_xchg(>ih.lock, 1))
> + return IRQ_NONE;
> +
>   rptr = rdev->ih.rptr;
> + if (rptr == wptr)
> + return IRQ_NONE;
> +
>   DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
>  
> - spin_lock_irqsave(>ih.lock, flags);
> - if (rptr == wptr) {
> - spin_unlock_irqrestore(>ih.lock, flags);
> - return IRQ_NONE;
> - }
> -restart_ih:
>   /* Order reading of wptr vs. reading of IH ring data */
>   rmb();
>  
>   /* display interrupts */
>   evergreen_irq_ack(rdev);
>  
> - rdev->ih.wptr = wptr;
>   while (rptr != wptr) {
>   /* wptr/rptr are in bytes! */
>   ring_index = rptr / 4;
> @@ -3265,17 +3266,19 @@ restart_ih:
>   rptr += 16;
>   rptr &= rdev->ih.ptr_mask;
>   }
> - /* make sure wptr hasn't changed while processing */
> - wptr = evergreen_get_ih_wptr(rdev);
> - if (wptr != rdev->ih.wptr)
> - goto restart_ih;
>   if (queue_hotplug)
>   schedule_work(>hotplug_work);
>   if (queue_hdmi)
>   schedule_work(>audio_work);
>   rdev->ih.rptr = rptr;
>   WREG32(IH_RB_RPTR, rdev->ih.rptr);
> - spin_unlock_irqrestore(>ih.lock, flags);
> + atomic_set(>ih.lock, 0);
> +
> + /* make sure wptr hasn't changed while processing */
> + wptr = evergreen_get_ih_wptr(rdev);
> + if (wptr != rptr)
> + goto restart_ih;
> +
>   return IRQ_HANDLED;
>  }
>  
> diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
> index a8d8c44..eadbb06 100644
> --- a/drivers/gpu/drm/radeon/r600.c
> +++ b/drivers/gpu/drm/radeon/r600.c
> @@ -2921,7 +2921,6 @@ void r600_disable_interrupts(struct radeon_device *rdev)
>   WREG32(IH_RB_RPTR, 0);
>   WREG32(IH_RB_WPTR, 0);
>   rdev->ih.enabled = false;
> - rdev->ih.wptr = 0;
>   rdev->ih.rptr = 0;
>  }
>  
> @@ -3373,7 +3372,6 @@ int r600_irq_process(struct radeon_device *rdev)
>   u32 rptr;
>   u32 src_id, src_data;
>   u32 ring_index;
> - unsigned long flags;
>   bool queue_hotplug = false;
>   bool queue_hdmi = false;
>  
> @@ -3385,24 +3383,24 @@ int r600_irq_process(struct radeon_device *rdev)
>   RREG32(IH_RB_WPTR);
>  
>   wptr = r600_get_ih_wptr(rdev);
> - rptr = rdev->ih.rptr;
> - DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
>  
> - spin_lock_irqsave(>ih.lock, flags);
> +restart_ih:
> + /* is somebody else already processing irqs? */
> + if (atomic_xchg(>ih.lock, 1))
> + return IRQ_NONE;
>  
> - if (rptr == wptr) {
> - spin_unlock_irqrestore(>ih.lock, flags);
> + rptr = rdev->ih.rptr;
> + if (rptr == wptr)
>   return IRQ_NONE;
> - }
>  
> -restart_ih:
> + DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
> +
>   /* Order reading of wptr vs. reading of IH ring data */
>   rmb();
>  
>   /* display interrupts */
>   r600_irq_ack(rdev);
>  
> - rdev->ih.wptr = wptr;
>   while (rptr != wptr) {
>   /* wptr/rptr are in bytes! */
>   ring_index = rptr / 4;
> @@ -3556,17 +3554,19 @@ restart_ih:
>   rptr += 16;
>   rptr &= rdev->ih.ptr_mask;
>   }
> - /* make sure wptr hasn't changed while processing */
> - wptr = r600_get_ih_wptr(rdev);
> - if (wptr != rdev->ih.wptr)

[PATCH 05/10] drm/radeon: remove some unneeded structure members

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:09AM +0200, Christian K?nig wrote:
> From: Christian Koenig 
> 
> Signed-off-by: Christian Koenig 

Reviewed-by: Jerome Glisse 

> ---
>  drivers/gpu/drm/radeon/radeon.h |2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index 3e83480..618df9a 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -733,9 +733,7 @@ struct r600_ih {
>   struct radeon_bo*ring_obj;
>   volatile uint32_t   *ring;
>   unsignedrptr;
> - unsignedrptr_offs;
>   unsignedwptr;
> - unsignedwptr_old;
>   unsignedring_size;
>   uint64_tgpu_addr;
>   uint32_tptr_mask;
> -- 
> 1.7.9.5
> 


[PATCH 04/10] drm/radeon: replace vmram_mutex with mclk_lock v2

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:08AM +0200, Christian K?nig wrote:
> It is a rw_semaphore now and only write locked
> while changing the clock. Also the lock is renamed
> to better reflect what it is protecting.
> 
> v2: Keep the ttm_vm_ops on IGPs
> 
> Signed-off-by: Christian K?nig 

Reviewed-by: Jerome Glisse 

> ---
>  drivers/gpu/drm/radeon/radeon.h|3 ++-
>  drivers/gpu/drm/radeon/radeon_device.c |2 +-
>  drivers/gpu/drm/radeon/radeon_object.c |8 
>  drivers/gpu/drm/radeon/radeon_pm.c |4 ++--
>  drivers/gpu/drm/radeon/radeon_ttm.c|4 ++--
>  5 files changed, 11 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index aebaf28..3e83480 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -1055,6 +1055,8 @@ struct radeon_power_state {
>  
>  struct radeon_pm {
>   struct mutexmutex;
> + /* write locked while reprogramming mclk */
> + struct rw_semaphore mclk_lock;
>   u32 active_crtcs;
>   int active_crtc_count;
>   int req_vblank;
> @@ -1551,7 +1553,6 @@ struct radeon_device {
>   struct work_struct audio_work;
>   int num_crtc; /* number of crtcs */
>   struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */
> - struct mutex vram_mutex;
>   bool audio_enabled;
>   struct r600_audio audio_status; /* audio stuff */
>   struct notifier_block acpi_nb;
> diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
> b/drivers/gpu/drm/radeon/radeon_device.c
> index 066c98b..7667184 100644
> --- a/drivers/gpu/drm/radeon/radeon_device.c
> +++ b/drivers/gpu/drm/radeon/radeon_device.c
> @@ -735,7 +735,7 @@ int radeon_device_init(struct radeon_device *rdev,
>   spin_lock_init(>ih.lock);
>   mutex_init(>gem.mutex);
>   mutex_init(>pm.mutex);
> - mutex_init(>vram_mutex);
> + init_rwsem(>pm.mclk_lock);
>   init_waitqueue_head(>irq.vblank_queue);
>   init_waitqueue_head(>irq.idle_queue);
>   r = radeon_gem_init(rdev);
> diff --git a/drivers/gpu/drm/radeon/radeon_object.c 
> b/drivers/gpu/drm/radeon/radeon_object.c
> index 830f1a7..6ecb200 100644
> --- a/drivers/gpu/drm/radeon/radeon_object.c
> +++ b/drivers/gpu/drm/radeon/radeon_object.c
> @@ -154,11 +154,11 @@ retry:
>   INIT_LIST_HEAD(>va);
>   radeon_ttm_placement_from_domain(bo, domain);
>   /* Kernel allocation are uninterruptible */
> - mutex_lock(>vram_mutex);
> + down_read(>pm.mclk_lock);
>   r = ttm_bo_init(>mman.bdev, >tbo, size, type,
>   >placement, page_align, 0, !kernel, NULL,
>   acc_size, sg, _ttm_bo_destroy);
> - mutex_unlock(>vram_mutex);
> + up_read(>pm.mclk_lock);
>   if (unlikely(r != 0)) {
>   if (r != -ERESTARTSYS) {
>   if (domain == RADEON_GEM_DOMAIN_VRAM) {
> @@ -219,9 +219,9 @@ void radeon_bo_unref(struct radeon_bo **bo)
>   return;
>   rdev = (*bo)->rdev;
>   tbo = &((*bo)->tbo);
> - mutex_lock(>vram_mutex);
> + down_read(>pm.mclk_lock);
>   ttm_bo_unref();
> - mutex_unlock(>vram_mutex);
> + up_read(>pm.mclk_lock);
>   if (tbo == NULL)
>   *bo = NULL;
>  }
> diff --git a/drivers/gpu/drm/radeon/radeon_pm.c 
> b/drivers/gpu/drm/radeon/radeon_pm.c
> index 0882554..d13b6ae 100644
> --- a/drivers/gpu/drm/radeon/radeon_pm.c
> +++ b/drivers/gpu/drm/radeon/radeon_pm.c
> @@ -251,7 +251,7 @@ static void radeon_pm_set_clocks(struct radeon_device 
> *rdev)
>   return;
>  
>   mutex_lock(>ddev->struct_mutex);
> - mutex_lock(>vram_mutex);
> + down_write(>pm.mclk_lock);
>   mutex_lock(>ring_lock);
>  
>   /* gui idle int has issues on older chips it seems */
> @@ -303,7 +303,7 @@ static void radeon_pm_set_clocks(struct radeon_device 
> *rdev)
>   rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
>  
>   mutex_unlock(>ring_lock);
> - mutex_unlock(>vram_mutex);
> + up_write(>pm.mclk_lock);
>   mutex_unlock(>ddev->struct_mutex);
>  }
>  
> diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c 
> b/drivers/gpu/drm/radeon/radeon_ttm.c
> index c43035c..0881131 100644
> --- a/drivers/gpu/drm/radeon/radeon_ttm.c
> +++ b/drivers/gpu/drm/radeon/radeon_ttm.c
> @@ -797,9 +797,9 @@ static int radeon_ttm_fault(struct vm_area_struct *vma, 
> struct vm_fault *vmf)
>   return VM_FAULT_NOPAGE;
>   }
>   rdev = radeon_get_rdev(bo->bdev);
> - mutex_lock(>vram_mutex);
> + down_read(>pm.mclk_lock);
>   r = ttm_vm_ops->fault(vma, vmf);
> - mutex_unlock(>vram_mutex);
> + up_read(>pm.mclk_lock);
>   return r;
>  }
>  
> -- 
> 1.7.9.5
> 
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 03/10] drm/radeon: rework ring syncing code

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:07AM +0200, Christian K?nig wrote:
> Move inter ring syncing with semaphores into the
> existing ring allocations, with that we need to
> lock the ring mutex only once.
> 
> Signed-off-by: Christian K?nig 

Reviewed-by: Jerome Glisse 

> ---
>  drivers/gpu/drm/radeon/evergreen_blit_kms.c |3 +-
>  drivers/gpu/drm/radeon/r600.c   |5 +-
>  drivers/gpu/drm/radeon/r600_blit_kms.c  |   24 +++--
>  drivers/gpu/drm/radeon/radeon.h |6 +--
>  drivers/gpu/drm/radeon/radeon_asic.h|5 +-
>  drivers/gpu/drm/radeon/radeon_cs.c  |   38 +++---
>  drivers/gpu/drm/radeon/radeon_ring.c|   30 +--
>  drivers/gpu/drm/radeon/radeon_semaphore.c   |   71 
> ++-
>  drivers/gpu/drm/radeon/radeon_test.c|6 +--
>  drivers/gpu/drm/radeon/radeon_ttm.c |   20 
>  10 files changed, 92 insertions(+), 116 deletions(-)
> 
> diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c 
> b/drivers/gpu/drm/radeon/evergreen_blit_kms.c
> index 1e96bd4..e512560 100644
> --- a/drivers/gpu/drm/radeon/evergreen_blit_kms.c
> +++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c
> @@ -622,7 +622,8 @@ int evergreen_blit_init(struct radeon_device *rdev)
>   rdev->r600_blit.primitives.draw_auto = draw_auto;
>   rdev->r600_blit.primitives.set_default_state = set_default_state;
>  
> - rdev->r600_blit.ring_size_common = 55; /* shaders + def state */
> + rdev->r600_blit.ring_size_common = 8; /* sync semaphore */
> + rdev->r600_blit.ring_size_common += 55; /* shaders + def state */
>   rdev->r600_blit.ring_size_common += 16; /* fence emit for VB IB */
>   rdev->r600_blit.ring_size_common += 5; /* done copy */
>   rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */
> diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
> index e5279f9..a8d8c44 100644
> --- a/drivers/gpu/drm/radeon/r600.c
> +++ b/drivers/gpu/drm/radeon/r600.c
> @@ -2371,15 +2371,16 @@ int r600_copy_blit(struct radeon_device *rdev,
>  unsigned num_gpu_pages,
>  struct radeon_fence **fence)
>  {
> + struct radeon_semaphore *sem = NULL;
>   struct radeon_sa_bo *vb = NULL;
>   int r;
>  
> - r = r600_blit_prepare_copy(rdev, num_gpu_pages, );
> + r = r600_blit_prepare_copy(rdev, num_gpu_pages, fence, , );
>   if (r) {
>   return r;
>   }
>   r600_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages, vb);
> - r600_blit_done_copy(rdev, fence, vb);
> + r600_blit_done_copy(rdev, fence, vb, sem);
>   return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c 
> b/drivers/gpu/drm/radeon/r600_blit_kms.c
> index 02f4eeb..2b8d641 100644
> --- a/drivers/gpu/drm/radeon/r600_blit_kms.c
> +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c
> @@ -512,7 +512,8 @@ int r600_blit_init(struct radeon_device *rdev)
>   rdev->r600_blit.primitives.draw_auto = draw_auto;
>   rdev->r600_blit.primitives.set_default_state = set_default_state;
>  
> - rdev->r600_blit.ring_size_common = 40; /* shaders + def state */
> + rdev->r600_blit.ring_size_common = 8; /* sync semaphore */
> + rdev->r600_blit.ring_size_common += 40; /* shaders + def state */
>   rdev->r600_blit.ring_size_common += 5; /* done copy */
>   rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */
>  
> @@ -666,7 +667,8 @@ static unsigned r600_blit_create_rect(unsigned 
> num_gpu_pages,
>  
>  
>  int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned 
> num_gpu_pages,
> -struct radeon_sa_bo **vb)
> +struct radeon_fence **fence, struct radeon_sa_bo 
> **vb,
> +struct radeon_semaphore **sem)
>  {
>   struct radeon_ring *ring = >ring[RADEON_RING_TYPE_GFX_INDEX];
>   int r;
> @@ -689,22 +691,37 @@ int r600_blit_prepare_copy(struct radeon_device *rdev, 
> unsigned num_gpu_pages,
>   return r;
>   }
>  
> + r = radeon_semaphore_create(rdev, sem);
> + if (r) {
> + radeon_sa_bo_free(rdev, vb, NULL);
> + return r;
> + }
> +
>   /* calculate number of loops correctly */
>   ring_size = num_loops * dwords_per_loop;
>   ring_size += rdev->r600_blit.ring_size_common;
>   r = radeon_ring_lock(rdev, ring, ring_size);
>   if (r) {
>   radeon_sa_bo_free(rdev, vb, NULL);
> + radeon_semaphore_free(rdev, sem, NULL);
>   return r;
>   }
>  
> + if (radeon_fence_need_sync(*fence, RADEON_RING_TYPE_GFX_INDEX)) {
> + radeon_semaphore_sync_rings(rdev, *sem, (*fence)->ring,
> + RADEON_RING_TYPE_GFX_INDEX);
> + radeon_fence_note_sync(*fence, RADEON_RING_TYPE_GFX_INDEX);
> + } else {
> + radeon_semaphore_free(rdev, sem, NULL);
> + }
> +

[PATCH 02/10] drm/radeon: add infrastructure for advanced ring synchronization

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:06AM +0200, Christian K?nig wrote:
> Signed-off-by: Christian K?nig 

Need a small improvement see below, otherwise

Reviewed-by: Jerome Glisse 

> ---
>  drivers/gpu/drm/radeon/radeon.h   |   23 ++-
>  drivers/gpu/drm/radeon/radeon_fence.c |   73 
> +
>  2 files changed, 85 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index 5e259b4..4e232c3 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -257,8 +257,8 @@ struct radeon_fence_driver {
>   uint32_tscratch_reg;
>   uint64_tgpu_addr;
>   volatile uint32_t   *cpu_addr;
> - /* seq is protected by ring emission lock */
> - uint64_tseq;
> + /* sync_seq is protected by ring emission lock */
> + uint64_tsync_seq[RADEON_NUM_RINGS];
>   atomic64_t  last_seq;
>   unsigned long   last_activity;
>   boolinitialized;
> @@ -288,6 +288,25 @@ int radeon_fence_wait_any(struct radeon_device *rdev,
>  struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
>  void radeon_fence_unref(struct radeon_fence **fence);
>  unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring);
> +bool radeon_fence_need_sync(struct radeon_fence *fence, int ring);
> +void radeon_fence_note_sync(struct radeon_fence *fence, int ring);
> +static inline struct radeon_fence *radeon_fence_later(struct radeon_fence *a,
> +   struct radeon_fence *b)
> +{
> + if (!a) {
> + return b;
> + }
> +
> + if (!b) {
> + return a;
> + }

Please add :
BUG_ON(a->ring != b->ring);

So we can catch if someone badly use this function.

> +
> + if (a->seq > b->seq) {
> + return a;
> + } else {
> + return b;
> + }
> +}
>  
>  /*
>   * Tiling registers
> diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
> b/drivers/gpu/drm/radeon/radeon_fence.c
> index 401d346..7b55625 100644
> --- a/drivers/gpu/drm/radeon/radeon_fence.c
> +++ b/drivers/gpu/drm/radeon/radeon_fence.c
> @@ -72,7 +72,7 @@ int radeon_fence_emit(struct radeon_device *rdev,
>   }
>   kref_init(&((*fence)->kref));
>   (*fence)->rdev = rdev;
> - (*fence)->seq = ++rdev->fence_drv[ring].seq;
> + (*fence)->seq = ++rdev->fence_drv[ring].sync_seq[ring];
>   (*fence)->ring = ring;
>   radeon_fence_ring_emit(rdev, ring, *fence);
>   trace_radeon_fence_emit(rdev->ddev, (*fence)->seq);
> @@ -449,7 +449,7 @@ int radeon_fence_wait_next_locked(struct radeon_device 
> *rdev, int ring)
>* wait.
>*/
>   seq = atomic64_read(>fence_drv[ring].last_seq) + 1ULL;
> - if (seq >= rdev->fence_drv[ring].seq) {
> + if (seq >= rdev->fence_drv[ring].sync_seq[ring]) {
>   /* nothing to wait for, last_seq is
>  already the last emited fence */
>   return -ENOENT;
> @@ -464,7 +464,7 @@ int radeon_fence_wait_empty_locked(struct radeon_device 
> *rdev, int ring)
>* activity can be scheduled so there won't be concurrent access
>* to seq value.
>*/
> - return radeon_fence_wait_seq(rdev, rdev->fence_drv[ring].seq,
> + return radeon_fence_wait_seq(rdev, rdev->fence_drv[ring].sync_seq[ring],
>ring, false, false);
>  }
>  
> @@ -492,7 +492,8 @@ unsigned radeon_fence_count_emitted(struct radeon_device 
> *rdev, int ring)
>* but it's ok to report slightly wrong fence count here.
>*/
>   radeon_fence_process(rdev, ring);
> - emitted = rdev->fence_drv[ring].seq - 
> atomic64_read(>fence_drv[ring].last_seq);
> + emitted = rdev->fence_drv[ring].sync_seq[ring]
> + - atomic64_read(>fence_drv[ring].last_seq);
>   /* to avoid 32bits warp around */
>   if (emitted > 0x1000) {
>   emitted = 0x1000;
> @@ -500,6 +501,51 @@ unsigned radeon_fence_count_emitted(struct radeon_device 
> *rdev, int ring)
>   return (unsigned)emitted;
>  }
>  
> +bool radeon_fence_need_sync(struct radeon_fence *fence, int dst_ring)
> +{
> + struct radeon_fence_driver *fdrv;
> +
> + if (!fence) {
> + return false;
> + }
> +
> + if (fence->ring == dst_ring) {
> + return false;
> + }
> +
> + /* we are protected by the ring mutex */
> + fdrv = >rdev->fence_drv[dst_ring];
> + if (fence->seq <= fdrv->sync_seq[fence->ring]) {
> + return false;
> + }
> +
> + return true;
> +}
> +
> +void radeon_fence_note_sync(struct radeon_fence *fence, int dst_ring)
> +{
> + struct radeon_fence_driver *dst, *src;
> + unsigned i;
> +
> + if (!fence) {
> + return;
> + }
> +
> + if 

[PATCH 01/10] drm/radeon: remove radeon_fence_create

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:05AM +0200, Christian K?nig wrote:
> It is completely unnecessary to create fences
> before they are emitted, so remove it and a bunch
> of checks if fences are emitted or not.
> 
> Signed-off-by: Christian K?nig 

Reviewed-by: Jerome Glisse 

> ---
>  drivers/gpu/drm/radeon/evergreen.c|2 +-
>  drivers/gpu/drm/radeon/ni.c   |2 +-
>  drivers/gpu/drm/radeon/r100.c |4 +-
>  drivers/gpu/drm/radeon/r200.c |4 +-
>  drivers/gpu/drm/radeon/r600.c |4 +-
>  drivers/gpu/drm/radeon/r600_blit_kms.c|6 +--
>  drivers/gpu/drm/radeon/radeon.h   |   11 +++--
>  drivers/gpu/drm/radeon/radeon_asic.h  |8 ++--
>  drivers/gpu/drm/radeon/radeon_benchmark.c |   10 +
>  drivers/gpu/drm/radeon/radeon_fence.c |   42 ++
>  drivers/gpu/drm/radeon/radeon_ring.c  |   19 +
>  drivers/gpu/drm/radeon/radeon_sa.c|2 +-
>  drivers/gpu/drm/radeon/radeon_test.c  |   66 
> -
>  drivers/gpu/drm/radeon/radeon_ttm.c   |   30 +
>  drivers/gpu/drm/radeon/si.c   |6 +--
>  15 files changed, 86 insertions(+), 130 deletions(-)
> 
> diff --git a/drivers/gpu/drm/radeon/evergreen.c 
> b/drivers/gpu/drm/radeon/evergreen.c
> index 58991af..dd3cea4 100644
> --- a/drivers/gpu/drm/radeon/evergreen.c
> +++ b/drivers/gpu/drm/radeon/evergreen.c
> @@ -1366,7 +1366,7 @@ void evergreen_mc_program(struct radeon_device *rdev)
>   */
>  void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib 
> *ib)
>  {
> - struct radeon_ring *ring = >ring[ib->fence->ring];
> + struct radeon_ring *ring = >ring[ib->ring];
>  
>   /* set to DX10/11 mode */
>   radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0));
> diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
> index b01c2dd..9d9f5ac 100644
> --- a/drivers/gpu/drm/radeon/ni.c
> +++ b/drivers/gpu/drm/radeon/ni.c
> @@ -1127,7 +1127,7 @@ void cayman_fence_ring_emit(struct radeon_device *rdev,
>  
>  void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
>  {
> - struct radeon_ring *ring = >ring[ib->fence->ring];
> + struct radeon_ring *ring = >ring[ib->ring];
>  
>   /* set to DX10/11 mode */
>   radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0));
> diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
> index fb44e7e..415b7d8 100644
> --- a/drivers/gpu/drm/radeon/r100.c
> +++ b/drivers/gpu/drm/radeon/r100.c
> @@ -883,7 +883,7 @@ int r100_copy_blit(struct radeon_device *rdev,
>  uint64_t src_offset,
>  uint64_t dst_offset,
>  unsigned num_gpu_pages,
> -struct radeon_fence *fence)
> +struct radeon_fence **fence)
>  {
>   struct radeon_ring *ring = >ring[RADEON_RING_TYPE_GFX_INDEX];
>   uint32_t cur_pages;
> @@ -947,7 +947,7 @@ int r100_copy_blit(struct radeon_device *rdev,
> RADEON_WAIT_HOST_IDLECLEAN |
> RADEON_WAIT_DMA_GUI_IDLE);
>   if (fence) {
> - r = radeon_fence_emit(rdev, fence);
> + r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX);
>   }
>   radeon_ring_unlock_commit(rdev, ring);
>   return r;
> diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c
> index a26144d..f088925 100644
> --- a/drivers/gpu/drm/radeon/r200.c
> +++ b/drivers/gpu/drm/radeon/r200.c
> @@ -85,7 +85,7 @@ int r200_copy_dma(struct radeon_device *rdev,
> uint64_t src_offset,
> uint64_t dst_offset,
> unsigned num_gpu_pages,
> -   struct radeon_fence *fence)
> +   struct radeon_fence **fence)
>  {
>   struct radeon_ring *ring = >ring[RADEON_RING_TYPE_GFX_INDEX];
>   uint32_t size;
> @@ -120,7 +120,7 @@ int r200_copy_dma(struct radeon_device *rdev,
>   radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
>   radeon_ring_write(ring, RADEON_WAIT_DMA_GUI_IDLE);
>   if (fence) {
> - r = radeon_fence_emit(rdev, fence);
> + r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX);
>   }
>   radeon_ring_unlock_commit(rdev, ring);
>   return r;
> diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
> index f388a1d..e5279f9 100644
> --- a/drivers/gpu/drm/radeon/r600.c
> +++ b/drivers/gpu/drm/radeon/r600.c
> @@ -2369,7 +2369,7 @@ int r600_copy_blit(struct radeon_device *rdev,
>  uint64_t src_offset,
>  uint64_t dst_offset,
>  unsigned num_gpu_pages,
> -struct radeon_fence *fence)
> +struct radeon_fence **fence)
>  {
>   struct radeon_sa_bo *vb = NULL;
>   int r;
> @@ -2670,7 +2670,7 @@ void r600_fini(struct radeon_device *rdev)
>   */
>  void 

[PATCH 07/10] drm/radeon: apply Murphy's law to the kms irq code

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 11:35:15AM -0400, Alex Deucher wrote:
> On Thu, May 24, 2012 at 3:49 AM, Christian K?nig
>  wrote:
> > From: Christian Koenig 
> >
> > 1. It is really dangerous to have more than one
> > ? spinlock protecting the same information.
> >
> > 2. radeon_irq_set sometimes wasn't called with lock
> > ? protection, so it can happen that more than one
> > ? CPU would tamper with the irq regs at the same
> > ? time.
> >
> > 3. The pm.gui_idle variable was assuming that the 3D
> > ? engine wasn't becoming idle between testing the
> > ? register and setting the variable. So just remove
> > ? it and test the register directly.
> >
> > Signed-off-by: Christian Koenig 
> > ---
> > ?drivers/gpu/drm/radeon/evergreen.c ? ? ?| ? ?1 -
> > ?drivers/gpu/drm/radeon/r100.c ? ? ? ? ? | ? ?1 -
> > ?drivers/gpu/drm/radeon/r600.c ? ? ? ? ? | ? ?1 -
> > ?drivers/gpu/drm/radeon/r600_hdmi.c ? ? ?| ? ?6 +--
> > ?drivers/gpu/drm/radeon/radeon.h ? ? ? ? | ? 33 +++---
> > ?drivers/gpu/drm/radeon/radeon_irq_kms.c | ? 72 
> > +--
> > ?drivers/gpu/drm/radeon/radeon_kms.c ? ? | ? 12 --
> > ?drivers/gpu/drm/radeon/radeon_pm.c ? ? ?| ? 12 +-
> > ?drivers/gpu/drm/radeon/rs600.c ? ? ? ? ?| ? ?1 -
> > ?drivers/gpu/drm/radeon/si.c ? ? ? ? ? ? | ? ?1 -
> > ?10 files changed, 90 insertions(+), 50 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/radeon/evergreen.c 
> > b/drivers/gpu/drm/radeon/evergreen.c
> > index bfcb39e..9e9b3bb 100644
> > --- a/drivers/gpu/drm/radeon/evergreen.c
> > +++ b/drivers/gpu/drm/radeon/evergreen.c
> > @@ -3254,7 +3254,6 @@ restart_ih:
> > ? ? ? ? ? ? ? ? ? ? ? ?break;
> > ? ? ? ? ? ? ? ?case 233: /* GUI IDLE */
> > ? ? ? ? ? ? ? ? ? ? ? ?DRM_DEBUG("IH: GUI idle\n");
> > - ? ? ? ? ? ? ? ? ? ? ? rdev->pm.gui_idle = true;
> > ? ? ? ? ? ? ? ? ? ? ? ?wake_up(>irq.idle_queue);
> > ? ? ? ? ? ? ? ? ? ? ? ?break;
> > ? ? ? ? ? ? ? ?default:
> > diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
> > index 415b7d8..2587426 100644
> > --- a/drivers/gpu/drm/radeon/r100.c
> > +++ b/drivers/gpu/drm/radeon/r100.c
> > @@ -782,7 +782,6 @@ int r100_irq_process(struct radeon_device *rdev)
> > ? ? ? ? ? ? ? ?/* gui idle interrupt */
> > ? ? ? ? ? ? ? ?if (status & RADEON_GUI_IDLE_STAT) {
> > ? ? ? ? ? ? ? ? ? ? ? ?rdev->irq.gui_idle_acked = true;
> > - ? ? ? ? ? ? ? ? ? ? ? rdev->pm.gui_idle = true;
> > ? ? ? ? ? ? ? ? ? ? ? ?wake_up(>irq.idle_queue);
> > ? ? ? ? ? ? ? ?}
> > ? ? ? ? ? ? ? ?/* Vertical blank interrupts */
> > diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
> > index eadbb06..90c6639 100644
> > --- a/drivers/gpu/drm/radeon/r600.c
> > +++ b/drivers/gpu/drm/radeon/r600.c
> > @@ -3542,7 +3542,6 @@ restart_ih:
> > ? ? ? ? ? ? ? ? ? ? ? ?break;
> > ? ? ? ? ? ? ? ?case 233: /* GUI IDLE */
> > ? ? ? ? ? ? ? ? ? ? ? ?DRM_DEBUG("IH: GUI idle\n");
> > - ? ? ? ? ? ? ? ? ? ? ? rdev->pm.gui_idle = true;
> > ? ? ? ? ? ? ? ? ? ? ? ?wake_up(>irq.idle_queue);
> > ? ? ? ? ? ? ? ? ? ? ? ?break;
> > ? ? ? ? ? ? ? ?default:
> > diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c 
> > b/drivers/gpu/drm/radeon/r600_hdmi.c
> > index 226379e..b76c0f2 100644
> > --- a/drivers/gpu/drm/radeon/r600_hdmi.c
> > +++ b/drivers/gpu/drm/radeon/r600_hdmi.c
> > @@ -523,8 +523,7 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
> >
> > ? ? ? ?if (rdev->irq.installed) {
> > ? ? ? ? ? ? ? ?/* if irq is available use it */
> > - ? ? ? ? ? ? ? rdev->irq.afmt[dig->afmt->id] = true;
> > - ? ? ? ? ? ? ? radeon_irq_set(rdev);
> > + ? ? ? ? ? ? ? radeon_irq_kms_enable_afmt(rdev, dig->afmt->id);
> > ? ? ? ?}
> >
> > ? ? ? ?dig->afmt->enabled = true;
> > @@ -560,8 +559,7 @@ void r600_hdmi_disable(struct drm_encoder *encoder)
> > ? ? ? ? ? ? ? ? ?offset, radeon_encoder->encoder_id);
> >
> > ? ? ? ?/* disable irq */
> > - ? ? ? rdev->irq.afmt[dig->afmt->id] = false;
> > - ? ? ? radeon_irq_set(rdev);
> > + ? ? ? radeon_irq_kms_disable_afmt(rdev, dig->afmt->id);
> >
> > ? ? ? ?/* Older chipsets not handled by AtomBIOS */
> > ? ? ? ?if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
> > diff --git a/drivers/gpu/drm/radeon/radeon.h 
> > b/drivers/gpu/drm/radeon/radeon.h
> > index 8479096..23552b4 100644
> > --- a/drivers/gpu/drm/radeon/radeon.h
> > +++ b/drivers/gpu/drm/radeon/radeon.h
> > @@ -610,21 +610,20 @@ union radeon_irq_stat_regs {
> > ?#define RADEON_MAX_AFMT_BLOCKS 6
> >
> > ?struct radeon_irq {
> > - ? ? ? bool ? ? ? ? ? ?installed;
> > - ? ? ? bool ? ? ? ? ? ?sw_int[RADEON_NUM_RINGS];
> > - ? ? ? bool ? ? ? ? ? ?crtc_vblank_int[RADEON_MAX_CRTCS];
> > - ? ? ? bool ? ? ? ? ? ?pflip[RADEON_MAX_CRTCS];
> > - ? ? ? wait_queue_head_t ? ? ? vblank_queue;
> > - ? ? ? bool ? ? ? ? ? ?hpd[RADEON_MAX_HPD_PINS];
> > - ? ? ? bool ? ? ? ? ? ?gui_idle;
> > - ? ? ? bool ? ? ? ? ? ?gui_idle_acked;
> > - ? ? ? wait_queue_head_t ? ? ? idle_queue;
> > - ? ? ? bool ? ? ? ? ? ?afmt[RADEON_MAX_AFMT_BLOCKS];
> > - ? ? ? spinlock_t sw_lock;
> > - ? ? ? int 

[PATCH] staging: omapdrm: fix crash when freeing bad fb

2012-05-24 Thread Andy Gross
During unload, don't cleanup the framebuffer if it is not valid.

Signed-off-by: Andy Gross 
---
 drivers/staging/omapdrm/omap_fbdev.c |   10 +++---
 1 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/omapdrm/omap_fbdev.c 
b/drivers/staging/omapdrm/omap_fbdev.c
index 11acd4c..8c6ed3b 100644
--- a/drivers/staging/omapdrm/omap_fbdev.c
+++ b/drivers/staging/omapdrm/omap_fbdev.c
@@ -208,7 +208,8 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
 */
ret = omap_gem_get_paddr(fbdev->bo, , true);
if (ret) {
-   dev_err(dev->dev, "could not map (paddr)!\n");
+   dev_err(dev->dev,
+   "could not map (paddr)!  Skipping framebuffer alloc\n");
ret = -ENOMEM;
goto fail;
}
@@ -388,8 +389,11 @@ void omap_fbdev_free(struct drm_device *dev)

fbi = helper->fbdev;

-   unregister_framebuffer(fbi);
-   framebuffer_release(fbi);
+   /* only cleanup framebuffer if it is present */
+   if (fbi) {
+   unregister_framebuffer(fbi);
+   framebuffer_release(fbi);
+   }

drm_fb_helper_fini(helper);

-- 
1.7.5.4



[PATCH] staging: omapdrm: Fix error paths during dmm init

2012-05-24 Thread Andy Gross
Failures during the dmm probe can cause the kernel to crash.  Moved
the spinlock to a global and moved list initializations immediately
after the allocation of the dmm private structure.

Signed-off-by: Andy Gross 
---
 drivers/staging/omapdrm/omap_dmm_priv.h  |1 -
 drivers/staging/omapdrm/omap_dmm_tiler.c |   44 -
 2 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/drivers/staging/omapdrm/omap_dmm_priv.h 
b/drivers/staging/omapdrm/omap_dmm_priv.h
index 2f529ab..08b22e9 100644
--- a/drivers/staging/omapdrm/omap_dmm_priv.h
+++ b/drivers/staging/omapdrm/omap_dmm_priv.h
@@ -181,7 +181,6 @@ struct dmm {

/* allocation list and lock */
struct list_head alloc_head;
-   spinlock_t list_lock;
 };

 #endif
diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c 
b/drivers/staging/omapdrm/omap_dmm_tiler.c
index 1ecb6a7..3bc715d 100644
--- a/drivers/staging/omapdrm/omap_dmm_tiler.c
+++ b/drivers/staging/omapdrm/omap_dmm_tiler.c
@@ -40,6 +40,9 @@
 static struct tcm *containers[TILFMT_NFORMATS];
 static struct dmm *omap_dmm;

+/* global spinlock for protecting lists */
+static DEFINE_SPINLOCK(list_lock);
+
 /* Geometry table */
 #define GEOM(xshift, yshift, bytes_per_pixel) { \
.x_shft = (xshift), \
@@ -147,13 +150,13 @@ static struct dmm_txn *dmm_txn_init(struct dmm *dmm, 
struct tcm *tcm)
down(>engine_sem);

/* grab an idle engine */
-   spin_lock(>list_lock);
+   spin_lock(_lock);
if (!list_empty(>idle_head)) {
engine = list_entry(dmm->idle_head.next, struct refill_engine,
idle_node);
list_del(>idle_node);
}
-   spin_unlock(>list_lock);
+   spin_unlock(_lock);

BUG_ON(!engine);

@@ -256,9 +259,9 @@ static int dmm_txn_commit(struct dmm_txn *txn, bool wait)
}

 cleanup:
-   spin_lock(>list_lock);
+   spin_lock(_lock);
list_add(>idle_node, >idle_head);
-   spin_unlock(>list_lock);
+   spin_unlock(_lock);

up(_dmm->engine_sem);
return ret;
@@ -351,9 +354,9 @@ struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, 
uint16_t w,
}

/* add to allocation list */
-   spin_lock(_dmm->list_lock);
+   spin_lock(_lock);
list_add(>alloc_node, _dmm->alloc_head);
-   spin_unlock(_dmm->list_lock);
+   spin_unlock(_lock);

return block;
 }
@@ -374,9 +377,9 @@ struct tiler_block *tiler_reserve_1d(size_t size)
return 0;
}

-   spin_lock(_dmm->list_lock);
+   spin_lock(_lock);
list_add(>alloc_node, _dmm->alloc_head);
-   spin_unlock(_dmm->list_lock);
+   spin_unlock(_lock);

return block;
 }
@@ -389,9 +392,9 @@ int tiler_release(struct tiler_block *block)
if (block->area.tcm)
dev_err(omap_dmm->dev, "failed to release block\n");

-   spin_lock(_dmm->list_lock);
+   spin_lock(_lock);
list_del(>alloc_node);
-   spin_unlock(_dmm->list_lock);
+   spin_unlock(_lock);

kfree(block);
return ret;
@@ -479,13 +482,13 @@ static int omap_dmm_remove(struct platform_device *dev)

if (omap_dmm) {
/* free all area regions */
-   spin_lock(_dmm->list_lock);
+   spin_lock(_lock);
list_for_each_entry_safe(block, _block, _dmm->alloc_head,
alloc_node) {
list_del(>alloc_node);
kfree(block);
}
-   spin_unlock(_dmm->list_lock);
+   spin_unlock(_lock);

for (i = 0; i < omap_dmm->num_lut; i++)
if (omap_dmm->tcm && omap_dmm->tcm[i])
@@ -503,7 +506,7 @@ static int omap_dmm_remove(struct platform_device *dev)

vfree(omap_dmm->lut);

-   if (omap_dmm->irq != -1)
+   if (omap_dmm->irq > 0)
free_irq(omap_dmm->irq, omap_dmm);

iounmap(omap_dmm->base);
@@ -527,6 +530,10 @@ static int omap_dmm_probe(struct platform_device *dev)
goto fail;
}

+   /* initialize lists */
+   INIT_LIST_HEAD(_dmm->alloc_head);
+   INIT_LIST_HEAD(_dmm->idle_head);
+
/* lookup hwmod data - base address and irq */
mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!mem) {
@@ -629,7 +636,6 @@ static int omap_dmm_probe(struct platform_device *dev)
}

sema_init(_dmm->engine_sem, omap_dmm->num_engines);
-   INIT_LIST_HEAD(_dmm->idle_head);
for (i = 0; i < omap_dmm->num_engines; i++) {
omap_dmm->engines[i].id = i;
omap_dmm->engines[i].dmm = omap_dmm;
@@ -672,9 +678,6 @@ static int omap_dmm_probe(struct platform_device *dev)
containers[TILFMT_32BIT] = omap_dmm->tcm[0];
containers[TILFMT_PAGE] = omap_dmm->tcm[0];

-   

[PATCH 0/4] drm/i915: Make video sprites survive a modeset

2012-05-24 Thread Jesse Barnes
On Thu, 24 May 2012 21:29:46 +0300
ville.syrjala at linux.intel.com wrote:

> Currently the video sprites appear to get disabled on modeset more by
> accient than by design.
> 
> With the current API that behaviour makes very little sense to me.
> You first enable some plane, and then it can get disabled due to some
> unrelated operation.
> 
> So these patches change the behaviour so that planes survive a modeset.
> There's a new hook to make sure they get disabled when swithing
> back to fbdev to show a panic oops.

Yeah that's not really a design requirement; the assumption was that
the display manager would do the right thing in any case (both mode
sets and plane sets are privileged ops).  When doing a mode set, the
plane parameters will probably need to be changed anyway...

But keeping it on with some kind of sensible behavior makes the simple
cases easier.

-- 
Jesse Barnes, Intel Open Source Technology Center


[PATCH 07/10] drm/radeon: apply Murphy's law to the kms irq code

2012-05-24 Thread Alex Deucher
On Thu, May 24, 2012 at 3:49 AM, Christian K?nig
 wrote:
> From: Christian Koenig 
>
> 1. It is really dangerous to have more than one
> ? spinlock protecting the same information.
>
> 2. radeon_irq_set sometimes wasn't called with lock
> ? protection, so it can happen that more than one
> ? CPU would tamper with the irq regs at the same
> ? time.
>
> 3. The pm.gui_idle variable was assuming that the 3D
> ? engine wasn't becoming idle between testing the
> ? register and setting the variable. So just remove
> ? it and test the register directly.
>
> Signed-off-by: Christian Koenig 
> ---
> ?drivers/gpu/drm/radeon/evergreen.c ? ? ?| ? ?1 -
> ?drivers/gpu/drm/radeon/r100.c ? ? ? ? ? | ? ?1 -
> ?drivers/gpu/drm/radeon/r600.c ? ? ? ? ? | ? ?1 -
> ?drivers/gpu/drm/radeon/r600_hdmi.c ? ? ?| ? ?6 +--
> ?drivers/gpu/drm/radeon/radeon.h ? ? ? ? | ? 33 +++---
> ?drivers/gpu/drm/radeon/radeon_irq_kms.c | ? 72 
> +--
> ?drivers/gpu/drm/radeon/radeon_kms.c ? ? | ? 12 --
> ?drivers/gpu/drm/radeon/radeon_pm.c ? ? ?| ? 12 +-
> ?drivers/gpu/drm/radeon/rs600.c ? ? ? ? ?| ? ?1 -
> ?drivers/gpu/drm/radeon/si.c ? ? ? ? ? ? | ? ?1 -
> ?10 files changed, 90 insertions(+), 50 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/evergreen.c 
> b/drivers/gpu/drm/radeon/evergreen.c
> index bfcb39e..9e9b3bb 100644
> --- a/drivers/gpu/drm/radeon/evergreen.c
> +++ b/drivers/gpu/drm/radeon/evergreen.c
> @@ -3254,7 +3254,6 @@ restart_ih:
> ? ? ? ? ? ? ? ? ? ? ? ?break;
> ? ? ? ? ? ? ? ?case 233: /* GUI IDLE */
> ? ? ? ? ? ? ? ? ? ? ? ?DRM_DEBUG("IH: GUI idle\n");
> - ? ? ? ? ? ? ? ? ? ? ? rdev->pm.gui_idle = true;
> ? ? ? ? ? ? ? ? ? ? ? ?wake_up(>irq.idle_queue);
> ? ? ? ? ? ? ? ? ? ? ? ?break;
> ? ? ? ? ? ? ? ?default:
> diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
> index 415b7d8..2587426 100644
> --- a/drivers/gpu/drm/radeon/r100.c
> +++ b/drivers/gpu/drm/radeon/r100.c
> @@ -782,7 +782,6 @@ int r100_irq_process(struct radeon_device *rdev)
> ? ? ? ? ? ? ? ?/* gui idle interrupt */
> ? ? ? ? ? ? ? ?if (status & RADEON_GUI_IDLE_STAT) {
> ? ? ? ? ? ? ? ? ? ? ? ?rdev->irq.gui_idle_acked = true;
> - ? ? ? ? ? ? ? ? ? ? ? rdev->pm.gui_idle = true;
> ? ? ? ? ? ? ? ? ? ? ? ?wake_up(>irq.idle_queue);
> ? ? ? ? ? ? ? ?}
> ? ? ? ? ? ? ? ?/* Vertical blank interrupts */
> diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
> index eadbb06..90c6639 100644
> --- a/drivers/gpu/drm/radeon/r600.c
> +++ b/drivers/gpu/drm/radeon/r600.c
> @@ -3542,7 +3542,6 @@ restart_ih:
> ? ? ? ? ? ? ? ? ? ? ? ?break;
> ? ? ? ? ? ? ? ?case 233: /* GUI IDLE */
> ? ? ? ? ? ? ? ? ? ? ? ?DRM_DEBUG("IH: GUI idle\n");
> - ? ? ? ? ? ? ? ? ? ? ? rdev->pm.gui_idle = true;
> ? ? ? ? ? ? ? ? ? ? ? ?wake_up(>irq.idle_queue);
> ? ? ? ? ? ? ? ? ? ? ? ?break;
> ? ? ? ? ? ? ? ?default:
> diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c 
> b/drivers/gpu/drm/radeon/r600_hdmi.c
> index 226379e..b76c0f2 100644
> --- a/drivers/gpu/drm/radeon/r600_hdmi.c
> +++ b/drivers/gpu/drm/radeon/r600_hdmi.c
> @@ -523,8 +523,7 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
>
> ? ? ? ?if (rdev->irq.installed) {
> ? ? ? ? ? ? ? ?/* if irq is available use it */
> - ? ? ? ? ? ? ? rdev->irq.afmt[dig->afmt->id] = true;
> - ? ? ? ? ? ? ? radeon_irq_set(rdev);
> + ? ? ? ? ? ? ? radeon_irq_kms_enable_afmt(rdev, dig->afmt->id);
> ? ? ? ?}
>
> ? ? ? ?dig->afmt->enabled = true;
> @@ -560,8 +559,7 @@ void r600_hdmi_disable(struct drm_encoder *encoder)
> ? ? ? ? ? ? ? ? ?offset, radeon_encoder->encoder_id);
>
> ? ? ? ?/* disable irq */
> - ? ? ? rdev->irq.afmt[dig->afmt->id] = false;
> - ? ? ? radeon_irq_set(rdev);
> + ? ? ? radeon_irq_kms_disable_afmt(rdev, dig->afmt->id);
>
> ? ? ? ?/* Older chipsets not handled by AtomBIOS */
> ? ? ? ?if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index 8479096..23552b4 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -610,21 +610,20 @@ union radeon_irq_stat_regs {
> ?#define RADEON_MAX_AFMT_BLOCKS 6
>
> ?struct radeon_irq {
> - ? ? ? bool ? ? ? ? ? ?installed;
> - ? ? ? bool ? ? ? ? ? ?sw_int[RADEON_NUM_RINGS];
> - ? ? ? bool ? ? ? ? ? ?crtc_vblank_int[RADEON_MAX_CRTCS];
> - ? ? ? bool ? ? ? ? ? ?pflip[RADEON_MAX_CRTCS];
> - ? ? ? wait_queue_head_t ? ? ? vblank_queue;
> - ? ? ? bool ? ? ? ? ? ?hpd[RADEON_MAX_HPD_PINS];
> - ? ? ? bool ? ? ? ? ? ?gui_idle;
> - ? ? ? bool ? ? ? ? ? ?gui_idle_acked;
> - ? ? ? wait_queue_head_t ? ? ? idle_queue;
> - ? ? ? bool ? ? ? ? ? ?afmt[RADEON_MAX_AFMT_BLOCKS];
> - ? ? ? spinlock_t sw_lock;
> - ? ? ? int sw_refcount[RADEON_NUM_RINGS];
> - ? ? ? union radeon_irq_stat_regs stat_regs;
> - ? ? ? spinlock_t pflip_lock[RADEON_MAX_CRTCS];
> - ? ? ? int pflip_refcount[RADEON_MAX_CRTCS];
> + ? ? ? bool ? ? ? ? ? ? ? ? ? ? ? ? ? ?installed;
> + ? ? ? spinlock_t ? ? ? ? ? ? ? ? ? ? ?lock;
> + ? ? ? bool ? ? ? ? ? ? ? ? 

[Intel-gfx] [PATCH 5/6] drm/i915: Handle framebuffer offsets[]

2012-05-24 Thread Jesse Barnes
On Thu, 24 May 2012 21:08:58 +0300
ville.syrjala at linux.intel.com wrote:

> From: Ville Syrj?l? 
> 
> Take fb->offset[0] into account when calculating the linear and tile x/y
> offsets.
> 
> For non-tiled surfaces fb->offset[0] is simply added to the linear
> byte offset.
> 
> For tiled surfaces treat fb->offsets[0] as a byte offset into the
> linearized view of the surface. So we end up converting fb->offsets[0]
> into additional x and y offsets.

Do you have code using a non-zero offsets[0]?  At least for current
code that would indicate some kind of problem... though hopefully we'll
be adding planar support back again sometime soon.

-- 
Jesse Barnes, Intel Open Source Technology Center


[PATCH] omap2+: add drm device

2012-05-24 Thread Tomi Valkeinen
On Thu, 2012-05-24 at 10:05 +0300, Tomi Valkeinen wrote:
> On Thu, 2012-05-24 at 00:27 -0600, Clark, Rob wrote:
> > On Thu, May 24, 2012 at 12:01 AM, Tomi Valkeinen  
> > wrote:
> > > Hi,
> > >
> > > On Wed, 2012-05-23 at 15:08 -0500, Andy Gross wrote:
> > >> Register OMAP DRM/KMS platform device.  DMM is split into a
> > >> separate device using hwmod.
> > >>
> > >> Signed-off-by: Andy Gross 
> > >
> > > 
> > >
> > >> +static int __init omap_init_drm(void)
> > >> +{
> > >> + struct omap_hwmod *oh = NULL;
> > >> + struct platform_device *pdev;
> > >> +
> > >> + /* lookup and populate the DMM information, if present - OMAP4+ */
> > >> + oh = omap_hwmod_lookup("dmm");
> > >> +
> > >> + if (oh) {
> > >> + pdev = omap_device_build(oh->name, -1, oh, NULL, 0, NULL, 
> > >> 0,
> > >> + false);
> > >> + WARN(IS_ERR(pdev), "Could not build omap_device for %s\n",
> > >> + oh->name);
> > >> + }
> > >> +
> > >> + return platform_device_register(_drm_device);
> > >> +
> > >> +}
> > >
> > > I still don't like fixing the tiler to drm. I would like to have basic
> > > tiler support in omapfb also, but with this approach I'll need to
> > > duplicate the code. And even if we disregard omapfb, wouldn't it be
> > > architecturally better to have the tiler as a separate independent
> > > library/driver?
> > 
> > Not easily, at least not if we want to manage to use tiler/dmm in a
> > more dynamic way, or to enable some additional features which are
> > still on the roadmap (like reprogramming dmm synchronized w/ scanout,
> > or some things which are coming if future hw generations).  We need
> > one place to keep track of which buffers are potentially evictable to
> > make room for mapping a new buffer.  And if you look at the tricks
> > that go on with mmap'ing tiled buffers to userspace, you *really*
> > don't want to duplicate that in N different drivers.
> 
> So why can't all that code be in a tiler library/driver?

And I think we've discussed about this before, so sorry if I'm repeating
myself. I just find it odd that we are not able to create a nice
separate lib/driver for the tiler, which is a separate piece of HW that
multiple drivers might want to use.

 Tomi

-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20120524/60e537c3/attachment.pgp>


Oops with Radeon/Uninorth on Maple

2012-05-24 Thread Dmitry Eremin-Solenikov
Hello, colleagues,

I'm trying to enable an AGP slot (again) on my Maple board (dual 
PPC970FX board, with CPC925 (U3H) north bridge).

  For now I'm stuck with a problem: I use radeon card, drm-radeon driver 
with KMS.

If I force drm-radeon to think about a card as about PCI card (by 
commenting corresponding lines in drm_radeon_kms.c), everything works, I 
get framebuffer, working X11, etc. If I enable agpgart-uninorth driver
and RADEON_IS_AGP flag in drm driver, I get an Oops early during the 
bootstrap. Relevant part of the log (I can send full dmesg of normal 
bootstrap or this oops on request, if that would help).

[2.820647] Linux agpgart interface v0.103
[2.824909] agpgart-uninorth :f0:0b.0: Apple U3H chipset
[2.830668] agpgart-uninorth :f0:0b.0: Found device u3, rev 35
[2.843611] agpgart-uninorth :f0:0b.0: configuring for size idx: 64
[2.850638] agpgart-uninorth :f0:0b.0: AGP aperture is 256M @ 0x0
[2.857646] [drm] Initialized drm 1.1.0 20060810
[2.862567] [drm] radeon defaulting to kernel modesetting.
[2.868091] [drm] radeon kernel modesetting enabled.
[2.873222] radeon :f0:10.0: enabling device ( -> 0003)
[2.880311] radeon :f0:10.0: enabling bus mastering
[2.885591] [drm] initializing kernel modesetting (RV350 
0x1002:0x4152 0x18BC:0x0416).
[2.893629] [drm] register mmio base: 0xD002
[2.898260] [drm] register mmio size: 65536
[2.947112] [drm] GPU not posted. posting now...
[3.051033] agpgart-uninorth :f0:0b.0: putting AGP V3 device into 
8x mode
[3.058197] radeon :f0:10.0: putting AGP V3 device into 8x mode
[3.064666] radeon :f0:10.0: GTT: 256M 0x - 0x0FFF
[3.070864] [drm] Generation 2 PCI interface, using max accessible memory
[3.077672] radeon :f0:10.0: VRAM: 128M 0xC000 - 
0xC7FF (128M used)
[3.086487] [drm] Supports vblank timestamp caching Rev 1 (10.10.2010).
[3.093126] [drm] Driver supports precise vblank timestamp query.
[3.099291] [drm] radeon: irq initialized.
[3.103404] [drm] Detected VRAM RAM=128M, BAR=128M
[3.108214] [drm] RAM width 128bits DDR
[3.112263] [TTM] Zone  kernel: Available graphics memory: 496682 kiB
[3.118732] [TTM] Initializing pool allocator
[3.123346] [drm] radeon: 128M of VRAM memory ready
[3.128256] [drm] radeon: 256M of GTT memory ready.
[3.133295] [drm] radeon: ib pool ready.
[3.137708] [drm] radeon: 1 quad pipes, 1 Z pipes initialized.
[3.144018] radeon :f0:10.0: WB disabled
[3.148326] [drm] fence driver on ring 0 use gpu addr 0x and 
cpu addr 0xd0066000
[3.157474] [drm] Loading R300 Microcode
[3.162480] [drm] radeon: ring at 0x1000
[3.167569] [drm] ring test succeeded in 0 usecs
cpu 0x0: Vector: 200 (Machine Check) at [c0d63aa0]
 pc: c00cc07c: .trace_hardirqs_on_caller+0x6c/0x190
 lr: c00152f4: .cpu_idle+0x1a4/0x220
 sp: c0d63d20
msr: 90009032
   current = 0xc0c4db30
   paca= 0xc000   softe: 0irq_happened: 0x01
 pid   = 0, comm = swapper/0
enter ? for help
[c0d63db0] c00152f4 .cpu_idle+0x1a4/0x220
[c0d63e50] c0008fb8 .rest_init+0xe8/0x110
[c0d63ee0] c0ba2998 .start_kernel+0x3e4/0x408
[c0d63f90] c0007558 .start_here_common+0x20/0x48
0:mon> x
[  843.783295] Oops: Machine check, sig: 7 [#1]
[  843.787589] SMP NR_CPUS=4 Maple
[  843.790768] Modules linked in:
[  843.793855] NIP: c00cc07c LR: c00152f4 CTR: 
c0023eac
[  843.800920] REGS: c0d63aa0 TRAP: 0200   Not tainted  (3.4.0+)
[  843.807376] MSR: 90009032   CR: 
2422  XER: 0006
[  843.815412] SOFTE: 0
[  843.817607] TASK = c0c4db30[0] 'swapper/0' THREAD: 
c0d6 CPU: 0
[  843.825035] GPR00:  c0d63d20 c0d63280 
c00152f4
[  843.833169] GPR04:  c0099d10 0001 
0002
[  843.841302] GPR08: 0100 c0e828e8 0140 

[  843.849436] GPR12: 4482 c000  

[  843.857570] GPR16: 00ff8750 00cdc890 010001e0 

[  843.865702] GPR20:   1dcd6500 

[  843.873835] GPR24:  00ec7b00 90009032 
c0d7b178
[  843.881979] GPR28: c0d7b278 0008 c0c970f8 
c00152f4
[  843.890314] NIP [c00cc07c] .trace_hardirqs_on_caller+0x6c/0x190
[  843.896942] LR [c00152f4] .cpu_idle+0x1a4/0x220
[  843.902181] Call Trace:
[  843.904640] [c0d63d20] [c0d63db0] 
init_thread_union+0x3db0/0x4000 (unreliable)
[  843.913317] [c0d63db0] [c00152f4] .cpu_idle+0x1a4/0x220
[  

[PATCH] omap2+: add drm device

2012-05-24 Thread Gross, Andy
On Thu, May 24, 2012 at 7:13 AM, Tomi Valkeinen  
wrote:
> On Thu, 2012-05-24 at 02:44 -0600, Rob Clark wrote:
>
>> but other drivers *can* use tiler, thanks to dmabuf.. I have omap4iss
>> v4l2 camera working w/ tiler buffers on my pandaboard, for example.
>>
>> Maybe fbdev is an exception to the rule because it has no way for
>> userspace to pass it a buffer to use. ?But on the other hand it is a
>> legacy API so I'm not sure if it is worth loosing too much sleep over
>> that.
>
> I'm not that familiar with dmabuf, but are you saying it's not possible
> for a kernel driver to request the buffers? They _must_ come from the
> userspace?
>
> Anyway, even if it would be possible, if the tiler is a part of omapdrm
> we need omapdrm to get and use the tiler buffers. And we can't have
> omapdrm running when using omapfb, because they both use omapdss.

And that is a good point.  The DSS is kind of a sticking point to anyone
having to enable DRM to get Tiler.  However, omapfb doesn't currently utilize
DMM/Tiler features.  Can't we defer generalizing until there is a
requirement for it?

Andy


[PATCH] omap2+: add drm device

2012-05-24 Thread Tomi Valkeinen
On Thu, 2012-05-24 at 00:27 -0600, Clark, Rob wrote:
> On Thu, May 24, 2012 at 12:01 AM, Tomi Valkeinen  
> wrote:
> > Hi,
> >
> > On Wed, 2012-05-23 at 15:08 -0500, Andy Gross wrote:
> >> Register OMAP DRM/KMS platform device.  DMM is split into a
> >> separate device using hwmod.
> >>
> >> Signed-off-by: Andy Gross 
> >
> > 
> >
> >> +static int __init omap_init_drm(void)
> >> +{
> >> + struct omap_hwmod *oh = NULL;
> >> + struct platform_device *pdev;
> >> +
> >> + /* lookup and populate the DMM information, if present - OMAP4+ */
> >> + oh = omap_hwmod_lookup("dmm");
> >> +
> >> + if (oh) {
> >> + pdev = omap_device_build(oh->name, -1, oh, NULL, 0, NULL, 0,
> >> + false);
> >> + WARN(IS_ERR(pdev), "Could not build omap_device for %s\n",
> >> + oh->name);
> >> + }
> >> +
> >> + return platform_device_register(_drm_device);
> >> +
> >> +}
> >
> > I still don't like fixing the tiler to drm. I would like to have basic
> > tiler support in omapfb also, but with this approach I'll need to
> > duplicate the code. And even if we disregard omapfb, wouldn't it be
> > architecturally better to have the tiler as a separate independent
> > library/driver?
> 
> Not easily, at least not if we want to manage to use tiler/dmm in a
> more dynamic way, or to enable some additional features which are
> still on the roadmap (like reprogramming dmm synchronized w/ scanout,
> or some things which are coming if future hw generations).  We need
> one place to keep track of which buffers are potentially evictable to
> make room for mapping a new buffer.  And if you look at the tricks
> that go on with mmap'ing tiled buffers to userspace, you *really*
> don't want to duplicate that in N different drivers.

So why can't all that code be in a tiler library/driver?

> Fortunately with dmabuf there is not really a need for N different
> drivers to need to use tiler/dmm directly.  The dmabuf mechanism
> provides what they need to import GEM buffers from omapdrm.  That may
> not really help omapfb because fbdev doesn't have a concept of
> importing buffers.  But OTOH this is unnecessary, because drm provides
> an fbdev interface for legacy apps.  The best thing I'd recommend is,
> if you miss some features of omapfb in the drm fbdev implementation,
> is to send some patches to add this missing features.

Well, at least currently omapfb and omapdrm work quite differently, if
I've understood right. Can we make a full omapfb layer on top of
omapdrm? With multiple framebuffers mapped to one or more overlays,
support for all the ioctls, etc?

I guess we'd still need to have omapfb driver to keep the module
parameters and behavior the same. Can omapdrm be used from inside the
kernel by another driver?

 Tomi

-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20120524/555fd618/attachment.pgp>


GPU lockup dumping

2012-05-24 Thread Christian König
On 23.05.2012 19:02, Jerome Glisse wrote:
> On Wed, May 23, 2012 at 12:41 PM, Dave Airlie  wrote:
>> On Wed, May 23, 2012 at 5:26 PM, Jerome Glisse  wrote:
>>> On Wed, May 23, 2012 at 12:08 PM, Dave Airlie  wrote:
 On Wed, May 23, 2012 at 3:48 PM, Jerome Glisse  
 wrote:
> On Wed, May 23, 2012 at 8:34 AM, Christian K?nig
>   wrote:
>> On 23.05.2012 11:27, Dave Airlie wrote:
>>> On Thu, May 17, 2012 at 7:28 PM,wrote:
 So here is improved patchset, where i splited ground work necessary
 for the dumping into their own patch. The debugfs improvement could
 probably be usefull to intel instead of having i915 have it's own
 debugfs file stuff.

 The lockup dumping public api have been move into radeon_drm.h

 Stressing the fact again that dump are self contained ie they have
 all the data needed to be replayed (vertex, indices, shader, texture,
 ...).

 Would really like to get this into 3.5, the new API is pretty much
 straightforward and userspace tools can easily be made to convert
 it to other format. The change to the driver is self contained.
>>> I really don't like introducing this at this stage into 3.5,
>>>
>>> I'd really like a good review of the API and what information we provide
>>> along with how extensible it is.
>>>
>>> I'm still not convinced replay is what we want in the field, I know its
>>> what
>>> *you* want, but I think apitrace stuff in userspace pretty much covers
>>> the replaying situation. So I'd have to look at this and see how easy
>>> it makes disecting command streams etc.
>>>
>>> Dave.
>>
>> I agree that it might not be a good idea to push that into 3.5, since at
>> least I (and I also think Alex) didn't had time to look into it yet. On 
>> the
>> other hand the patches look quite reasonable.
>>
>> But I still wanted to throw in a requirement from my day to day work, 
>> maybe
>> that helps finding a more general solution:
>> When we start to work with more parts of the chip it might be necessary 
>> to
>> dump everything that is currently "in the fly". For example I had a whole
>> bunch of problems where copying data around with a 3D Blit and then 
>> missing
>> a sync between this job and a job on another rings causes a "hiccup" in 
>> the
>> hardware.
>>
>> I know that this isn't your focus and that is absolutely ok with me, 
>> cause
>> the format you are introducing is just used in debugfs and so not part of
>> any stable API (at least not in my understanding), but you should still 
>> keep
>> in mind that we might need to extend it into that direction in the 
>> future.
>>
>> Christian.
> Note that my format is also done with that in mind, it can capture ib
> from all rings. The only thing i don't think worth capturing are the
> ring themself because there would be no way to replay them without
> adding some new special API.
 I'd like to dump the rings as well, as I said I'd rather we didn't
 limit this to replay, but make it useful for getting as much info as
 possible out

 Dave.
>>> Ring will contains very little, like ib schedule and fence, i don't
>>> see how useful this can be.
>>>
>> In case we have a bug in our ib scheduling or fencing :-0
>>
>> Dave.
> Well i think we have several kind of lockup, the most basic one is
> userspace sending broken shader, vertex, or something in that line.
> The more complex one is timing related, like a bo move or some cache
> invalidation that didn't happen properly and GPU endup reading either
> wrong data or old cached data. I don't see how to capture useful
> information for this second case, beside doing snapshot of memory.
>
> For multi-ring i agree that dumping the ring might prove useful spot
> inter-ring semaphore deadlock, or possibly inter-ring absence of
> synchronization (but that would be a bad kernel bug).

I don't think that we need the actual data from the rings neither (at 
least as long as we keep the radeon_ring_* debugfs files). But it would 
still be nice to know weather or not there was a sync between the rings. 
See the patches I just send to you (sorry, actually send more patches 
than I wanted to send), storing the new sync_seq array within the debug 
output should enable us to actually figure out the dependencies and 
order between different IBs.

Cheers,
Christian.



[PATCH] drm: fix case where panic notifier isn't unregistered

2012-05-24 Thread Frank Binns
Hi,
I don't know if this patch got missed in the list traffic or if I did something 
wrong but it doesn't appear to have been picked up. This is my first time 
contributing so if I did anything wrong some pointers would be appreciated.

Thanks
Frank


> From: dri-devel-bounces+frank.binns=imgtec.com at lists.freedesktop.org 
> [mailto:dri-devel-bounces+frank.binns=imgtec.com at lists.freedesktop.org] On 
> Behalf Of Frank Binns
> Sent: 14 May 2012 16:28
> To: 'airlied at linux.ie'; 'dri-devel at lists.freedesktop.org'
> Subject: [PATCH] drm: fix case where panic notifier isn't unregistered
>
> The framebuffer helper panic notifier is unregistered, in 
> drm_fb_helper_fini(), when kernel_fb_helper_list goes from being non-empty to 
> empty. However, in drm_fb_helper_single_fb_probe(), it's possible for the 
> panic notifier to be registered without an element being added to this list 
> if a driver's probe function returns 0. Make sure that an attempt to add the 
> panic notifier is made only when adding an element to kernel_fb_helper_list.
>
> Signed-off-by: Frank Binns 
> ---
> drivers/gpu/drm/drm_fb_helper.c |?? 21 ++---
> 1 files changed, 10 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index a0d6e89..d3764b3 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -807,21 +807,20 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper 
> *fb_helper,
>?? printk(KERN_INFO "fb%d: %s frame buffer 
>device\n", info->node,
>?? ???info->fix.id);
>
> + /* Switch back to kernel console on panic */
> + /* multi card linked list maybe */
> + if (list_empty(_fb_helper_list)) {
> + printk(KERN_INFO "drm: 
> registered panic notifier\n");
> + 
> atomic_notifier_chain_register(_notifier_list,
> +
>  ?? );
> + register_sysrq_key('v', 
> _drm_fb_helper_restore_op);
> + }
> +
> + list_add(_helper->kernel_fb_list, 
> _fb_helper_list);
>?? } else {
>?? drm_fb_helper_set_par(info);
>?? }
>
> -? /* Switch back to kernel console on panic */
> -? /* multi card linked list maybe */
> -? if (list_empty(_fb_helper_list)) {
> -? printk(KERN_INFO "drm: registered panic 
> notifier\n");
> -? 
> atomic_notifier_chain_register(_notifier_list,
> -?
>  ?? );
> -? register_sysrq_key('v', 
> _drm_fb_helper_restore_op);
> -? }
> -? if (new_fb)
> -? list_add(_helper->kernel_fb_list, 
> _fb_helper_list);
> -
>?? return 0;
> }
> EXPORT_SYMBOL(drm_fb_helper_single_fb_probe);
> -- 
> 1.7.5.4




[PATCH 10/10] drm/radeon: work around bugs in caymans compute rings

2012-05-24 Thread Christian König
From: Christian Koenig 

The shader preemption on cayman doesn't work
correctly with multiple rings. So to be able to
still make use of the compute rings we use a
semaphore to make sure that only one IB can execute
at the same time.

This isn't as effective as shader preemption, but
also isn't as bad as putting everything on the GFX ring.

Signed-off-by: Christian Koenig 
---
 drivers/gpu/drm/radeon/ni.c|  142 ++--
 drivers/gpu/drm/radeon/radeon.h|2 +
 drivers/gpu/drm/radeon/radeon_cs.c |2 +-
 3 files changed, 139 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 9d9f5ac..6a3e8a8 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1125,13 +1125,75 @@ void cayman_fence_ring_emit(struct radeon_device *rdev,
radeon_ring_write(ring, 0);
 }

+/* The shader preemption on cayman doesn't work
+ * correctly with multiple rings. So to be able to
+ * still make use of the compute rings we use a
+ * semaphore to make sure that only one IB can execute
+ * at the same time
+ */
+static void cayman_cp_ring_create_workaround(struct radeon_device *rdev)
+{
+   struct radeon_ring *ring = >ring[RADEON_RING_TYPE_GFX_INDEX];
+   int r;
+
+   r = radeon_semaphore_create(rdev, >cayman_ring_lock);
+   if (r) {
+   dev_err(rdev->dev, "Can't allocate "
+   "cayman_ring_lock (%d)!\n", r);
+   return;
+   }
+
+   r = radeon_ring_alloc(rdev, ring, 8);
+   if (r) {
+   dev_err(rdev->dev, "Can't initialize "
+   "cayman_ring_lock (%d)!\n", r);
+   radeon_semaphore_free(rdev, >cayman_ring_lock, NULL);
+   return;
+   }
+
+   radeon_semaphore_emit_signal(rdev, RADEON_RING_TYPE_GFX_INDEX,
+rdev->cayman_ring_lock);
+
+   radeon_ring_commit(rdev, >ring[RADEON_RING_TYPE_GFX_INDEX]);
+}
+
+static void cayman_cp_ring_cleanup_workaround(struct radeon_device *rdev)
+{
+   struct radeon_fence *fence;
+   int r;
+
+   r = radeon_fence_emit(rdev, , RADEON_RING_TYPE_GFX_INDEX);
+   if (r) {
+   dev_err(rdev->dev, "Can't cleanup "
+   "cayman_ring_lock (%d)!\n", r);
+   return;
+   }
+
+   radeon_semaphore_free(rdev, >cayman_ring_lock, fence);
+   radeon_fence_unref();
+}
+
 void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
 {
struct radeon_ring *ring = >ring[ib->ring];

+   if (ib->ring != RADEON_RING_TYPE_GFX_INDEX) {
+   if (rdev->cayman_ring_lock == NULL) {
+   cayman_cp_ring_create_workaround(rdev);
+   }
+   } else {
+   if (rdev->cayman_ring_lock != NULL &&
+   !radeon_fence_count_emitted(rdev, 
CAYMAN_RING_TYPE_CP1_INDEX) &&
+   !radeon_fence_count_emitted(rdev, 
CAYMAN_RING_TYPE_CP2_INDEX)) {
+   cayman_cp_ring_cleanup_workaround(rdev);
+   }
+   }
+
/* set to DX10/11 mode */
radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0));
radeon_ring_write(ring, 1);
+   if (rdev->cayman_ring_lock)
+   radeon_semaphore_emit_wait(rdev, ib->ring, 
rdev->cayman_ring_lock);
radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
radeon_ring_write(ring,
 #ifdef __BIG_ENDIAN
@@ -1140,6 +1202,8 @@ void cayman_ring_ib_execute(struct radeon_device *rdev, 
struct radeon_ib *ib)
  (ib->gpu_addr & 0xFFFC));
radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFF);
radeon_ring_write(ring, ib->length_dw | (ib->vm_id << 24));
+   if (rdev->cayman_ring_lock)
+   radeon_semaphore_emit_signal(rdev, ib->ring, 
rdev->cayman_ring_lock);

/* flush read cache over gart for this vmid */
radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
@@ -1190,6 +1254,25 @@ static int cayman_cp_load_microcode(struct radeon_device 
*rdev)
return 0;
 }

+static int cayman_cp_start_compute(struct radeon_device *rdev, int ridx)
+{
+   struct radeon_ring *ring = >ring[ridx];
+   int r;
+
+   r = radeon_ring_lock(rdev, ring, 2);
+   if (r) {
+   DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
+   return r;
+   }
+
+   /* clear the compute context state */
+   radeon_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0) | 2);
+   radeon_ring_write(ring, 0);
+
+   radeon_ring_unlock_commit(rdev, ring);
+   return 0;
+}
+
 static int cayman_cp_start(struct radeon_device *rdev)
 {
struct radeon_ring *ring = >ring[RADEON_RING_TYPE_GFX_INDEX];
@@ -1251,7 +1334,17 @@ static int cayman_cp_start(struct radeon_device *rdev)

radeon_ring_unlock_commit(rdev, ring);

-   /* XXX init 

[PATCH 09/10] drm/radeon: replace cs_mutex with vm_mutex

2012-05-24 Thread Christian König
Try to remove or replace the cs_mutex with a
vm_mutex where it is still needed.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h|   44 +---
 drivers/gpu/drm/radeon/radeon_cs.c |7 ++---
 drivers/gpu/drm/radeon/radeon_device.c |2 +-
 drivers/gpu/drm/radeon/radeon_gart.c   |   16 ++--
 drivers/gpu/drm/radeon/radeon_gem.c|2 --
 5 files changed, 12 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 60de11e..58a2fcf 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -159,48 +159,6 @@ static inline int radeon_atrm_get_bios_chunk(uint8_t 
*bios, int offset, int len)
 #endif
 bool radeon_get_bios(struct radeon_device *rdev);

-
-/*
- * Mutex which allows recursive locking from the same process.
- */
-struct radeon_mutex {
-   struct mutexmutex;
-   struct task_struct  *owner;
-   int level;
-};
-
-static inline void radeon_mutex_init(struct radeon_mutex *mutex)
-{
-   mutex_init(>mutex);
-   mutex->owner = NULL;
-   mutex->level = 0;
-}
-
-static inline void radeon_mutex_lock(struct radeon_mutex *mutex)
-{
-   if (mutex_trylock(>mutex)) {
-   /* The mutex was unlocked before, so it's ours now */
-   mutex->owner = current;
-   } else if (mutex->owner != current) {
-   /* Another process locked the mutex, take it */
-   mutex_lock(>mutex);
-   mutex->owner = current;
-   }
-   /* Otherwise the mutex was already locked by this process */
-
-   mutex->level++;
-}
-
-static inline void radeon_mutex_unlock(struct radeon_mutex *mutex)
-{
-   if (--mutex->level > 0)
-   return;
-
-   mutex->owner = NULL;
-   mutex_unlock(>mutex);
-}
-
-
 /*
  * Dummy page
  */
@@ -1527,7 +1485,6 @@ struct radeon_device {
struct radeon_gem   gem;
struct radeon_pmpm;
uint32_tbios_scratch[RADEON_BIOS_NUM_SCRATCH];
-   struct radeon_mutex cs_mutex;
struct radeon_wbwb;
struct radeon_dummy_pagedummy_page;
boolshutdown;
@@ -1561,6 +1518,7 @@ struct radeon_device {
struct radeon_debugfs   debugfs[RADEON_DEBUGFS_MAX_COMPONENTS];
unsigneddebugfs_count;
/* virtual memory */
+   struct mutexvm_mutex;
struct radeon_vm_managervm_manager;
 };

diff --git a/drivers/gpu/drm/radeon/radeon_cs.c 
b/drivers/gpu/drm/radeon/radeon_cs.c
index d295821..d1ead9c 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -438,6 +438,7 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev,
}

mutex_lock(>mutex);
+   mutex_lock(>vm_mutex);
r = radeon_vm_bind(rdev, vm);
if (r) {
goto out;
@@ -474,6 +475,7 @@ out:
}
vm->fence = radeon_fence_ref(parser->ib.fence);
}
+   mutex_unlock(>vm_mutex);
mutex_unlock(>vm.mutex);
return r;
 }
@@ -494,9 +496,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
struct radeon_cs_parser parser;
int r;

-   radeon_mutex_lock(>cs_mutex);
if (!rdev->accel_working) {
-   radeon_mutex_unlock(>cs_mutex);
return -EBUSY;
}
/* initialize parser */
@@ -510,7 +510,6 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
DRM_ERROR("Failed to initialize parser !\n");
radeon_cs_parser_fini(, r);
r = radeon_cs_handle_lockup(rdev, r);
-   radeon_mutex_unlock(>cs_mutex);
return r;
}
r = radeon_cs_parser_relocs();
@@ -519,7 +518,6 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
DRM_ERROR("Failed to parse relocation %d!\n", r);
radeon_cs_parser_fini(, r);
r = radeon_cs_handle_lockup(rdev, r);
-   radeon_mutex_unlock(>cs_mutex);
return r;
}
r = radeon_cs_ib_chunk(rdev, );
@@ -533,7 +531,6 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
 out:
radeon_cs_parser_fini(, r);
r = radeon_cs_handle_lockup(rdev, r);
-   radeon_mutex_unlock(>cs_mutex);
return r;
 }

diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index 3c563d1..4168012 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -728,7 +728,6 @@ int radeon_device_init(struct radeon_device *rdev,

/* mutex initialization are all done here so we
 * 

[PATCH 07/10] drm/radeon: apply Murphy's law to the kms irq code

2012-05-24 Thread Christian König
From: Christian Koenig 

1. It is really dangerous to have more than one
   spinlock protecting the same information.

2. radeon_irq_set sometimes wasn't called with lock
   protection, so it can happen that more than one
   CPU would tamper with the irq regs at the same
   time.

3. The pm.gui_idle variable was assuming that the 3D
   engine wasn't becoming idle between testing the
   register and setting the variable. So just remove
   it and test the register directly.

Signed-off-by: Christian Koenig 
---
 drivers/gpu/drm/radeon/evergreen.c  |1 -
 drivers/gpu/drm/radeon/r100.c   |1 -
 drivers/gpu/drm/radeon/r600.c   |1 -
 drivers/gpu/drm/radeon/r600_hdmi.c  |6 +--
 drivers/gpu/drm/radeon/radeon.h |   33 +++---
 drivers/gpu/drm/radeon/radeon_irq_kms.c |   72 +--
 drivers/gpu/drm/radeon/radeon_kms.c |   12 --
 drivers/gpu/drm/radeon/radeon_pm.c  |   12 +-
 drivers/gpu/drm/radeon/rs600.c  |1 -
 drivers/gpu/drm/radeon/si.c |1 -
 10 files changed, 90 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c 
b/drivers/gpu/drm/radeon/evergreen.c
index bfcb39e..9e9b3bb 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -3254,7 +3254,6 @@ restart_ih:
break;
case 233: /* GUI IDLE */
DRM_DEBUG("IH: GUI idle\n");
-   rdev->pm.gui_idle = true;
wake_up(>irq.idle_queue);
break;
default:
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 415b7d8..2587426 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -782,7 +782,6 @@ int r100_irq_process(struct radeon_device *rdev)
/* gui idle interrupt */
if (status & RADEON_GUI_IDLE_STAT) {
rdev->irq.gui_idle_acked = true;
-   rdev->pm.gui_idle = true;
wake_up(>irq.idle_queue);
}
/* Vertical blank interrupts */
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index eadbb06..90c6639 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -3542,7 +3542,6 @@ restart_ih:
break;
case 233: /* GUI IDLE */
DRM_DEBUG("IH: GUI idle\n");
-   rdev->pm.gui_idle = true;
wake_up(>irq.idle_queue);
break;
default:
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c 
b/drivers/gpu/drm/radeon/r600_hdmi.c
index 226379e..b76c0f2 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -523,8 +523,7 @@ void r600_hdmi_enable(struct drm_encoder *encoder)

if (rdev->irq.installed) {
/* if irq is available use it */
-   rdev->irq.afmt[dig->afmt->id] = true;
-   radeon_irq_set(rdev);
+   radeon_irq_kms_enable_afmt(rdev, dig->afmt->id);
}

dig->afmt->enabled = true;
@@ -560,8 +559,7 @@ void r600_hdmi_disable(struct drm_encoder *encoder)
  offset, radeon_encoder->encoder_id);

/* disable irq */
-   rdev->irq.afmt[dig->afmt->id] = false;
-   radeon_irq_set(rdev);
+   radeon_irq_kms_disable_afmt(rdev, dig->afmt->id);

/* Older chipsets not handled by AtomBIOS */
if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 8479096..23552b4 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -610,21 +610,20 @@ union radeon_irq_stat_regs {
 #define RADEON_MAX_AFMT_BLOCKS 6

 struct radeon_irq {
-   boolinstalled;
-   boolsw_int[RADEON_NUM_RINGS];
-   boolcrtc_vblank_int[RADEON_MAX_CRTCS];
-   boolpflip[RADEON_MAX_CRTCS];
-   wait_queue_head_t   vblank_queue;
-   boolhpd[RADEON_MAX_HPD_PINS];
-   boolgui_idle;
-   boolgui_idle_acked;
-   wait_queue_head_t   idle_queue;
-   boolafmt[RADEON_MAX_AFMT_BLOCKS];
-   spinlock_t sw_lock;
-   int sw_refcount[RADEON_NUM_RINGS];
-   union radeon_irq_stat_regs stat_regs;
-   spinlock_t pflip_lock[RADEON_MAX_CRTCS];
-   int pflip_refcount[RADEON_MAX_CRTCS];
+   boolinstalled;
+   spinlock_t  lock;
+   boolsw_int[RADEON_NUM_RINGS];
+   int sw_refcount[RADEON_NUM_RINGS];
+   boolcrtc_vblank_int[RADEON_MAX_CRTCS];
+   bool

[PATCH 06/10] drm/radeon: fix & improve ih ring handling

2012-05-24 Thread Christian König
From: Christian Koenig 

The spinlock was actually there to protect the
rptr, but rptr was read outside of the locked area.

Also we don't really need a spinlock here, an
atomic should to quite fine since we only need to
prevent it from being reentrant.

Signed-off-by: Christian Koenig 
---
 drivers/gpu/drm/radeon/evergreen.c |   29 -
 drivers/gpu/drm/radeon/r600.c  |   30 +++---
 drivers/gpu/drm/radeon/radeon.h|3 +--
 drivers/gpu/drm/radeon/radeon_device.c |3 +--
 drivers/gpu/drm/radeon/si.c|   30 --
 5 files changed, 49 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c 
b/drivers/gpu/drm/radeon/evergreen.c
index dd3cea4..bfcb39e 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -2943,7 +2943,6 @@ int evergreen_irq_process(struct radeon_device *rdev)
u32 rptr;
u32 src_id, src_data;
u32 ring_index;
-   unsigned long flags;
bool queue_hotplug = false;
bool queue_hdmi = false;

@@ -2951,22 +2950,24 @@ int evergreen_irq_process(struct radeon_device *rdev)
return IRQ_NONE;

wptr = evergreen_get_ih_wptr(rdev);
+
+restart_ih:
+   /* is somebody else already processing irqs? */
+   if (atomic_xchg(>ih.lock, 1))
+   return IRQ_NONE;
+
rptr = rdev->ih.rptr;
+   if (rptr == wptr)
+   return IRQ_NONE;
+
DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);

-   spin_lock_irqsave(>ih.lock, flags);
-   if (rptr == wptr) {
-   spin_unlock_irqrestore(>ih.lock, flags);
-   return IRQ_NONE;
-   }
-restart_ih:
/* Order reading of wptr vs. reading of IH ring data */
rmb();

/* display interrupts */
evergreen_irq_ack(rdev);

-   rdev->ih.wptr = wptr;
while (rptr != wptr) {
/* wptr/rptr are in bytes! */
ring_index = rptr / 4;
@@ -3265,17 +3266,19 @@ restart_ih:
rptr += 16;
rptr &= rdev->ih.ptr_mask;
}
-   /* make sure wptr hasn't changed while processing */
-   wptr = evergreen_get_ih_wptr(rdev);
-   if (wptr != rdev->ih.wptr)
-   goto restart_ih;
if (queue_hotplug)
schedule_work(>hotplug_work);
if (queue_hdmi)
schedule_work(>audio_work);
rdev->ih.rptr = rptr;
WREG32(IH_RB_RPTR, rdev->ih.rptr);
-   spin_unlock_irqrestore(>ih.lock, flags);
+   atomic_set(>ih.lock, 0);
+
+   /* make sure wptr hasn't changed while processing */
+   wptr = evergreen_get_ih_wptr(rdev);
+   if (wptr != rptr)
+   goto restart_ih;
+
return IRQ_HANDLED;
 }

diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index a8d8c44..eadbb06 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2921,7 +2921,6 @@ void r600_disable_interrupts(struct radeon_device *rdev)
WREG32(IH_RB_RPTR, 0);
WREG32(IH_RB_WPTR, 0);
rdev->ih.enabled = false;
-   rdev->ih.wptr = 0;
rdev->ih.rptr = 0;
 }

@@ -3373,7 +3372,6 @@ int r600_irq_process(struct radeon_device *rdev)
u32 rptr;
u32 src_id, src_data;
u32 ring_index;
-   unsigned long flags;
bool queue_hotplug = false;
bool queue_hdmi = false;

@@ -3385,24 +3383,24 @@ int r600_irq_process(struct radeon_device *rdev)
RREG32(IH_RB_WPTR);

wptr = r600_get_ih_wptr(rdev);
-   rptr = rdev->ih.rptr;
-   DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);

-   spin_lock_irqsave(>ih.lock, flags);
+restart_ih:
+   /* is somebody else already processing irqs? */
+   if (atomic_xchg(>ih.lock, 1))
+   return IRQ_NONE;

-   if (rptr == wptr) {
-   spin_unlock_irqrestore(>ih.lock, flags);
+   rptr = rdev->ih.rptr;
+   if (rptr == wptr)
return IRQ_NONE;
-   }

-restart_ih:
+   DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
+
/* Order reading of wptr vs. reading of IH ring data */
rmb();

/* display interrupts */
r600_irq_ack(rdev);

-   rdev->ih.wptr = wptr;
while (rptr != wptr) {
/* wptr/rptr are in bytes! */
ring_index = rptr / 4;
@@ -3556,17 +3554,19 @@ restart_ih:
rptr += 16;
rptr &= rdev->ih.ptr_mask;
}
-   /* make sure wptr hasn't changed while processing */
-   wptr = r600_get_ih_wptr(rdev);
-   if (wptr != rdev->ih.wptr)
-   goto restart_ih;
if (queue_hotplug)
schedule_work(>hotplug_work);
if (queue_hdmi)
schedule_work(>audio_work);
rdev->ih.rptr = rptr;

[PATCH 05/10] drm/radeon: remove some unneeded structure members

2012-05-24 Thread Christian König
From: Christian Koenig 

Signed-off-by: Christian Koenig 
---
 drivers/gpu/drm/radeon/radeon.h |2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 3e83480..618df9a 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -733,9 +733,7 @@ struct r600_ih {
struct radeon_bo*ring_obj;
volatile uint32_t   *ring;
unsignedrptr;
-   unsignedrptr_offs;
unsignedwptr;
-   unsignedwptr_old;
unsignedring_size;
uint64_tgpu_addr;
uint32_tptr_mask;
-- 
1.7.9.5



  1   2   3   >