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

Commit 04d78e39 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux

Pull drm fixes from Dave Airlie:
 "Just a bunch of fixes to squeeze in before -rc1:

   - three nouveau regression fixes

   - one qxl regression fix

   - a bunch of i915 fixes

  ... and some core displayport/atomic fixes"

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
  drm/nouveau/device: enable c800 quirk for tecra w50
  drm/nouveau/clk/gt215: Unbreak engine pausing for GT21x/MCP7x
  drm/nouveau/gr/nv04: fix big endian setting on gr context
  drm/qxl: validate monitors config modes
  drm/i915: Allow DSI dual link to be configured on any pipe
  drm/i915: Don't try to use DDR DVFS on CHV when disabled in the BIOS
  drm/i915: Fix CSR MMIO address check
  drm/i915: Limit the number of loops for reading a split 64bit register
  drm/i915: Fix broken mst get_hw_state.
  drm/i915: Pass hpd_status_i915[] to intel_get_hpd_pins() in pre-g4x
  uapi/drm/i915_drm.h: fix userspace compilation.
  drm/i915: Always mark the object as dirty when used by the GPU
  drm/dp: Add dp_aux_i2c_speed_khz module param to set the assume i2c bus speed
  drm/dp: Adjust i2c-over-aux retry count based on message size and i2c bus speed
  drm/dp: Define AUX_RETRY_INTERVAL as 500 us
  drm/atomic: Fix bookkeeping with TEST_ONLY, v3.
parents b0a1ea51 9fbcc7c0
Loading
Loading
Loading
Loading
+23 −16
Original line number Diff line number Diff line
@@ -1515,7 +1515,8 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
			copied_props++;
		}

		if (obj->type == DRM_MODE_OBJECT_PLANE && count_props) {
		if (obj->type == DRM_MODE_OBJECT_PLANE && count_props &&
		    !(arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)) {
			plane = obj_to_plane(obj);
			plane_mask |= (1 << drm_plane_index(plane));
			plane->old_fb = plane->fb;
@@ -1537,10 +1538,11 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
	}

	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
		/*
		 * Unlike commit, check_only does not clean up state.
		 * Below we call drm_atomic_state_free for it.
		 */
		ret = drm_atomic_check_only(state);
		/* _check_only() does not free state, unlike _commit() */
		if (!ret)
			drm_atomic_state_free(state);
	} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
		ret = drm_atomic_async_commit(state);
	} else {
@@ -1567,14 +1569,13 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
		plane->old_fb = NULL;
	}

	if (ret == -EDEADLK) {
		drm_atomic_state_clear(state);
		drm_modeset_backoff(&ctx);
		goto retry;
	}
	if (ret && arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
		/*
		 * TEST_ONLY and PAGE_FLIP_EVENT are mutually exclusive,
		 * if they weren't, this code should be called on success
		 * for TEST_ONLY too.
		 */

	if (ret) {
		if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
		for_each_crtc_in_state(state, crtc, crtc_state, i) {
			if (!crtc_state->event)
				continue;
@@ -1584,9 +1585,15 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
		}
	}

		drm_atomic_state_free(state);
	if (ret == -EDEADLK) {
		drm_atomic_state_clear(state);
		drm_modeset_backoff(&ctx);
		goto retry;
	}

	if (ret || arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
		drm_atomic_state_free(state);

	drm_modeset_drop_locks(&ctx);
	drm_modeset_acquire_fini(&ctx);

+94 −5
Original line number Diff line number Diff line
@@ -159,6 +159,8 @@ int drm_dp_bw_code_to_link_rate(u8 link_bw)
}
EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate);

#define AUX_RETRY_INTERVAL 500 /* us */

/**
 * DOC: dp helpers
 *
@@ -213,7 +215,7 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
			return -EIO;

		case DP_AUX_NATIVE_REPLY_DEFER:
			usleep_range(400, 500);
			usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
			break;
		}
	}
@@ -422,6 +424,90 @@ static u32 drm_dp_i2c_functionality(struct i2c_adapter *adapter)
	       I2C_FUNC_10BIT_ADDR;
}

#define AUX_PRECHARGE_LEN 10 /* 10 to 16 */
#define AUX_SYNC_LEN (16 + 4) /* preamble + AUX_SYNC_END */
#define AUX_STOP_LEN 4
#define AUX_CMD_LEN 4
#define AUX_ADDRESS_LEN 20
#define AUX_REPLY_PAD_LEN 4
#define AUX_LENGTH_LEN 8

/*
 * Calculate the duration of the AUX request/reply in usec. Gives the
 * "best" case estimate, ie. successful while as short as possible.
 */
static int drm_dp_aux_req_duration(const struct drm_dp_aux_msg *msg)
{
	int len = AUX_PRECHARGE_LEN + AUX_SYNC_LEN + AUX_STOP_LEN +
		AUX_CMD_LEN + AUX_ADDRESS_LEN + AUX_LENGTH_LEN;

	if ((msg->request & DP_AUX_I2C_READ) == 0)
		len += msg->size * 8;

	return len;
}

static int drm_dp_aux_reply_duration(const struct drm_dp_aux_msg *msg)
{
	int len = AUX_PRECHARGE_LEN + AUX_SYNC_LEN + AUX_STOP_LEN +
		AUX_CMD_LEN + AUX_REPLY_PAD_LEN;

	/*
	 * For read we expect what was asked. For writes there will
	 * be 0 or 1 data bytes. Assume 0 for the "best" case.
	 */
	if (msg->request & DP_AUX_I2C_READ)
		len += msg->size * 8;

	return len;
}

#define I2C_START_LEN 1
#define I2C_STOP_LEN 1
#define I2C_ADDR_LEN 9 /* ADDRESS + R/W + ACK/NACK */
#define I2C_DATA_LEN 9 /* DATA + ACK/NACK */

/*
 * Calculate the length of the i2c transfer in usec, assuming
 * the i2c bus speed is as specified. Gives the the "worst"
 * case estimate, ie. successful while as long as possible.
 * Doesn't account the the "MOT" bit, and instead assumes each
 * message includes a START, ADDRESS and STOP. Neither does it
 * account for additional random variables such as clock stretching.
 */
static int drm_dp_i2c_msg_duration(const struct drm_dp_aux_msg *msg,
				   int i2c_speed_khz)
{
	/* AUX bitrate is 1MHz, i2c bitrate as specified */
	return DIV_ROUND_UP((I2C_START_LEN + I2C_ADDR_LEN +
			     msg->size * I2C_DATA_LEN +
			     I2C_STOP_LEN) * 1000, i2c_speed_khz);
}

/*
 * Deterine how many retries should be attempted to successfully transfer
 * the specified message, based on the estimated durations of the
 * i2c and AUX transfers.
 */
static int drm_dp_i2c_retry_count(const struct drm_dp_aux_msg *msg,
			      int i2c_speed_khz)
{
	int aux_time_us = drm_dp_aux_req_duration(msg) +
		drm_dp_aux_reply_duration(msg);
	int i2c_time_us = drm_dp_i2c_msg_duration(msg, i2c_speed_khz);

	return DIV_ROUND_UP(i2c_time_us, aux_time_us + AUX_RETRY_INTERVAL);
}

/*
 * FIXME currently assumes 10 kHz as some real world devices seem
 * to require it. We should query/set the speed via DPCD if supported.
 */
static int dp_aux_i2c_speed_khz __read_mostly = 10;
module_param_unsafe(dp_aux_i2c_speed_khz, int, 0644);
MODULE_PARM_DESC(dp_aux_i2c_speed_khz,
		 "Assumed speed of the i2c bus in kHz, (1-400, default 10)");

/*
 * Transfer a single I2C-over-AUX message and handle various error conditions,
 * retrying the transaction as appropriate.  It is assumed that the
@@ -434,13 +520,16 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
{
	unsigned int retry, defer_i2c;
	int ret;

	/*
	 * DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device
	 * is required to retry at least seven times upon receiving AUX_DEFER
	 * before giving up the AUX transaction.
	 *
	 * We also try to account for the i2c bus speed.
	 */
	for (retry = 0, defer_i2c = 0; retry < (7 + defer_i2c); retry++) {
	int max_retries = max(7, drm_dp_i2c_retry_count(msg, dp_aux_i2c_speed_khz));

	for (retry = 0, defer_i2c = 0; retry < (max_retries + defer_i2c); retry++) {
		mutex_lock(&aux->hw_mutex);
		ret = aux->transfer(aux, msg);
		mutex_unlock(&aux->hw_mutex);
@@ -476,7 +565,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
			 * For now just defer for long enough to hopefully be
			 * safe for all use-cases.
			 */
			usleep_range(500, 600);
			usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
			continue;

		default:
@@ -506,7 +595,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
			aux->i2c_defer_count++;
			if (defer_i2c < 7)
				defer_i2c++;
			usleep_range(400, 500);
			usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
			continue;

		default:
+7 −5
Original line number Diff line number Diff line
@@ -1929,6 +1929,8 @@ struct drm_i915_private {
			struct skl_wm_values skl_hw;
			struct vlv_wm_values vlv;
		};

		uint8_t max_level;
	} wm;

	struct i915_runtime_pm pm;
@@ -3384,13 +3386,13 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val);
#define I915_READ64(reg)	dev_priv->uncore.funcs.mmio_readq(dev_priv, (reg), true)

#define I915_READ64_2x32(lower_reg, upper_reg) ({			\
	u32 upper, lower, tmp;						\
	tmp = I915_READ(upper_reg);					\
	u32 upper, lower, old_upper, loop = 0;				\
	upper = I915_READ(upper_reg);					\
	do {								\
		upper = tmp;						\
		old_upper = upper;					\
		lower = I915_READ(lower_reg);				\
		tmp = I915_READ(upper_reg);				\
	} while (upper != tmp);						\
		upper = I915_READ(upper_reg);				\
	} while (upper != old_upper && loop++ < 2);			\
	(u64)upper << 32 | lower; })

#define POSTING_READ(reg)	(void)I915_READ_NOTRACE(reg)
+1 −1
Original line number Diff line number Diff line
@@ -1032,6 +1032,7 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas,
		u32 old_read = obj->base.read_domains;
		u32 old_write = obj->base.write_domain;

		obj->dirty = 1; /* be paranoid  */
		obj->base.write_domain = obj->base.pending_write_domain;
		if (obj->base.write_domain == 0)
			obj->base.pending_read_domains |= obj->base.read_domains;
@@ -1039,7 +1040,6 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas,

		i915_vma_move_to_active(vma, req);
		if (obj->base.write_domain) {
			obj->dirty = 1;
			i915_gem_request_assign(&obj->last_write_req, req);

			intel_fb_obj_invalidate(obj, ORIGIN_CS);
+1 −1
Original line number Diff line number Diff line
@@ -1558,7 +1558,7 @@ static void i9xx_hpd_irq_handler(struct drm_device *dev)
		u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;

		intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger,
				   hotplug_trigger, hpd_status_g4x,
				   hotplug_trigger, hpd_status_i915,
				   i9xx_port_hotplug_long_detect);
		intel_hpd_irq_handler(dev, pin_mask, long_mask);
	}
Loading