Commit 9dd1f5f3 authored by Simona Vetter's avatar Simona Vetter
Browse files

Merge tag 'drm-misc-fixes-2026-01-16' of...

Merge tag 'drm-misc-fixes-2026-01-16' of https://gitlab.freedesktop.org/drm/misc/kernel

 into drm-fixes

drm-misc-fixes for v6.19-rc6:

vmwgfx:
- Fix hw regression from refactoring cursor handling on v10 'hardware'
- Fix warnings in destructor by merging the 2 release functions
- kernel doc fix
- error handling in vmw_compat_shader_add()

rockchip:
- fix vop2 polling
- fix regression waiting for cfgdone without config change
- fix warning when enabling encoder

core:
- take gem lock when preallocating in gpuvm.
- add single byte read fallback to dp for broken usb-c adapters
- remove duplicate drm_sysfb declarations

gud:
- Fix oops on usb disconnect

Simple panel:
- Re-add fallback when connector is not set to fix regressions
- Set correct type in DataImage SCF0700C48GGU18

nouveau:
- locking fixes for cursor handling.

Signed-off-by: default avatarSimona Vetter <simona.vetter@ffwll.ch>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patch.msgid.link/ce0acfe2-9c1a-42b7-8782-f1e7f34b8544@linux.intel.com
parents 52456a62 b91a565e
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -163,6 +163,7 @@ struct dw_hdmi_qp {

	unsigned long ref_clk_rate;
	struct regmap *regm;
	int main_irq;

	unsigned long tmds_char_rate;
};
@@ -1271,6 +1272,7 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev,

	dw_hdmi_qp_init_hw(hdmi);

	hdmi->main_irq = plat_data->main_irq;
	ret = devm_request_threaded_irq(dev, plat_data->main_irq,
					dw_hdmi_qp_main_hardirq, NULL,
					IRQF_SHARED, dev_name(dev), hdmi);
@@ -1331,9 +1333,16 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev,
}
EXPORT_SYMBOL_GPL(dw_hdmi_qp_bind);

void dw_hdmi_qp_suspend(struct device *dev, struct dw_hdmi_qp *hdmi)
{
	disable_irq(hdmi->main_irq);
}
EXPORT_SYMBOL_GPL(dw_hdmi_qp_suspend);

void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi)
{
	dw_hdmi_qp_init_hw(hdmi);
	enable_irq(hdmi->main_irq);
}
EXPORT_SYMBOL_GPL(dw_hdmi_qp_resume);

+48 −21
Original line number Diff line number Diff line
@@ -1602,14 +1602,48 @@ drm_gpuvm_bo_create(struct drm_gpuvm *gpuvm,
}
EXPORT_SYMBOL_GPL(drm_gpuvm_bo_create);

/*
 * drm_gpuvm_bo_destroy_not_in_lists() - final part of drm_gpuvm_bo cleanup
 * @vm_bo: the &drm_gpuvm_bo to destroy
 *
 * It is illegal to call this method if the @vm_bo is present in the GEMs gpuva
 * list, the extobj list, or the evicted list.
 *
 * Note that this puts a refcount on the GEM object, which may destroy the GEM
 * object if the refcount reaches zero. It's illegal for this to happen if the
 * caller holds the GEMs gpuva mutex because it would free the mutex.
 */
static void
drm_gpuvm_bo_destroy_not_in_lists(struct drm_gpuvm_bo *vm_bo)
{
	struct drm_gpuvm *gpuvm = vm_bo->vm;
	const struct drm_gpuvm_ops *ops = gpuvm->ops;
	struct drm_gem_object *obj = vm_bo->obj;

	if (ops && ops->vm_bo_free)
		ops->vm_bo_free(vm_bo);
	else
		kfree(vm_bo);

	drm_gpuvm_put(gpuvm);
	drm_gem_object_put(obj);
}

static void
drm_gpuvm_bo_destroy_not_in_lists_kref(struct kref *kref)
{
	struct drm_gpuvm_bo *vm_bo = container_of(kref, struct drm_gpuvm_bo,
						  kref);

	drm_gpuvm_bo_destroy_not_in_lists(vm_bo);
}

static void
drm_gpuvm_bo_destroy(struct kref *kref)
{
	struct drm_gpuvm_bo *vm_bo = container_of(kref, struct drm_gpuvm_bo,
						  kref);
	struct drm_gpuvm *gpuvm = vm_bo->vm;
	const struct drm_gpuvm_ops *ops = gpuvm->ops;
	struct drm_gem_object *obj = vm_bo->obj;
	bool lock = !drm_gpuvm_resv_protected(gpuvm);

	if (!lock)
@@ -1618,16 +1652,10 @@ drm_gpuvm_bo_destroy(struct kref *kref)
	drm_gpuvm_bo_list_del(vm_bo, extobj, lock);
	drm_gpuvm_bo_list_del(vm_bo, evict, lock);

	drm_gem_gpuva_assert_lock_held(gpuvm, obj);
	drm_gem_gpuva_assert_lock_held(gpuvm, vm_bo->obj);
	list_del(&vm_bo->list.entry.gem);

	if (ops && ops->vm_bo_free)
		ops->vm_bo_free(vm_bo);
	else
		kfree(vm_bo);

	drm_gpuvm_put(gpuvm);
	drm_gem_object_put(obj);
	drm_gpuvm_bo_destroy_not_in_lists(vm_bo);
}

/**
@@ -1745,9 +1773,7 @@ EXPORT_SYMBOL_GPL(drm_gpuvm_bo_put_deferred);
void
drm_gpuvm_bo_deferred_cleanup(struct drm_gpuvm *gpuvm)
{
	const struct drm_gpuvm_ops *ops = gpuvm->ops;
	struct drm_gpuvm_bo *vm_bo;
	struct drm_gem_object *obj;
	struct llist_node *bo_defer;

	bo_defer = llist_del_all(&gpuvm->bo_defer);
@@ -1766,14 +1792,7 @@ drm_gpuvm_bo_deferred_cleanup(struct drm_gpuvm *gpuvm)
	while (bo_defer) {
		vm_bo = llist_entry(bo_defer, struct drm_gpuvm_bo, list.entry.bo_defer);
		bo_defer = bo_defer->next;
		obj = vm_bo->obj;
		if (ops && ops->vm_bo_free)
			ops->vm_bo_free(vm_bo);
		else
			kfree(vm_bo);

		drm_gpuvm_put(gpuvm);
		drm_gem_object_put(obj);
		drm_gpuvm_bo_destroy_not_in_lists(vm_bo);
	}
}
EXPORT_SYMBOL_GPL(drm_gpuvm_bo_deferred_cleanup);
@@ -1861,6 +1880,9 @@ EXPORT_SYMBOL_GPL(drm_gpuvm_bo_obtain);
 * count is decreased. If not found @__vm_bo is returned without further
 * increase of the reference count.
 *
 * The provided @__vm_bo must not already be in the gpuva, evict, or extobj
 * lists prior to calling this method.
 *
 * A new &drm_gpuvm_bo is added to the GEMs gpuva list.
 *
 * Returns: a pointer to the found &drm_gpuvm_bo or @__vm_bo if no existing
@@ -1873,14 +1895,19 @@ drm_gpuvm_bo_obtain_prealloc(struct drm_gpuvm_bo *__vm_bo)
	struct drm_gem_object *obj = __vm_bo->obj;
	struct drm_gpuvm_bo *vm_bo;

	drm_WARN_ON(gpuvm->drm, !drm_gpuvm_immediate_mode(gpuvm));

	mutex_lock(&obj->gpuva.lock);
	vm_bo = drm_gpuvm_bo_find(gpuvm, obj);
	if (vm_bo) {
		drm_gpuvm_bo_put(__vm_bo);
		mutex_unlock(&obj->gpuva.lock);
		kref_put(&__vm_bo->kref, drm_gpuvm_bo_destroy_not_in_lists_kref);
		return vm_bo;
	}

	drm_gem_gpuva_assert_lock_held(gpuvm, obj);
	list_add_tail(&__vm_bo->list.entry.gem, &obj->gpuva.list);
	mutex_unlock(&obj->gpuva.lock);

	return __vm_bo;
}
+8 −12
Original line number Diff line number Diff line
@@ -457,28 +457,21 @@ int gud_plane_atomic_check(struct drm_plane *plane,
	struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
	struct drm_crtc *crtc = new_plane_state->crtc;
	struct drm_crtc_state *crtc_state;
	struct drm_crtc_state *crtc_state = NULL;
	const struct drm_display_mode *mode;
	struct drm_framebuffer *old_fb = old_plane_state->fb;
	struct drm_connector_state *connector_state = NULL;
	struct drm_framebuffer *fb = new_plane_state->fb;
	const struct drm_format_info *format = fb->format;
	const struct drm_format_info *format;
	struct drm_connector *connector;
	unsigned int i, num_properties;
	struct gud_state_req *req;
	int idx, ret;
	size_t len;

	if (drm_WARN_ON_ONCE(plane->dev, !fb))
		return -EINVAL;

	if (drm_WARN_ON_ONCE(plane->dev, !crtc))
		return -EINVAL;

	if (crtc)
		crtc_state = drm_atomic_get_new_crtc_state(state, crtc);

	mode = &crtc_state->mode;

	ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
						  DRM_PLANE_NO_SCALING,
						  DRM_PLANE_NO_SCALING,
@@ -492,6 +485,9 @@ int gud_plane_atomic_check(struct drm_plane *plane,
	if (old_plane_state->rotation != new_plane_state->rotation)
		crtc_state->mode_changed = true;

	mode = &crtc_state->mode;
	format = fb->format;

	if (old_fb && old_fb->format != format)
		crtc_state->mode_changed = true;

@@ -598,7 +594,7 @@ void gud_plane_atomic_update(struct drm_plane *plane,
	struct drm_atomic_helper_damage_iter iter;
	int ret, idx;

	if (crtc->state->mode_changed || !crtc->state->enable) {
	if (!crtc || crtc->state->mode_changed || !crtc->state->enable) {
		cancel_work_sync(&gdrm->work);
		mutex_lock(&gdrm->damage_lock);
		if (gdrm->fb) {
+1 −0
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ curs507a_prepare(struct nv50_wndw *wndw, struct nv50_head_atom *asyh,
		asyh->curs.handle = handle;
		asyh->curs.offset = offset;
		asyh->set.curs = asyh->curs.visible;
		nv50_atom(asyh->state.state)->lock_core = true;
	}
}

+5 −0
Original line number Diff line number Diff line
@@ -43,6 +43,9 @@ nv50_head_flush_clr(struct nv50_head *head,
	union nv50_head_atom_mask clr = {
		.mask = asyh->clr.mask & ~(flush ? 0 : asyh->set.mask),
	};

	lockdep_assert_held(&head->disp->mutex);

	if (clr.crc)  nv50_crc_atomic_clr(head);
	if (clr.olut) head->func->olut_clr(head);
	if (clr.core) head->func->core_clr(head);
@@ -65,6 +68,8 @@ nv50_head_flush_set_wndw(struct nv50_head *head, struct nv50_head_atom *asyh)
void
nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{
	lockdep_assert_held(&head->disp->mutex);

	if (asyh->set.view   ) head->func->view    (head, asyh);
	if (asyh->set.mode   ) head->func->mode    (head, asyh);
	if (asyh->set.core   ) head->func->core_set(head, asyh);
Loading