Commit 9b984a71 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-misc-fixes-2024-11-08' of...

Merge tag 'drm-misc-fixes-2024-11-08' of https://gitlab.freedesktop.org/drm/misc/kernel

 into drm-fixes

Short summary of fixes pull:

imagination:
- Track PVR context per file
- Break ref-counting cycle

panel-orientation-quirks:
- Fix matching Lenovo Yoga Tab 3 X90F

panthor:
- Lock VM array
- Be strict about I/O mapping flags

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20241108085058.GA37468@linux.fritz.box
parents fd836e82 f432a162
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -403,7 +403,6 @@ static const struct dmi_system_id orientation_data[] = {
	}, {	/* Lenovo Yoga Tab 3 X90F */
		.matches = {
		 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
		 DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
		 DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"),
		},
		.driver_data = (void *)&lcd1600x2560_rightside_up,
+33 −0
Original line number Diff line number Diff line
@@ -17,10 +17,14 @@

#include <drm/drm_auth.h>
#include <drm/drm_managed.h>

#include <linux/bug.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/xarray.h>
@@ -354,6 +358,10 @@ int pvr_context_create(struct pvr_file *pvr_file, struct drm_pvr_ioctl_create_co
		return err;
	}

	spin_lock(&pvr_dev->ctx_list_lock);
	list_add_tail(&ctx->file_link, &pvr_file->contexts);
	spin_unlock(&pvr_dev->ctx_list_lock);

	return 0;

err_destroy_fw_obj:
@@ -380,6 +388,11 @@ pvr_context_release(struct kref *ref_count)
		container_of(ref_count, struct pvr_context, ref_count);
	struct pvr_device *pvr_dev = ctx->pvr_dev;

	WARN_ON(in_interrupt());
	spin_lock(&pvr_dev->ctx_list_lock);
	list_del(&ctx->file_link);
	spin_unlock(&pvr_dev->ctx_list_lock);

	xa_erase(&pvr_dev->ctx_ids, ctx->ctx_id);
	pvr_context_destroy_queues(ctx);
	pvr_fw_object_destroy(ctx->fw_obj);
@@ -437,11 +450,30 @@ pvr_context_destroy(struct pvr_file *pvr_file, u32 handle)
 */
void pvr_destroy_contexts_for_file(struct pvr_file *pvr_file)
{
	struct pvr_device *pvr_dev = pvr_file->pvr_dev;
	struct pvr_context *ctx;
	unsigned long handle;

	xa_for_each(&pvr_file->ctx_handles, handle, ctx)
		pvr_context_destroy(pvr_file, handle);

	spin_lock(&pvr_dev->ctx_list_lock);
	ctx = list_first_entry(&pvr_file->contexts, struct pvr_context, file_link);

	while (!list_entry_is_head(ctx, &pvr_file->contexts, file_link)) {
		list_del_init(&ctx->file_link);

		if (pvr_context_get_if_referenced(ctx)) {
			spin_unlock(&pvr_dev->ctx_list_lock);

			pvr_vm_unmap_all(ctx->vm_ctx);

			pvr_context_put(ctx);
			spin_lock(&pvr_dev->ctx_list_lock);
		}
		ctx = list_first_entry(&pvr_file->contexts, struct pvr_context, file_link);
	}
	spin_unlock(&pvr_dev->ctx_list_lock);
}

/**
@@ -451,6 +483,7 @@ void pvr_destroy_contexts_for_file(struct pvr_file *pvr_file)
void pvr_context_device_init(struct pvr_device *pvr_dev)
{
	xa_init_flags(&pvr_dev->ctx_ids, XA_FLAGS_ALLOC1);
	spin_lock_init(&pvr_dev->ctx_list_lock);
}

/**
+21 −0
Original line number Diff line number Diff line
@@ -85,6 +85,9 @@ struct pvr_context {
		/** @compute: Transfer queue. */
		struct pvr_queue *transfer;
	} queues;

	/** @file_link: pvr_file PVR context list link. */
	struct list_head file_link;
};

static __always_inline struct pvr_queue *
@@ -123,6 +126,24 @@ pvr_context_get(struct pvr_context *ctx)
	return ctx;
}

/**
 * pvr_context_get_if_referenced() - Take an additional reference on a still
 * referenced context.
 * @ctx: Context pointer.
 *
 * Call pvr_context_put() to release.
 *
 * Returns:
 *  * True on success, or
 *  * false if no context pointer passed, or the context wasn't still
 *  * referenced.
 */
static __always_inline bool
pvr_context_get_if_referenced(struct pvr_context *ctx)
{
	return ctx != NULL && kref_get_unless_zero(&ctx->ref_count) != 0;
}

/**
 * pvr_context_lookup() - Lookup context pointer from handle and file.
 * @pvr_file: Pointer to pvr_file structure.
+10 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/math.h>
#include <linux/mutex.h>
#include <linux/spinlock_types.h>
#include <linux/timer.h>
#include <linux/types.h>
#include <linux/wait.h>
@@ -293,6 +294,12 @@ struct pvr_device {

	/** @sched_wq: Workqueue for schedulers. */
	struct workqueue_struct *sched_wq;

	/**
	 * @ctx_list_lock: Lock to be held when accessing the context list in
	 *  struct pvr_file.
	 */
	spinlock_t ctx_list_lock;
};

/**
@@ -344,6 +351,9 @@ struct pvr_file {
	 * This array is used to allocate handles returned to userspace.
	 */
	struct xarray vm_ctx_handles;

	/** @contexts: PVR context list. */
	struct list_head contexts;
};

/**
+3 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <linux/export.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -1326,6 +1327,8 @@ pvr_drm_driver_open(struct drm_device *drm_dev, struct drm_file *file)
	 */
	pvr_file->pvr_dev = pvr_dev;

	INIT_LIST_HEAD(&pvr_file->contexts);

	xa_init_flags(&pvr_file->ctx_handles, XA_FLAGS_ALLOC1);
	xa_init_flags(&pvr_file->free_list_handles, XA_FLAGS_ALLOC1);
	xa_init_flags(&pvr_file->hwrt_handles, XA_FLAGS_ALLOC1);
Loading