Commit 5fa88138 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-misc-fixes-2022-11-17' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes



drm-misc-fixes for v6.1-rc6:
- Fix error handling in vc4_atomic_commit_tail()
- Set bpc for logictechno panels.
- Fix potential memory leak in drm_dev_init()
- Fix potential null-ptr-deref in drm_vblank_destroy_worker()
- Set lima's clkname corrrectly when regulator is missing.
- Small amdgpu fix to gang submission.
- Revert hiding unregistered connectors from userspace, as it breaks on DP-MST.
- Add workaround for DP++ dual mode adaptors that don't support
  i2c subaddressing.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/c7d02936-c550-199b-6cb7-cbf6cf104e4a@linux.intel.com
parents 094226ad 5954acba
Loading
Loading
Loading
Loading
+16 −7
Original line number Original line Diff line number Diff line
@@ -109,6 +109,7 @@ static int amdgpu_cs_p1_ib(struct amdgpu_cs_parser *p,
		return r;
		return r;


	++(num_ibs[r]);
	++(num_ibs[r]);
	p->gang_leader_idx = r;
	return 0;
	return 0;
}
}


@@ -300,7 +301,7 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
		if (ret)
		if (ret)
			goto free_all_kdata;
			goto free_all_kdata;
	}
	}
	p->gang_leader = p->jobs[p->gang_size - 1];
	p->gang_leader = p->jobs[p->gang_leader_idx];


	if (p->ctx->vram_lost_counter != p->gang_leader->vram_lost_counter) {
	if (p->ctx->vram_lost_counter != p->gang_leader->vram_lost_counter) {
		ret = -ECANCELED;
		ret = -ECANCELED;
@@ -1195,16 +1196,18 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
			return r;
			return r;
	}
	}


	for (i = 0; i < p->gang_size - 1; ++i) {
	for (i = 0; i < p->gang_size; ++i) {
		if (p->jobs[i] == leader)
			continue;

		r = amdgpu_sync_clone(&leader->sync, &p->jobs[i]->sync);
		r = amdgpu_sync_clone(&leader->sync, &p->jobs[i]->sync);
		if (r)
		if (r)
			return r;
			return r;
	}
	}


	r = amdgpu_ctx_wait_prev_fence(p->ctx, p->entities[p->gang_size - 1]);
	r = amdgpu_ctx_wait_prev_fence(p->ctx, p->entities[p->gang_leader_idx]);
	if (r && r != -ERESTARTSYS)
	if (r && r != -ERESTARTSYS)
		DRM_ERROR("amdgpu_ctx_wait_prev_fence failed.\n");
		DRM_ERROR("amdgpu_ctx_wait_prev_fence failed.\n");

	return r;
	return r;
}
}


@@ -1238,9 +1241,12 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
	for (i = 0; i < p->gang_size; ++i)
	for (i = 0; i < p->gang_size; ++i)
		drm_sched_job_arm(&p->jobs[i]->base);
		drm_sched_job_arm(&p->jobs[i]->base);


	for (i = 0; i < (p->gang_size - 1); ++i) {
	for (i = 0; i < p->gang_size; ++i) {
		struct dma_fence *fence;
		struct dma_fence *fence;


		if (p->jobs[i] == leader)
			continue;

		fence = &p->jobs[i]->base.s_fence->scheduled;
		fence = &p->jobs[i]->base.s_fence->scheduled;
		r = amdgpu_sync_fence(&leader->sync, fence);
		r = amdgpu_sync_fence(&leader->sync, fence);
		if (r)
		if (r)
@@ -1276,7 +1282,10 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
	list_for_each_entry(e, &p->validated, tv.head) {
	list_for_each_entry(e, &p->validated, tv.head) {


		/* Everybody except for the gang leader uses READ */
		/* Everybody except for the gang leader uses READ */
		for (i = 0; i < (p->gang_size - 1); ++i) {
		for (i = 0; i < p->gang_size; ++i) {
			if (p->jobs[i] == leader)
				continue;

			dma_resv_add_fence(e->tv.bo->base.resv,
			dma_resv_add_fence(e->tv.bo->base.resv,
					   &p->jobs[i]->base.s_fence->finished,
					   &p->jobs[i]->base.s_fence->finished,
					   DMA_RESV_USAGE_READ);
					   DMA_RESV_USAGE_READ);
@@ -1286,7 +1295,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
		e->tv.num_shared = 0;
		e->tv.num_shared = 0;
	}
	}


	seq = amdgpu_ctx_add_fence(p->ctx, p->entities[p->gang_size - 1],
	seq = amdgpu_ctx_add_fence(p->ctx, p->entities[p->gang_leader_idx],
				   p->fence);
				   p->fence);
	amdgpu_cs_post_dependencies(p);
	amdgpu_cs_post_dependencies(p);


+1 −0
Original line number Original line Diff line number Diff line
@@ -54,6 +54,7 @@ struct amdgpu_cs_parser {


	/* scheduler job objects */
	/* scheduler job objects */
	unsigned int		gang_size;
	unsigned int		gang_size;
	unsigned int		gang_leader_idx;
	struct drm_sched_entity	*entities[AMDGPU_CS_GANG_SIZE];
	struct drm_sched_entity	*entities[AMDGPU_CS_GANG_SIZE];
	struct amdgpu_job	*jobs[AMDGPU_CS_GANG_SIZE];
	struct amdgpu_job	*jobs[AMDGPU_CS_GANG_SIZE];
	struct amdgpu_job	*gang_leader;
	struct amdgpu_job	*gang_leader;
+29 −22
Original line number Original line Diff line number Diff line
@@ -63,23 +63,45 @@
ssize_t drm_dp_dual_mode_read(struct i2c_adapter *adapter,
ssize_t drm_dp_dual_mode_read(struct i2c_adapter *adapter,
			      u8 offset, void *buffer, size_t size)
			      u8 offset, void *buffer, size_t size)
{
{
	u8 zero = 0;
	char *tmpbuf = NULL;
	/*
	 * As sub-addressing is not supported by all adaptors,
	 * always explicitly read from the start and discard
	 * any bytes that come before the requested offset.
	 * This way, no matter whether the adaptor supports it
	 * or not, we'll end up reading the proper data.
	 */
	struct i2c_msg msgs[] = {
	struct i2c_msg msgs[] = {
		{
		{
			.addr = DP_DUAL_MODE_SLAVE_ADDRESS,
			.addr = DP_DUAL_MODE_SLAVE_ADDRESS,
			.flags = 0,
			.flags = 0,
			.len = 1,
			.len = 1,
			.buf = &offset,
			.buf = &zero,
		},
		},
		{
		{
			.addr = DP_DUAL_MODE_SLAVE_ADDRESS,
			.addr = DP_DUAL_MODE_SLAVE_ADDRESS,
			.flags = I2C_M_RD,
			.flags = I2C_M_RD,
			.len = size,
			.len = size + offset,
			.buf = buffer,
			.buf = buffer,
		},
		},
	};
	};
	int ret;
	int ret;


	if (offset) {
		tmpbuf = kmalloc(size + offset, GFP_KERNEL);
		if (!tmpbuf)
			return -ENOMEM;

		msgs[1].buf = tmpbuf;
	}

	ret = i2c_transfer(adapter, msgs, ARRAY_SIZE(msgs));
	ret = i2c_transfer(adapter, msgs, ARRAY_SIZE(msgs));
	if (tmpbuf)
		memcpy(buffer, tmpbuf + offset, size);

	kfree(tmpbuf);

	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;
	if (ret != ARRAY_SIZE(msgs))
	if (ret != ARRAY_SIZE(msgs))
@@ -208,18 +230,6 @@ enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(const struct drm_device *dev,
	if (ret)
	if (ret)
		return DRM_DP_DUAL_MODE_UNKNOWN;
		return DRM_DP_DUAL_MODE_UNKNOWN;


	/*
	 * Sigh. Some (maybe all?) type 1 adaptors are broken and ack
	 * the offset but ignore it, and instead they just always return
	 * data from the start of the HDMI ID buffer. So for a broken
	 * type 1 HDMI adaptor a single byte read will always give us
	 * 0x44, and for a type 1 DVI adaptor it should give 0x00
	 * (assuming it implements any registers). Fortunately neither
	 * of those values will match the type 2 signature of the
	 * DP_DUAL_MODE_ADAPTOR_ID register so we can proceed with
	 * the type 2 adaptor detection safely even in the presence
	 * of broken type 1 adaptors.
	 */
	ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_ADAPTOR_ID,
	ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_ADAPTOR_ID,
				    &adaptor_id, sizeof(adaptor_id));
				    &adaptor_id, sizeof(adaptor_id));
	drm_dbg_kms(dev, "DP dual mode adaptor ID: %02x (err %zd)\n", adaptor_id, ret);
	drm_dbg_kms(dev, "DP dual mode adaptor ID: %02x (err %zd)\n", adaptor_id, ret);
@@ -233,11 +243,10 @@ enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(const struct drm_device *dev,
				return DRM_DP_DUAL_MODE_TYPE2_DVI;
				return DRM_DP_DUAL_MODE_TYPE2_DVI;
		}
		}
		/*
		/*
		 * If neither a proper type 1 ID nor a broken type 1 adaptor
		 * If not a proper type 1 ID, still assume type 1, but let
		 * as described above, assume type 1, but let the user know
		 * the user know that we may have misdetected the type.
		 * that we may have misdetected the type.
		 */
		 */
		if (!is_type1_adaptor(adaptor_id) && adaptor_id != hdmi_id[0])
		if (!is_type1_adaptor(adaptor_id))
			drm_err(dev, "Unexpected DP dual mode adaptor ID %02x\n", adaptor_id);
			drm_err(dev, "Unexpected DP dual mode adaptor ID %02x\n", adaptor_id);


	}
	}
@@ -343,10 +352,8 @@ EXPORT_SYMBOL(drm_dp_dual_mode_get_tmds_output);
 * @enable: enable (as opposed to disable) the TMDS output buffers
 * @enable: enable (as opposed to disable) the TMDS output buffers
 *
 *
 * Set the state of the TMDS output buffers in the adaptor. For
 * Set the state of the TMDS output buffers in the adaptor. For
 * type2 this is set via the DP_DUAL_MODE_TMDS_OEN register. As
 * type2 this is set via the DP_DUAL_MODE_TMDS_OEN register.
 * some type 1 adaptors have problems with registers (see comments
 * Type1 adaptors do not support any register writes.
 * in drm_dp_dual_mode_detect()) we avoid touching the register,
 * making this function a no-op on type 1 adaptors.
 *
 *
 * Returns:
 * Returns:
 * 0 on success, negative error code on failure
 * 0 on success, negative error code on failure
+1 −1
Original line number Original line Diff line number Diff line
@@ -615,7 +615,7 @@ static int drm_dev_init(struct drm_device *dev,
	mutex_init(&dev->clientlist_mutex);
	mutex_init(&dev->clientlist_mutex);
	mutex_init(&dev->master_mutex);
	mutex_init(&dev->master_mutex);


	ret = drmm_add_action(dev, drm_dev_init_release, NULL);
	ret = drmm_add_action_or_reset(dev, drm_dev_init_release, NULL);
	if (ret)
	if (ret)
		return ret;
		return ret;


+2 −1
Original line number Original line Diff line number Diff line
@@ -104,6 +104,7 @@ static inline void drm_vblank_flush_worker(struct drm_vblank_crtc *vblank)


static inline void drm_vblank_destroy_worker(struct drm_vblank_crtc *vblank)
static inline void drm_vblank_destroy_worker(struct drm_vblank_crtc *vblank)
{
{
	if (vblank->worker)
		kthread_destroy_worker(vblank->worker);
		kthread_destroy_worker(vblank->worker);
}
}


Loading