Browse Source

Merge tag 'topic/drm-misc-2015-03-31' of git://anongit.freedesktop.org/drm-intel into drm-next

Final drm-misc pull for 4.0, just various things all over, including a few
more important atomic fixes. btw I didn't pick up the vmwgfx patch from
Ville's series, but one patch has one hunk touching vmwgfx and
Thomas/Jakob didn't get around to ack it. I figured it's simple enough to
be ok though.

* tag 'topic/drm-misc-2015-03-31' of git://anongit.freedesktop.org/drm-intel:
  drm: line wrap DRM_IOCTL_DEF* macros
  drm/atomic: Don't try to free a NULL state
  drm/atomic: Clear crtcs, connectors and planes when clearing state
  drm: Rewrite drm_ioctl_flags() to resemble the new drm_ioctl() code
  drm: Use max() to make the ioctl alloc size code cleaner
  drm: Simplify core vs. drv ioctl handling
  drm: Drop ioctl->cmd_drv
  drm: Fix DRM_IOCTL_DEF_DRV()
  drm/atomic-helpers: Properly avoid full modeset dance
  drm: atomic: Allow setting CRTC active property
  drm: atomic: Expose CRTC active property
  drm: crtc_helper: Update hwmode before mode_set call
  drm: mode: Allow NULL modes for equality check
  drm: fb_helper: Simplify exit condition
  drm: mode: Fix typo in kerneldoc
  drm/dp: Print the number of bytes processed for aux nacks
Dave Airlie 10 years ago
parent
commit
53d8858bb8

+ 22 - 5
drivers/gpu/drm/drm_atomic.c

@@ -134,6 +134,7 @@ void drm_atomic_state_clear(struct drm_atomic_state *state)
 
 
 		connector->funcs->atomic_destroy_state(connector,
 		connector->funcs->atomic_destroy_state(connector,
 						       state->connector_states[i]);
 						       state->connector_states[i]);
+		state->connectors[i] = NULL;
 		state->connector_states[i] = NULL;
 		state->connector_states[i] = NULL;
 	}
 	}
 
 
@@ -145,6 +146,7 @@ void drm_atomic_state_clear(struct drm_atomic_state *state)
 
 
 		crtc->funcs->atomic_destroy_state(crtc,
 		crtc->funcs->atomic_destroy_state(crtc,
 						  state->crtc_states[i]);
 						  state->crtc_states[i]);
+		state->crtcs[i] = NULL;
 		state->crtc_states[i] = NULL;
 		state->crtc_states[i] = NULL;
 	}
 	}
 
 
@@ -156,6 +158,7 @@ void drm_atomic_state_clear(struct drm_atomic_state *state)
 
 
 		plane->funcs->atomic_destroy_state(plane,
 		plane->funcs->atomic_destroy_state(plane,
 						   state->plane_states[i]);
 						   state->plane_states[i]);
+		state->planes[i] = NULL;
 		state->plane_states[i] = NULL;
 		state->plane_states[i] = NULL;
 	}
 	}
 }
 }
@@ -170,6 +173,9 @@ EXPORT_SYMBOL(drm_atomic_state_clear);
  */
  */
 void drm_atomic_state_free(struct drm_atomic_state *state)
 void drm_atomic_state_free(struct drm_atomic_state *state)
 {
 {
+	if (!state)
+		return;
+
 	drm_atomic_state_clear(state);
 	drm_atomic_state_clear(state);
 
 
 	DRM_DEBUG_ATOMIC("Freeing atomic state %p\n", state);
 	DRM_DEBUG_ATOMIC("Freeing atomic state %p\n", state);
@@ -248,11 +254,14 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
 	struct drm_mode_config *config = &dev->mode_config;
 	struct drm_mode_config *config = &dev->mode_config;
 
 
 	/* FIXME: Mode prop is missing, which also controls ->enable. */
 	/* FIXME: Mode prop is missing, which also controls ->enable. */
-	if (property == config->prop_active) {
+	if (property == config->prop_active)
 		state->active = val;
 		state->active = val;
-	} else if (crtc->funcs->atomic_set_property)
+	else if (crtc->funcs->atomic_set_property)
 		return crtc->funcs->atomic_set_property(crtc, state, property, val);
 		return crtc->funcs->atomic_set_property(crtc, state, property, val);
-	return -EINVAL;
+	else
+		return -EINVAL;
+
+	return 0;
 }
 }
 EXPORT_SYMBOL(drm_atomic_crtc_set_property);
 EXPORT_SYMBOL(drm_atomic_crtc_set_property);
 
 
@@ -266,9 +275,17 @@ int drm_atomic_crtc_get_property(struct drm_crtc *crtc,
 		const struct drm_crtc_state *state,
 		const struct drm_crtc_state *state,
 		struct drm_property *property, uint64_t *val)
 		struct drm_property *property, uint64_t *val)
 {
 {
-	if (crtc->funcs->atomic_get_property)
+	struct drm_device *dev = crtc->dev;
+	struct drm_mode_config *config = &dev->mode_config;
+
+	if (property == config->prop_active)
+		*val = state->active;
+	else if (crtc->funcs->atomic_get_property)
 		return crtc->funcs->atomic_get_property(crtc, state, property, val);
 		return crtc->funcs->atomic_get_property(crtc, state, property, val);
-	return -EINVAL;
+	else
+		return -EINVAL;
+
+	return 0;
 }
 }
 
 
 /**
 /**

+ 4 - 2
drivers/gpu/drm/drm_atomic_helper.c

@@ -587,7 +587,8 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
 
 
 		old_crtc_state = old_state->crtc_states[drm_crtc_index(old_conn_state->crtc)];
 		old_crtc_state = old_state->crtc_states[drm_crtc_index(old_conn_state->crtc)];
 
 
-		if (!old_crtc_state->active)
+		if (!old_crtc_state->active ||
+		    !needs_modeset(old_conn_state->crtc->state))
 			continue;
 			continue;
 
 
 		encoder = old_conn_state->best_encoder;
 		encoder = old_conn_state->best_encoder;
@@ -847,7 +848,8 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
 		if (!connector || !connector->state->best_encoder)
 		if (!connector || !connector->state->best_encoder)
 			continue;
 			continue;
 
 
-		if (!connector->state->crtc->state->active)
+		if (!connector->state->crtc->state->active ||
+		    !needs_modeset(connector->state->crtc->state))
 			continue;
 			continue;
 
 
 		encoder = connector->state->best_encoder;
 		encoder = connector->state->best_encoder;

+ 5 - 4
drivers/gpu/drm/drm_crtc_helper.c

@@ -270,7 +270,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 			      struct drm_framebuffer *old_fb)
 			      struct drm_framebuffer *old_fb)
 {
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_device *dev = crtc->dev;
-	struct drm_display_mode *adjusted_mode, saved_mode;
+	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
 	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 	struct drm_encoder_helper_funcs *encoder_funcs;
 	struct drm_encoder_helper_funcs *encoder_funcs;
 	int saved_x, saved_y;
 	int saved_x, saved_y;
@@ -292,6 +292,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 	}
 	}
 
 
 	saved_mode = crtc->mode;
 	saved_mode = crtc->mode;
+	saved_hwmode = crtc->hwmode;
 	saved_x = crtc->x;
 	saved_x = crtc->x;
 	saved_y = crtc->y;
 	saved_y = crtc->y;
 
 
@@ -334,6 +335,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 	}
 	}
 	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
 	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
 
 
+	crtc->hwmode = *adjusted_mode;
+
 	/* Prepare the encoders and CRTCs before setting the mode. */
 	/* Prepare the encoders and CRTCs before setting the mode. */
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 
 
@@ -396,9 +399,6 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 			encoder->bridge->funcs->enable(encoder->bridge);
 			encoder->bridge->funcs->enable(encoder->bridge);
 	}
 	}
 
 
-	/* Store real post-adjustment hardware mode. */
-	crtc->hwmode = *adjusted_mode;
-
 	/* Calculate and store various constants which
 	/* Calculate and store various constants which
 	 * are later needed by vblank and swap-completion
 	 * are later needed by vblank and swap-completion
 	 * timestamping. They are derived from true hwmode.
 	 * timestamping. They are derived from true hwmode.
@@ -411,6 +411,7 @@ done:
 	if (!ret) {
 	if (!ret) {
 		crtc->enabled = saved_enabled;
 		crtc->enabled = saved_enabled;
 		crtc->mode = saved_mode;
 		crtc->mode = saved_mode;
+		crtc->hwmode = saved_hwmode;
 		crtc->x = saved_x;
 		crtc->x = saved_x;
 		crtc->y = saved_y;
 		crtc->y = saved_y;
 	}
 	}

+ 2 - 2
drivers/gpu/drm/drm_dp_helper.c

@@ -462,7 +462,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
 			break;
 			break;
 
 
 		case DP_AUX_NATIVE_REPLY_NACK:
 		case DP_AUX_NATIVE_REPLY_NACK:
-			DRM_DEBUG_KMS("native nack\n");
+			DRM_DEBUG_KMS("native nack (result=%d, size=%zu)\n", ret, msg->size);
 			return -EREMOTEIO;
 			return -EREMOTEIO;
 
 
 		case DP_AUX_NATIVE_REPLY_DEFER:
 		case DP_AUX_NATIVE_REPLY_DEFER:
@@ -493,7 +493,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
 			return ret;
 			return ret;
 
 
 		case DP_AUX_I2C_REPLY_NACK:
 		case DP_AUX_I2C_REPLY_NACK:
-			DRM_DEBUG_KMS("I2C nack\n");
+			DRM_DEBUG_KMS("I2C nack (result=%d, size=%zu\n", ret, msg->size);
 			aux->i2c_nack_count++;
 			aux->i2c_nack_count++;
 			return -EREMOTEIO;
 			return -EREMOTEIO;
 
 

+ 3 - 3
drivers/gpu/drm/drm_fb_helper.c

@@ -1283,12 +1283,12 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f
 						      int width, int height)
 						      int width, int height)
 {
 {
 	struct drm_cmdline_mode *cmdline_mode;
 	struct drm_cmdline_mode *cmdline_mode;
-	struct drm_display_mode *mode = NULL;
+	struct drm_display_mode *mode;
 	bool prefer_non_interlace;
 	bool prefer_non_interlace;
 
 
 	cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
 	cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
 	if (cmdline_mode->specified == false)
 	if (cmdline_mode->specified == false)
-		return mode;
+		return NULL;
 
 
 	/* attempt to find a matching mode in the list of modes
 	/* attempt to find a matching mode in the list of modes
 	 *  we have gotten so far, if not add a CVT mode that conforms
 	 *  we have gotten so far, if not add a CVT mode that conforms
@@ -1297,7 +1297,7 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f
 		goto create_mode;
 		goto create_mode;
 
 
 	prefer_non_interlace = !cmdline_mode->interlace;
 	prefer_non_interlace = !cmdline_mode->interlace;
- again:
+again:
 	list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
 	list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
 		/* check width/height */
 		/* check width/height */
 		if (mode->hdisplay != cmdline_mode->xres ||
 		if (mode->hdisplay != cmdline_mode->xres ||

+ 28 - 32
drivers/gpu/drm/drm_ioctl.c

@@ -524,8 +524,13 @@ static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
 	return 0;
 	return 0;
 }
 }
 
 
-#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
-	[DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl}
+#define DRM_IOCTL_DEF(ioctl, _func, _flags)	\
+	[DRM_IOCTL_NR(ioctl)] = {		\
+		.cmd = ioctl,			\
+		.func = _func,			\
+		.flags = _flags,		\
+		.name = #ioctl			\
+	}
 
 
 /** Ioctl table */
 /** Ioctl table */
 static const struct drm_ioctl_desc drm_ioctls[] = {
 static const struct drm_ioctl_desc drm_ioctls[] = {
@@ -663,39 +668,29 @@ long drm_ioctl(struct file *filp,
 	int retcode = -EINVAL;
 	int retcode = -EINVAL;
 	char stack_kdata[128];
 	char stack_kdata[128];
 	char *kdata = NULL;
 	char *kdata = NULL;
-	unsigned int usize, asize;
+	unsigned int usize, asize, drv_size;
 
 
 	dev = file_priv->minor->dev;
 	dev = file_priv->minor->dev;
 
 
 	if (drm_device_is_unplugged(dev))
 	if (drm_device_is_unplugged(dev))
 		return -ENODEV;
 		return -ENODEV;
 
 
-	if ((nr >= DRM_CORE_IOCTL_COUNT) &&
-	    ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
-		goto err_i1;
-	if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
-	    (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
-		u32 drv_size;
+	if (nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END) {
+		/* driver ioctl */
+		if (nr - DRM_COMMAND_BASE >= dev->driver->num_ioctls)
+			goto err_i1;
 		ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
 		ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
-		drv_size = _IOC_SIZE(ioctl->cmd_drv);
-		usize = asize = _IOC_SIZE(cmd);
-		if (drv_size > asize)
-			asize = drv_size;
-		cmd = ioctl->cmd_drv;
-	}
-	else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
-		u32 drv_size;
-
+	} else {
+		/* core ioctl */
+		if (nr >= DRM_CORE_IOCTL_COUNT)
+			goto err_i1;
 		ioctl = &drm_ioctls[nr];
 		ioctl = &drm_ioctls[nr];
+	}
 
 
-		drv_size = _IOC_SIZE(ioctl->cmd);
-		usize = asize = _IOC_SIZE(cmd);
-		if (drv_size > asize)
-			asize = drv_size;
-
-		cmd = ioctl->cmd;
-	} else
-		goto err_i1;
+	drv_size = _IOC_SIZE(ioctl->cmd);
+	usize = _IOC_SIZE(cmd);
+	asize = max(usize, drv_size);
+	cmd = ioctl->cmd;
 
 
 	DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
 	DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
 		  task_pid_nr(current),
 		  task_pid_nr(current),
@@ -776,12 +771,13 @@ EXPORT_SYMBOL(drm_ioctl);
  */
  */
 bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
 bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
 {
 {
-	if ((nr >= DRM_COMMAND_END && nr < DRM_CORE_IOCTL_COUNT) ||
-	    (nr < DRM_COMMAND_BASE)) {
-		*flags = drm_ioctls[nr].flags;
-		return true;
-	}
+	if (nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END)
+		return false;
+
+	if (nr >= DRM_CORE_IOCTL_COUNT)
+		return false;
 
 
-	return false;
+	*flags = drm_ioctls[nr].flags;
+	return true;
 }
 }
 EXPORT_SYMBOL(drm_ioctl_flags);
 EXPORT_SYMBOL(drm_ioctl_flags);

+ 7 - 1
drivers/gpu/drm/drm_modes.c

@@ -903,6 +903,12 @@ EXPORT_SYMBOL(drm_mode_duplicate);
  */
  */
 bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2)
 bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2)
 {
 {
+	if (!mode1 && !mode2)
+		return true;
+
+	if (!mode1 || !mode2)
+		return false;
+
 	/* do clock check convert to PICOS so fb modes get matched
 	/* do clock check convert to PICOS so fb modes get matched
 	 * the same */
 	 * the same */
 	if (mode1->clock && mode2->clock) {
 	if (mode1->clock && mode2->clock) {
@@ -1148,7 +1154,7 @@ EXPORT_SYMBOL(drm_mode_sort);
 /**
 /**
  * drm_mode_connector_list_update - update the mode list for the connector
  * drm_mode_connector_list_update - update the mode list for the connector
  * @connector: the connector to update
  * @connector: the connector to update
- * @merge_type_bits: whether to merge or overright type bits.
+ * @merge_type_bits: whether to merge or overwrite type bits
  *
  *
  * This moves the modes from the @connector probed_modes list
  * This moves the modes from the @connector probed_modes list
  * to the actual mode list. It compares the probed mode against the current
  * to the actual mode list. It compares the probed mode against the current

+ 2 - 2
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c

@@ -134,7 +134,7 @@
  */
  */
 
 
 #define VMW_IOCTL_DEF(ioctl, func, flags) \
 #define VMW_IOCTL_DEF(ioctl, func, flags) \
-  [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = {DRM_##ioctl, flags, func, DRM_IOCTL_##ioctl}
+  [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = {DRM_IOCTL_##ioctl, flags, func}
 
 
 /**
 /**
  * Ioctl definitions.
  * Ioctl definitions.
@@ -1044,7 +1044,7 @@ static long vmw_generic_ioctl(struct file *filp, unsigned int cmd,
 		const struct drm_ioctl_desc *ioctl =
 		const struct drm_ioctl_desc *ioctl =
 			&vmw_ioctls[nr - DRM_COMMAND_BASE];
 			&vmw_ioctls[nr - DRM_COMMAND_BASE];
 
 
-		if (unlikely(ioctl->cmd_drv != cmd)) {
+		if (unlikely(ioctl->cmd != cmd)) {
 			DRM_ERROR("Invalid command format, ioctl %d\n",
 			DRM_ERROR("Invalid command format, ioctl %d\n",
 				  nr - DRM_COMMAND_BASE);
 				  nr - DRM_COMMAND_BASE);
 			return -EINVAL;
 			return -EINVAL;

+ 7 - 3
include/drm/drmP.h

@@ -253,7 +253,6 @@ struct drm_ioctl_desc {
 	unsigned int cmd;
 	unsigned int cmd;
 	int flags;
 	int flags;
 	drm_ioctl_t *func;
 	drm_ioctl_t *func;
-	unsigned int cmd_drv;
 	const char *name;
 	const char *name;
 };
 };
 
 
@@ -262,8 +261,13 @@ struct drm_ioctl_desc {
  * ioctl, for use by drm_ioctl().
  * ioctl, for use by drm_ioctl().
  */
  */
 
 
-#define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags)			\
-	[DRM_IOCTL_NR(DRM_##ioctl)] = {.cmd = DRM_##ioctl, .func = _func, .flags = _flags, .cmd_drv = DRM_IOCTL_##ioctl, .name = #ioctl}
+#define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags)				\
+	[DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = {	\
+		.cmd = DRM_IOCTL_##ioctl,				\
+		.func = _func,						\
+		.flags = _flags,					\
+		.name = #ioctl						\
+	 }
 
 
 /* Event queued up for userspace to read */
 /* Event queued up for userspace to read */
 struct drm_pending_event {
 struct drm_pending_event {