Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca5a1b9b authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-intel-next-2014-06-20' of git://anongit.freedesktop.org/drm-intel into drm-next

- Accurate frontbuffer tracking and frontbuffer rendering invalidate, flush and
  flip events. This is prep work for proper PSR support and should also be
  useful for DRRS&fbc.
- Runtime suspend hardware on system suspend to support the new SOix sleep
  states, from Jesse.
- PSR updates for broadwell (Rodrigo)
- Universal plane support for cursors (Matt Roper), including core drm patches.
- Prefault gtt mappings (Chris)
- baytrail write-enable pte bit support (Akash Goel)
- mmio based flips (Sourab Gupta) instead of blitter ring flips
- interrupt handling race fixes (Oscar Mateo)

And old, not yet merged features from the previous round:
- rps/turbo support for chv (Deepak)
- some other straggling chv patches (Ville)
- proper universal plane conversion for the primary plane (Matt Roper)
- ppgtt on vlv from Jesse
- pile of cleanups, little fixes for insane corner cases and improved debug
  support all over

* tag 'drm-intel-next-2014-06-20' of git://anongit.freedesktop.org/drm-intel: (99 commits)
  drm/i915: Update DRIVER_DATE to 20140620
  drivers/i915: Fix unnoticed failure of init_ring_common()
  drm/i915: Track frontbuffer invalidation/flushing
  drm/i915: Use new frontbuffer bits to increase pll clock
  drm/i915: don't take runtime PM reference around freeze/thaw
  drm/i915: use runtime irq suspend/resume in freeze/thaw
  drm/i915: Properly track domain of the fbcon fb
  drm/i915: Print obj->frontbuffer_bits in debugfs output
  drm/i915: Introduce accurate frontbuffer tracking
  drm/i915: Drop schedule_back from psr_exit
  drm/i915: Ditch intel_edp_psr_update
  drm/i915: Drop unecessary complexity from psr_inactivate
  drm/i915: Remove ctx->last_ring
  drm/i915/chv: Ack interrupts before handling them (CHV)
  drm/i915/bdw: Ack interrupts before handling them (GEN8)
  drm/i915/vlv: Ack interrupts before handling them (VLV)
  drm/i915: Ack interrupts before handling them (GEN5 - GEN7)
  drm/i915: Don't BUG_ON in i915_gem_obj_offset
  drm/i915: Grab dev->struct_mutex in i915_gem_pageflip_info
  drm/i915: Add some L3 registers to the parser whitelist
  ...

Conflicts:
	drivers/gpu/drm/i915/i915_drv.c
parents c7dbc6c9 34882298
Loading
Loading
Loading
Loading
+255 −102
Original line number Diff line number Diff line
@@ -41,6 +41,10 @@

#include "drm_crtc_internal.h"

static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
							struct drm_mode_fb_cmd2 *r,
							struct drm_file *file_priv);

/**
 * drm_modeset_lock_all - take all modeset locks
 * @dev: drm device
@@ -723,7 +727,7 @@ DEFINE_WW_CLASS(crtc_ww_class);
 */
int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
			      struct drm_plane *primary,
			      void *cursor,
			      struct drm_plane *cursor,
			      const struct drm_crtc_funcs *funcs)
{
	struct drm_mode_config *config = &dev->mode_config;
@@ -748,8 +752,11 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
	config->num_crtc++;

	crtc->primary = primary;
	crtc->cursor = cursor;
	if (primary)
		primary->possible_crtcs = 1 << drm_crtc_index(crtc);
	if (cursor)
		cursor->possible_crtcs = 1 << drm_crtc_index(crtc);

 out:
	drm_modeset_unlock_all(dev);
@@ -2177,45 +2184,32 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
	return ret;
}

/**
 * drm_mode_setplane - configure a plane's configuration
 * @dev: DRM device
 * @data: ioctl data*
 * @file_priv: DRM file info
/*
 * setplane_internal - setplane handler for internal callers
 *
 * Set plane configuration, including placement, fb, scaling, and other factors.
 * Or pass a NULL fb to disable.
 * Note that we assume an extra reference has already been taken on fb.  If the
 * update fails, this reference will be dropped before return; if it succeeds,
 * the previous framebuffer (if any) will be unreferenced instead.
 *
 * Returns:
 * Zero on success, errno on failure.
 * src_{x,y,w,h} are provided in 16.16 fixed point format
 */
int drm_mode_setplane(struct drm_device *dev, void *data,
		      struct drm_file *file_priv)
static int setplane_internal(struct drm_plane *plane,
			     struct drm_crtc *crtc,
			     struct drm_framebuffer *fb,
			     int32_t crtc_x, int32_t crtc_y,
			     uint32_t crtc_w, uint32_t crtc_h,
			     /* src_{x,y,w,h} values are 16.16 fixed point */
			     uint32_t src_x, uint32_t src_y,
			     uint32_t src_w, uint32_t src_h)
{
	struct drm_mode_set_plane *plane_req = data;
	struct drm_plane *plane;
	struct drm_crtc *crtc;
	struct drm_framebuffer *fb = NULL, *old_fb = NULL;
	struct drm_device *dev = plane->dev;
	struct drm_framebuffer *old_fb = NULL;
	int ret = 0;
	unsigned int fb_width, fb_height;
	int i;

	if (!drm_core_check_feature(dev, DRIVER_MODESET))
		return -EINVAL;

	/*
	 * First, find the plane, crtc, and fb objects.  If not available,
	 * we don't bother to call the driver.
	 */
	plane = drm_plane_find(dev, plane_req->plane_id);
	if (!plane) {
		DRM_DEBUG_KMS("Unknown plane ID %d\n",
			      plane_req->plane_id);
		return -ENOENT;
	}

	/* No fb means shut it down */
	if (!plane_req->fb_id) {
	if (!fb) {
		drm_modeset_lock_all(dev);
		old_fb = plane->fb;
		ret = plane->funcs->disable_plane(plane);
@@ -2229,14 +2223,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
		goto out;
	}

	crtc = drm_crtc_find(dev, plane_req->crtc_id);
	if (!crtc) {
		DRM_DEBUG_KMS("Unknown crtc ID %d\n",
			      plane_req->crtc_id);
		ret = -ENOENT;
		goto out;
	}

	/* Check whether this plane is usable on this CRTC */
	if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
		DRM_DEBUG_KMS("Invalid crtc for plane\n");
@@ -2244,14 +2230,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
		goto out;
	}

	fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
	if (!fb) {
		DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
			      plane_req->fb_id);
		ret = -ENOENT;
		goto out;
	}

	/* Check whether this plane supports the fb pixel format. */
	for (i = 0; i < plane->format_count; i++)
		if (fb->pixel_format == plane->format_types[i])
@@ -2267,43 +2245,25 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
	fb_height = fb->height << 16;

	/* Make sure source coordinates are inside the fb. */
	if (plane_req->src_w > fb_width ||
	    plane_req->src_x > fb_width - plane_req->src_w ||
	    plane_req->src_h > fb_height ||
	    plane_req->src_y > fb_height - plane_req->src_h) {
	if (src_w > fb_width ||
	    src_x > fb_width - src_w ||
	    src_h > fb_height ||
	    src_y > fb_height - src_h) {
		DRM_DEBUG_KMS("Invalid source coordinates "
			      "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
			      plane_req->src_w >> 16,
			      ((plane_req->src_w & 0xffff) * 15625) >> 10,
			      plane_req->src_h >> 16,
			      ((plane_req->src_h & 0xffff) * 15625) >> 10,
			      plane_req->src_x >> 16,
			      ((plane_req->src_x & 0xffff) * 15625) >> 10,
			      plane_req->src_y >> 16,
			      ((plane_req->src_y & 0xffff) * 15625) >> 10);
			      src_w >> 16, ((src_w & 0xffff) * 15625) >> 10,
			      src_h >> 16, ((src_h & 0xffff) * 15625) >> 10,
			      src_x >> 16, ((src_x & 0xffff) * 15625) >> 10,
			      src_y >> 16, ((src_y & 0xffff) * 15625) >> 10);
		ret = -ENOSPC;
		goto out;
	}

	/* Give drivers some help against integer overflows */
	if (plane_req->crtc_w > INT_MAX ||
	    plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w ||
	    plane_req->crtc_h > INT_MAX ||
	    plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) {
		DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
			      plane_req->crtc_w, plane_req->crtc_h,
			      plane_req->crtc_x, plane_req->crtc_y);
		ret = -ERANGE;
		goto out;
	}

	drm_modeset_lock_all(dev);
	old_fb = plane->fb;
	ret = plane->funcs->update_plane(plane, crtc, fb,
					 plane_req->crtc_x, plane_req->crtc_y,
					 plane_req->crtc_w, plane_req->crtc_h,
					 plane_req->src_x, plane_req->src_y,
					 plane_req->src_w, plane_req->src_h);
					 crtc_x, crtc_y, crtc_w, crtc_h,
					 src_x, src_y, src_w, src_h);
	if (!ret) {
		plane->crtc = crtc;
		plane->fb = fb;
@@ -2320,6 +2280,85 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
		drm_framebuffer_unreference(old_fb);

	return ret;

}

/**
 * drm_mode_setplane - configure a plane's configuration
 * @dev: DRM device
 * @data: ioctl data*
 * @file_priv: DRM file info
 *
 * Set plane configuration, including placement, fb, scaling, and other factors.
 * Or pass a NULL fb to disable (planes may be disabled without providing a
 * valid crtc).
 *
 * Returns:
 * Zero on success, errno on failure.
 */
int drm_mode_setplane(struct drm_device *dev, void *data,
		      struct drm_file *file_priv)
{
	struct drm_mode_set_plane *plane_req = data;
	struct drm_mode_object *obj;
	struct drm_plane *plane;
	struct drm_crtc *crtc = NULL;
	struct drm_framebuffer *fb = NULL;

	if (!drm_core_check_feature(dev, DRIVER_MODESET))
		return -EINVAL;

	/* Give drivers some help against integer overflows */
	if (plane_req->crtc_w > INT_MAX ||
	    plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w ||
	    plane_req->crtc_h > INT_MAX ||
	    plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) {
		DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
			      plane_req->crtc_w, plane_req->crtc_h,
			      plane_req->crtc_x, plane_req->crtc_y);
		return -ERANGE;
	}

	/*
	 * First, find the plane, crtc, and fb objects.  If not available,
	 * we don't bother to call the driver.
	 */
	obj = drm_mode_object_find(dev, plane_req->plane_id,
				   DRM_MODE_OBJECT_PLANE);
	if (!obj) {
		DRM_DEBUG_KMS("Unknown plane ID %d\n",
			      plane_req->plane_id);
		return -ENOENT;
	}
	plane = obj_to_plane(obj);

	if (plane_req->fb_id) {
		fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
		if (!fb) {
			DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
				      plane_req->fb_id);
			return -ENOENT;
		}

		obj = drm_mode_object_find(dev, plane_req->crtc_id,
					   DRM_MODE_OBJECT_CRTC);
		if (!obj) {
			DRM_DEBUG_KMS("Unknown crtc ID %d\n",
				      plane_req->crtc_id);
			return -ENOENT;
		}
		crtc = obj_to_crtc(obj);
	}

	/*
	 * setplane_internal will take care of deref'ing either the old or new
	 * framebuffer depending on success.
	 */
	return setplane_internal(plane, crtc, fb,
				 plane_req->crtc_x, plane_req->crtc_y,
				 plane_req->crtc_w, plane_req->crtc_h,
				 plane_req->src_x, plane_req->src_y,
				 plane_req->src_w, plane_req->src_h);
}

/**
@@ -2568,6 +2607,102 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
	return ret;
}

/**
 * drm_mode_cursor_universal - translate legacy cursor ioctl call into a
 *     universal plane handler call
 * @crtc: crtc to update cursor for
 * @req: data pointer for the ioctl
 * @file_priv: drm file for the ioctl call
 *
 * Legacy cursor ioctl's work directly with driver buffer handles.  To
 * translate legacy ioctl calls into universal plane handler calls, we need to
 * wrap the native buffer handle in a drm_framebuffer.
 *
 * Note that we assume any handle passed to the legacy ioctls was a 32-bit ARGB
 * buffer with a pitch of 4*width; the universal plane interface should be used
 * directly in cases where the hardware can support other buffer settings and
 * userspace wants to make use of these capabilities.
 *
 * Returns:
 * Zero on success, errno on failure.
 */
static int drm_mode_cursor_universal(struct drm_crtc *crtc,
				     struct drm_mode_cursor2 *req,
				     struct drm_file *file_priv)
{
	struct drm_device *dev = crtc->dev;
	struct drm_framebuffer *fb = NULL;
	struct drm_mode_fb_cmd2 fbreq = {
		.width = req->width,
		.height = req->height,
		.pixel_format = DRM_FORMAT_ARGB8888,
		.pitches = { req->width * 4 },
		.handles = { req->handle },
	};
	int32_t crtc_x, crtc_y;
	uint32_t crtc_w = 0, crtc_h = 0;
	uint32_t src_w = 0, src_h = 0;
	int ret = 0;

	BUG_ON(!crtc->cursor);

	/*
	 * Obtain fb we'll be using (either new or existing) and take an extra
	 * reference to it if fb != null.  setplane will take care of dropping
	 * the reference if the plane update fails.
	 */
	if (req->flags & DRM_MODE_CURSOR_BO) {
		if (req->handle) {
			fb = add_framebuffer_internal(dev, &fbreq, file_priv);
			if (IS_ERR(fb)) {
				DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n");
				return PTR_ERR(fb);
			}

			drm_framebuffer_reference(fb);
		} else {
			fb = NULL;
		}
	} else {
		mutex_lock(&dev->mode_config.mutex);
		fb = crtc->cursor->fb;
		if (fb)
			drm_framebuffer_reference(fb);
		mutex_unlock(&dev->mode_config.mutex);
	}

	if (req->flags & DRM_MODE_CURSOR_MOVE) {
		crtc_x = req->x;
		crtc_y = req->y;
	} else {
		crtc_x = crtc->cursor_x;
		crtc_y = crtc->cursor_y;
	}

	if (fb) {
		crtc_w = fb->width;
		crtc_h = fb->height;
		src_w = fb->width << 16;
		src_h = fb->height << 16;
	}

	/*
	 * setplane_internal will take care of deref'ing either the old or new
	 * framebuffer depending on success.
	 */
	ret = setplane_internal(crtc->cursor, crtc, fb,
				crtc_x, crtc_y, crtc_w, crtc_h,
				0, 0, src_w, src_h);

	/* Update successful; save new cursor position, if necessary */
	if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) {
		crtc->cursor_x = req->x;
		crtc->cursor_y = req->y;
	}

	return ret;
}

static int drm_mode_cursor_common(struct drm_device *dev,
				  struct drm_mode_cursor2 *req,
				  struct drm_file *file_priv)
@@ -2587,6 +2722,13 @@ static int drm_mode_cursor_common(struct drm_device *dev,
		return -ENOENT;
	}

	/*
	 * If this crtc has a universal cursor plane, call that plane's update
	 * handler rather than using legacy cursor handlers.
	 */
	if (crtc->cursor)
		return drm_mode_cursor_universal(crtc, req, file_priv);

	drm_modeset_lock(&crtc->mutex, NULL);
	if (req->flags & DRM_MODE_CURSOR_BO) {
		if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
@@ -2886,56 +3028,38 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
	return 0;
}

/**
 * drm_mode_addfb2 - add an FB to the graphics configuration
 * @dev: drm device for the ioctl
 * @data: data pointer for the ioctl
 * @file_priv: drm file for the ioctl call
 *
 * Add a new FB to the specified CRTC, given a user request with format. This is
 * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers
 * and uses fourcc codes as pixel format specifiers.
 *
 * Called by the user via ioctl.
 *
 * Returns:
 * Zero on success, errno on failure.
 */
int drm_mode_addfb2(struct drm_device *dev,
		    void *data, struct drm_file *file_priv)
static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
							struct drm_mode_fb_cmd2 *r,
							struct drm_file *file_priv)
{
	struct drm_mode_fb_cmd2 *r = data;
	struct drm_mode_config *config = &dev->mode_config;
	struct drm_framebuffer *fb;
	int ret;

	if (!drm_core_check_feature(dev, DRIVER_MODESET))
		return -EINVAL;

	if (r->flags & ~DRM_MODE_FB_INTERLACED) {
		DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
		return -EINVAL;
		return ERR_PTR(-EINVAL);
	}

	if ((config->min_width > r->width) || (r->width > config->max_width)) {
		DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
			  r->width, config->min_width, config->max_width);
		return -EINVAL;
		return ERR_PTR(-EINVAL);
	}
	if ((config->min_height > r->height) || (r->height > config->max_height)) {
		DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",
			  r->height, config->min_height, config->max_height);
		return -EINVAL;
		return ERR_PTR(-EINVAL);
	}

	ret = framebuffer_check(r);
	if (ret)
		return ret;
		return ERR_PTR(ret);

	fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
	if (IS_ERR(fb)) {
		DRM_DEBUG_KMS("could not create framebuffer\n");
		return PTR_ERR(fb);
		return fb;
	}

	mutex_lock(&file_priv->fbs_lock);
@@ -2944,8 +3068,37 @@ int drm_mode_addfb2(struct drm_device *dev,
	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
	mutex_unlock(&file_priv->fbs_lock);

	return fb;
}

	return ret;
/**
 * drm_mode_addfb2 - add an FB to the graphics configuration
 * @dev: drm device for the ioctl
 * @data: data pointer for the ioctl
 * @file_priv: drm file for the ioctl call
 *
 * Add a new FB to the specified CRTC, given a user request with format. This is
 * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers
 * and uses fourcc codes as pixel format specifiers.
 *
 * Called by the user via ioctl.
 *
 * Returns:
 * Zero on success, errno on failure.
 */
int drm_mode_addfb2(struct drm_device *dev,
		    void *data, struct drm_file *file_priv)
{
	struct drm_framebuffer *fb;

	if (!drm_core_check_feature(dev, DRIVER_MODESET))
		return -EINVAL;

	fb = add_framebuffer_internal(dev, data, file_priv);
	if (IS_ERR(fb))
		return PTR_ERR(fb);

	return 0;
}

/**
+3 −0
Original line number Diff line number Diff line
@@ -426,6 +426,9 @@ static const u32 gen7_render_regs[] = {
	GEN7_SO_WRITE_OFFSET(1),
	GEN7_SO_WRITE_OFFSET(2),
	GEN7_SO_WRITE_OFFSET(3),
	GEN7_L3SQCREG1,
	GEN7_L3CNTLREG2,
	GEN7_L3CNTLREG3,
};

static const u32 gen7_blt_regs[] = {
+34 −18
Original line number Diff line number Diff line
@@ -170,6 +170,8 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
	}
	if (obj->ring != NULL)
		seq_printf(m, " (%s)", obj->ring->name);
	if (obj->frontbuffer_bits)
		seq_printf(m, " (frontbuffer: 0x%03x)", obj->frontbuffer_bits);
}

static void describe_ctx(struct seq_file *m, struct intel_context *ctx)
@@ -515,6 +517,11 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data)
	struct drm_device *dev = node->minor->dev;
	unsigned long flags;
	struct intel_crtc *crtc;
	int ret;

	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;

	for_each_intel_crtc(dev, crtc) {
		const char pipe = pipe_name(crtc->pipe);
@@ -556,6 +563,8 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data)
		spin_unlock_irqrestore(&dev->event_lock, flags);
	}

	mutex_unlock(&dev->struct_mutex);

	return 0;
}

@@ -1029,7 +1038,8 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
			   MEMSTAT_VID_SHIFT);
		seq_printf(m, "Current P-state: %d\n",
			   (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
	} else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) {
	} else if (IS_GEN6(dev) || (IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) ||
		   IS_BROADWELL(dev)) {
		u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
		u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
		u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
@@ -1048,7 +1058,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused)

		reqf = I915_READ(GEN6_RPNSWREQ);
		reqf &= ~GEN6_TURBO_DISABLE;
		if (IS_HASWELL(dev))
		if (IS_HASWELL(dev) || IS_BROADWELL(dev))
			reqf >>= 24;
		else
			reqf >>= 25;
@@ -1065,7 +1075,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
		rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI);
		rpcurdown = I915_READ(GEN6_RP_CUR_DOWN);
		rpprevdown = I915_READ(GEN6_RP_PREV_DOWN);
		if (IS_HASWELL(dev))
		if (IS_HASWELL(dev) || IS_BROADWELL(dev))
			cagf = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT;
		else
			cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT;
@@ -1677,9 +1687,6 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)

#ifdef CONFIG_DRM_I915_FBDEV
	struct drm_i915_private *dev_priv = dev->dev_private;
	int ret = mutex_lock_interruptible(&dev->mode_config.mutex);
	if (ret)
		return ret;

	ifbdev = dev_priv->fbdev;
	fb = to_intel_framebuffer(ifbdev->helper.fb);
@@ -1692,7 +1699,6 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
		   atomic_read(&fb->base.refcount.refcount));
	describe_obj(m, fb->obj);
	seq_putc(m, '\n');
	mutex_unlock(&dev->mode_config.mutex);
#endif

	mutex_lock(&dev->mode_config.fb_lock);
@@ -1723,7 +1729,7 @@ static int i915_context_status(struct seq_file *m, void *unused)
	struct intel_context *ctx;
	int ret, i;

	ret = mutex_lock_interruptible(&dev->mode_config.mutex);
	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;

@@ -1753,7 +1759,7 @@ static int i915_context_status(struct seq_file *m, void *unused)
		seq_putc(m, '\n');
	}

	mutex_unlock(&dev->mode_config.mutex);
	mutex_unlock(&dev->struct_mutex);

	return 0;
}
@@ -1978,10 +1984,12 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)

	seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support));
	seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok));
	seq_printf(m, "Enabled: %s\n", yesno(dev_priv->psr.enabled));
	seq_printf(m, "Active: %s\n", yesno(dev_priv->psr.active));

	enabled = HAS_PSR(dev) &&
		I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE;
	seq_printf(m, "Enabled: %s\n", yesno(enabled));
	seq_printf(m, "HW Enabled & Active bit: %s\n", yesno(enabled));

	if (HAS_PSR(dev))
		psrperf = I915_READ(EDP_PSR_PERF_CNT(dev)) &
@@ -2223,9 +2231,12 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *intel_crtc)
	struct drm_crtc *crtc = &intel_crtc->base;
	struct intel_encoder *intel_encoder;

	if (crtc->primary->fb)
		seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n",
			   crtc->primary->fb->base.id, crtc->x, crtc->y,
			   crtc->primary->fb->width, crtc->primary->fb->height);
	else
		seq_puts(m, "\tprimary plane disabled\n");
	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
		intel_encoder_info(m, intel_crtc, intel_encoder);
}
@@ -2929,11 +2940,16 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
	/* real source -> none transition */
	if (source == INTEL_PIPE_CRC_SOURCE_NONE) {
		struct intel_pipe_crc_entry *entries;
		struct intel_crtc *crtc =
			to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);

		DRM_DEBUG_DRIVER("stopping CRCs for pipe %c\n",
				 pipe_name(pipe));

		drm_modeset_lock(&crtc->base.mutex, NULL);
		if (crtc->active)
			intel_wait_for_vblank(dev, pipe);
		drm_modeset_unlock(&crtc->base.mutex);

		spin_lock_irq(&pipe_crc->lock);
		entries = pipe_crc->entries;
@@ -3506,7 +3522,7 @@ i915_max_freq_get(void *data, u64 *val)
	struct drm_i915_private *dev_priv = dev->dev_private;
	int ret;

	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
	if (INTEL_INFO(dev)->gen < 6)
		return -ENODEV;

	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
@@ -3532,7 +3548,7 @@ i915_max_freq_set(void *data, u64 val)
	u32 rp_state_cap, hw_max, hw_min;
	int ret;

	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
	if (INTEL_INFO(dev)->gen < 6)
		return -ENODEV;

	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
@@ -3587,7 +3603,7 @@ i915_min_freq_get(void *data, u64 *val)
	struct drm_i915_private *dev_priv = dev->dev_private;
	int ret;

	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
	if (INTEL_INFO(dev)->gen < 6)
		return -ENODEV;

	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
@@ -3613,7 +3629,7 @@ i915_min_freq_set(void *data, u64 val)
	u32 rp_state_cap, hw_max, hw_min;
	int ret;

	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
	if (INTEL_INFO(dev)->gen < 6)
		return -ENODEV;

	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
+19 −15
Original line number Diff line number Diff line
@@ -369,6 +369,7 @@ static int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords)

	for (i = 0; i < dwords;) {
		int sz = validate_cmd(buffer[i]);

		if (sz == 0 || i + sz > dwords)
			return -EINVAL;
		i += sz;
@@ -1266,6 +1267,7 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
{
	struct drm_device *dev = pci_get_drvdata(pdev);
	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };

	if (state == VGA_SWITCHEROO_ON) {
		pr_info("switched on\n");
		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
@@ -1488,10 +1490,11 @@ static void i915_dump_device_info(struct drm_i915_private *dev_priv)
#define SEP_EMPTY
#define PRINT_FLAG(name) info->name ? #name "," : ""
#define SEP_COMMA ,
	DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x flags="
	DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x rev=0x%02x flags="
			 DEV_INFO_FOR_EACH_FLAG(PRINT_S, SEP_EMPTY),
			 info->gen,
			 dev_priv->dev->pdev->device,
			 dev_priv->dev->pdev->revision,
			 DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_COMMA));
#undef PRINT_S
#undef SEP_EMPTY
@@ -1602,6 +1605,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
	spin_lock_init(&dev_priv->backlight_lock);
	spin_lock_init(&dev_priv->uncore.lock);
	spin_lock_init(&dev_priv->mm.object_stat_lock);
	spin_lock_init(&dev_priv->mmio_flip_lock);
	mutex_init(&dev_priv->dpio_lock);
	mutex_init(&dev_priv->modeset_restore_lock);

+24 −15
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
 */

#include <linux/device.h>
#include <linux/acpi.h>
#include <drm/drmP.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
@@ -46,8 +47,6 @@ static struct drm_driver driver;
			  PIPE_C_OFFSET, PIPE_EDP_OFFSET }, \
	.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
			   TRANSCODER_C_OFFSET, TRANSCODER_EDP_OFFSET }, \
	.dpll_offsets = { DPLL_A_OFFSET, DPLL_B_OFFSET }, \
	.dpll_md_offsets = { DPLL_A_MD_OFFSET, DPLL_B_MD_OFFSET }, \
	.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET }

#define GEN_CHV_PIPEOFFSETS \
@@ -55,10 +54,6 @@ static struct drm_driver driver;
			  CHV_PIPE_C_OFFSET }, \
	.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
			   CHV_TRANSCODER_C_OFFSET, }, \
	.dpll_offsets = { DPLL_A_OFFSET, DPLL_B_OFFSET, \
			  CHV_DPLL_C_OFFSET }, \
	.dpll_md_offsets = { DPLL_A_MD_OFFSET, DPLL_B_MD_OFFSET, \
			     CHV_DPLL_C_MD_OFFSET }, \
	.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET, \
			     CHV_PALETTE_C_OFFSET }

@@ -499,8 +494,7 @@ static int i915_drm_freeze(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_crtc *crtc;

	intel_runtime_pm_get(dev_priv);
	pci_power_t opregion_target_state;

	/* ignore lid events during suspend */
	mutex_lock(&dev_priv->modeset_restore_lock);
@@ -526,9 +520,9 @@ static int i915_drm_freeze(struct drm_device *dev)
			return error;
		}

		drm_irq_uninstall(dev);
		intel_runtime_pm_disable_interrupts(dev);

		intel_disable_gt_powersave(dev);
		intel_suspend_gt_powersave(dev);

		/*
		 * Disable CRTCs directly since we want to preserve sw state
@@ -547,8 +541,14 @@ static int i915_drm_freeze(struct drm_device *dev)

	i915_save_state(dev);

	if (acpi_target_system_state() >= ACPI_STATE_S3)
		opregion_target_state = PCI_D3cold;
	else
		opregion_target_state = PCI_D1;
	intel_opregion_notify_adapter(dev, opregion_target_state);

	intel_uncore_forcewake_reset(dev, false);
	intel_opregion_fini(dev);
	intel_uncore_fini(dev);

	console_lock();
	intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED);
@@ -556,6 +556,8 @@ static int i915_drm_freeze(struct drm_device *dev)

	dev_priv->suspend_count++;

	intel_display_set_init_power(dev_priv, false);

	return 0;
}

@@ -605,7 +607,10 @@ static int i915_drm_thaw_early(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;

	intel_uncore_early_sanitize(dev);
	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
		hsw_disable_pc8(dev_priv);

	intel_uncore_early_sanitize(dev, true);
	intel_uncore_sanitize(dev);
	intel_power_domains_init_hw(dev_priv);

@@ -638,8 +643,7 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
		}
		mutex_unlock(&dev->struct_mutex);

		/* We need working interrupts for modeset enabling ... */
		drm_irq_install(dev, dev->pdev->irq);
		intel_runtime_pm_restore_interrupts(dev);

		intel_modeset_init_hw(dev);

@@ -676,7 +680,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
	dev_priv->modeset_restore = MODESET_DONE;
	mutex_unlock(&dev_priv->modeset_restore_lock);

	intel_runtime_pm_put(dev_priv);
	intel_opregion_notify_adapter(dev, PCI_D0);

	return 0;
}

@@ -885,6 +890,7 @@ static int i915_pm_suspend_late(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct drm_device *drm_dev = pci_get_drvdata(pdev);
	struct drm_i915_private *dev_priv = drm_dev->dev_private;

	/*
	 * We have a suspedn ordering issue with the snd-hda driver also
@@ -898,6 +904,9 @@ static int i915_pm_suspend_late(struct device *dev)
	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
		return 0;

	if (IS_HASWELL(drm_dev) || IS_BROADWELL(drm_dev))
		hsw_enable_pc8(dev_priv);

	pci_disable_device(pdev);
	pci_set_power_state(pdev, PCI_D3hot);

Loading