[PATCH] drm/radeon: fix typo in trinity tiling setup
From: Alex DeucherUsing 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
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)
https://bugs.freedesktop.org/show_bug.cgi?id=50325 --- Comment #2 from T?r?k Edwin2012-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)
https://bugs.freedesktop.org/show_bug.cgi?id=50325 --- Comment #1 from T?r?k Edwin2012-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)
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
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[]
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
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
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
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
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
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
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
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
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
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
... 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
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
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
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
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
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
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
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
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
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
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
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
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
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[]
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
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
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
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
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
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
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[]
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()
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
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
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
Just a few small items caught in my net while trawling the code.
[PATCH 0/4] drm/i915: Make video sprites survive a modeset
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
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
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
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
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
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
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
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
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
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
> -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
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
> 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
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
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
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
>> 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
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
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
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
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
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
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
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()
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
> + 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
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
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
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
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
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
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
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
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
> -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
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
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
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
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
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
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
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
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
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
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
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[]
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
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
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: 90009032CR: 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
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
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
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
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
From: Christian KoenigThe 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
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
From: Christian Koenig1. 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
From: Christian KoenigThe 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
From: Christian KoenigSigned-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