mirror of
https://github.com/armbian/build.git
synced 2025-08-09 04:36:58 +02:00
clean patches for rockchip-rk3588-legacy (#5189)
This commit is contained in:
parent
e2f32c53f8
commit
97983de408
@ -1,115 +0,0 @@
|
|||||||
From 628b9127e29ac2a00852a59e13d45108c5c4e778 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
|
|
||||||
Date: Wed, 3 Nov 2021 10:02:08 +0100
|
|
||||||
Subject: [PATCH 1/5] dma-buf: add dma_resv_get_singleton v2
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
Add a function to simplify getting a single fence for all the fences in
|
|
||||||
the dma_resv object.
|
|
||||||
|
|
||||||
v2: fix ref leak in error handling
|
|
||||||
|
|
||||||
Signed-off-by: Christian König <christian.koenig@amd.com>
|
|
||||||
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
||||||
Link: https://patchwork.freedesktop.org/patch/msgid/20220321135856.1331-3-christian.koenig@amd.com
|
|
||||||
(cherry picked from commit 92cedee6a6a3e6fcc3ffc0e3866baae5f6f76ac1)
|
|
||||||
---
|
|
||||||
drivers/dma-buf/dma-resv.c | 59 ++++++++++++++++++++++++++++++++++++++
|
|
||||||
include/linux/dma-resv.h | 2 ++
|
|
||||||
2 files changed, 61 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
|
|
||||||
index 1187e5e80ede..4c4ec20b99f7 100644
|
|
||||||
--- a/drivers/dma-buf/dma-resv.c
|
|
||||||
+++ b/drivers/dma-buf/dma-resv.c
|
|
||||||
@@ -33,6 +33,7 @@
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/dma-resv.h>
|
|
||||||
+#include <linux/dma-fence-array.h>
|
|
||||||
#include <linux/export.h>
|
|
||||||
#include <linux/mm.h>
|
|
||||||
#include <linux/sched/mm.h>
|
|
||||||
@@ -517,6 +518,64 @@ int dma_resv_get_fences_rcu(struct dma_resv *obj,
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(dma_resv_get_fences_rcu);
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * dma_resv_get_singleton - Get a single fence for all the fences
|
|
||||||
+ * @obj: the reservation object
|
|
||||||
+ * @write: true if we should return all fences
|
|
||||||
+ * @fence: the resulting fence
|
|
||||||
+ *
|
|
||||||
+ * Get a single fence representing all the fences inside the resv object.
|
|
||||||
+ * Returns either 0 for success or -ENOMEM.
|
|
||||||
+ *
|
|
||||||
+ * Warning: This can't be used like this when adding the fence back to the resv
|
|
||||||
+ * object since that can lead to stack corruption when finalizing the
|
|
||||||
+ * dma_fence_array.
|
|
||||||
+ *
|
|
||||||
+ * Returns 0 on success and negative error values on failure.
|
|
||||||
+ */
|
|
||||||
+int dma_resv_get_singleton(struct dma_resv *obj, bool write,
|
|
||||||
+ struct dma_fence **fence)
|
|
||||||
+{
|
|
||||||
+ struct dma_fence_array *array;
|
|
||||||
+ struct dma_fence **fences;
|
|
||||||
+ unsigned count;
|
|
||||||
+ int r;
|
|
||||||
+
|
|
||||||
+ if (!write) {
|
|
||||||
+ *fence = dma_resv_get_excl_rcu(obj);
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ r = dma_resv_get_fences_rcu(obj, NULL, &count, &fences);
|
|
||||||
+ if (r)
|
|
||||||
+ return r;
|
|
||||||
+
|
|
||||||
+ if (count == 0) {
|
|
||||||
+ *fence = NULL;
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (count == 1) {
|
|
||||||
+ *fence = fences[0];
|
|
||||||
+ kfree(fences);
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ array = dma_fence_array_create(count, fences,
|
|
||||||
+ dma_fence_context_alloc(1),
|
|
||||||
+ 1, false);
|
|
||||||
+ if (!array) {
|
|
||||||
+ while (count--)
|
|
||||||
+ dma_fence_put(fences[count]);
|
|
||||||
+ kfree(fences);
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ *fence = &array->base;
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+EXPORT_SYMBOL_GPL(dma_resv_get_singleton);
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
* dma_resv_wait_timeout_rcu - Wait on reservation's objects
|
|
||||||
* shared and/or exclusive fences.
|
|
||||||
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h
|
|
||||||
index d44a77e8a7e3..171ff5e7ff88 100644
|
|
||||||
--- a/include/linux/dma-resv.h
|
|
||||||
+++ b/include/linux/dma-resv.h
|
|
||||||
@@ -283,6 +283,8 @@ int dma_resv_get_fences_rcu(struct dma_resv *obj,
|
|
||||||
unsigned *pshared_count,
|
|
||||||
struct dma_fence ***pshared);
|
|
||||||
|
|
||||||
+int dma_resv_get_singleton(struct dma_resv *obj, bool write,
|
|
||||||
+ struct dma_fence **fence);
|
|
||||||
int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src);
|
|
||||||
|
|
||||||
long dma_resv_wait_timeout_rcu(struct dma_resv *obj, bool wait_all, bool intr,
|
|
||||||
--
|
|
||||||
2.38.1
|
|
||||||
|
|
@ -1,264 +0,0 @@
|
|||||||
From e2efe6b72f4ceb3511dcd847a172d47d59ce2ed1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jason Ekstrand <jason@jlekstrand.net>
|
|
||||||
Date: Wed, 8 Jun 2022 10:21:41 -0500
|
|
||||||
Subject: [PATCH 2/5] dma-buf: Add an API for exporting sync files (v14)
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
Modern userspace APIs like Vulkan are built on an explicit
|
|
||||||
synchronization model. This doesn't always play nicely with the
|
|
||||||
implicit synchronization used in the kernel and assumed by X11 and
|
|
||||||
Wayland. The client -> compositor half of the synchronization isn't too
|
|
||||||
bad, at least on intel, because we can control whether or not i915
|
|
||||||
synchronizes on the buffer and whether or not it's considered written.
|
|
||||||
|
|
||||||
The harder part is the compositor -> client synchronization when we get
|
|
||||||
the buffer back from the compositor. We're required to be able to
|
|
||||||
provide the client with a VkSemaphore and VkFence representing the point
|
|
||||||
in time where the window system (compositor and/or display) finished
|
|
||||||
using the buffer. With current APIs, it's very hard to do this in such
|
|
||||||
a way that we don't get confused by the Vulkan driver's access of the
|
|
||||||
buffer. In particular, once we tell the kernel that we're rendering to
|
|
||||||
the buffer again, any CPU waits on the buffer or GPU dependencies will
|
|
||||||
wait on some of the client rendering and not just the compositor.
|
|
||||||
|
|
||||||
This new IOCTL solves this problem by allowing us to get a snapshot of
|
|
||||||
the implicit synchronization state of a given dma-buf in the form of a
|
|
||||||
sync file. It's effectively the same as a poll() or I915_GEM_WAIT only,
|
|
||||||
instead of CPU waiting directly, it encapsulates the wait operation, at
|
|
||||||
the current moment in time, in a sync_file so we can check/wait on it
|
|
||||||
later. As long as the Vulkan driver does the sync_file export from the
|
|
||||||
dma-buf before we re-introduce it for rendering, it will only contain
|
|
||||||
fences from the compositor or display. This allows to accurately turn
|
|
||||||
it into a VkFence or VkSemaphore without any over-synchronization.
|
|
||||||
|
|
||||||
By making this an ioctl on the dma-buf itself, it allows this new
|
|
||||||
functionality to be used in an entirely driver-agnostic way without
|
|
||||||
having access to a DRM fd. This makes it ideal for use in driver-generic
|
|
||||||
code in Mesa or in a client such as a compositor where the DRM fd may be
|
|
||||||
hard to reach.
|
|
||||||
|
|
||||||
v2 (Jason Ekstrand):
|
|
||||||
- Use a wrapper dma_fence_array of all fences including the new one
|
|
||||||
when importing an exclusive fence.
|
|
||||||
|
|
||||||
v3 (Jason Ekstrand):
|
|
||||||
- Lock around setting shared fences as well as exclusive
|
|
||||||
- Mark SIGNAL_SYNC_FILE as a read-write ioctl.
|
|
||||||
- Initialize ret to 0 in dma_buf_wait_sync_file
|
|
||||||
|
|
||||||
v4 (Jason Ekstrand):
|
|
||||||
- Use the new dma_resv_get_singleton helper
|
|
||||||
|
|
||||||
v5 (Jason Ekstrand):
|
|
||||||
- Rename the IOCTLs to import/export rather than wait/signal
|
|
||||||
- Drop the WRITE flag and always get/set the exclusive fence
|
|
||||||
|
|
||||||
v6 (Jason Ekstrand):
|
|
||||||
- Drop the sync_file import as it was all-around sketchy and not nearly
|
|
||||||
as useful as import.
|
|
||||||
- Re-introduce READ/WRITE flag support for export
|
|
||||||
- Rework the commit message
|
|
||||||
|
|
||||||
v7 (Jason Ekstrand):
|
|
||||||
- Require at least one sync flag
|
|
||||||
- Fix a refcounting bug: dma_resv_get_excl() doesn't take a reference
|
|
||||||
- Use _rcu helpers since we're accessing the dma_resv read-only
|
|
||||||
|
|
||||||
v8 (Jason Ekstrand):
|
|
||||||
- Return -ENOMEM if the sync_file_create fails
|
|
||||||
- Predicate support on IS_ENABLED(CONFIG_SYNC_FILE)
|
|
||||||
|
|
||||||
v9 (Jason Ekstrand):
|
|
||||||
- Add documentation for the new ioctl
|
|
||||||
|
|
||||||
v10 (Jason Ekstrand):
|
|
||||||
- Go back to dma_buf_sync_file as the ioctl struct name
|
|
||||||
|
|
||||||
v11 (Daniel Vetter):
|
|
||||||
- Go back to dma_buf_export_sync_file as the ioctl struct name
|
|
||||||
- Better kerneldoc describing what the read/write flags do
|
|
||||||
|
|
||||||
v12 (Christian König):
|
|
||||||
- Document why we chose to make it an ioctl on dma-buf
|
|
||||||
|
|
||||||
v13 (Jason Ekstrand):
|
|
||||||
- Rebase on Christian König's fence rework
|
|
||||||
|
|
||||||
v14 (Daniel Vetter & Christian König):
|
|
||||||
- Use dma_rev_usage_rw to get the properly inverted usage to pass to
|
|
||||||
dma_resv_get_singleton()
|
|
||||||
- Clean up the sync_file and fd if copy_to_user() fails
|
|
||||||
|
|
||||||
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
|
|
||||||
Signed-off-by: Jason Ekstrand <jason.ekstrand@intel.com>
|
|
||||||
Signed-off-by: Jason Ekstrand <jason.ekstrand@collabora.com>
|
|
||||||
Acked-by: Simon Ser <contact@emersion.fr>
|
|
||||||
Reviewed-by: Christian König <christian.koenig@amd.com>
|
|
||||||
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
||||||
Cc: Sumit Semwal <sumit.semwal@linaro.org>
|
|
||||||
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
|
|
||||||
Signed-off-by: Simon Ser <contact@emersion.fr>
|
|
||||||
Link: https://patchwork.freedesktop.org/patch/msgid/20220608152142.14495-2-jason@jlekstrand.net
|
|
||||||
(cherry picked from commit 20e10881a043af63f2962a9e6bca64661225b383)
|
|
||||||
---
|
|
||||||
drivers/dma-buf/dma-buf.c | 67 ++++++++++++++++++++++++++++++++++++
|
|
||||||
include/uapi/linux/dma-buf.h | 35 +++++++++++++++++++
|
|
||||||
2 files changed, 102 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
|
|
||||||
index 023f34ed98af..437f3620dce8 100644
|
|
||||||
--- a/drivers/dma-buf/dma-buf.c
|
|
||||||
+++ b/drivers/dma-buf/dma-buf.c
|
|
||||||
@@ -20,6 +20,7 @@
|
|
||||||
#include <linux/debugfs.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/seq_file.h>
|
|
||||||
+#include <linux/sync_file.h>
|
|
||||||
#include <linux/poll.h>
|
|
||||||
#include <linux/dma-resv.h>
|
|
||||||
#include <linux/mm.h>
|
|
||||||
@@ -266,6 +267,9 @@ static loff_t dma_buf_llseek(struct file *file, loff_t offset, int whence)
|
|
||||||
* Note that this only signals the completion of the respective fences, i.e. the
|
|
||||||
* DMA transfers are complete. Cache flushing and any other necessary
|
|
||||||
* preparations before CPU access can begin still need to happen.
|
|
||||||
+ *
|
|
||||||
+ * As an alternative to poll(), the set of fences on DMA buffer can be
|
|
||||||
+ * exported as a &sync_file using &dma_buf_sync_file_export.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void dma_buf_poll_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
|
|
||||||
@@ -463,6 +467,64 @@ static long dma_buf_set_name_user(struct dma_buf *dmabuf, const char __user *buf
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+#if IS_ENABLED(CONFIG_SYNC_FILE)
|
|
||||||
+static long dma_buf_export_sync_file(struct dma_buf *dmabuf,
|
|
||||||
+ void __user *user_data)
|
|
||||||
+{
|
|
||||||
+ struct dma_buf_export_sync_file arg;
|
|
||||||
+ struct dma_fence *fence = NULL;
|
|
||||||
+ struct sync_file *sync_file;
|
|
||||||
+ bool write;
|
|
||||||
+ int fd, ret;
|
|
||||||
+
|
|
||||||
+ if (copy_from_user(&arg, user_data, sizeof(arg)))
|
|
||||||
+ return -EFAULT;
|
|
||||||
+
|
|
||||||
+ if (arg.flags & ~DMA_BUF_SYNC_RW)
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ if ((arg.flags & DMA_BUF_SYNC_RW) == 0)
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ fd = get_unused_fd_flags(O_CLOEXEC);
|
|
||||||
+ if (fd < 0)
|
|
||||||
+ return fd;
|
|
||||||
+
|
|
||||||
+ write = (arg.flags & DMA_BUF_SYNC_WRITE);
|
|
||||||
+ ret = dma_resv_get_singleton(dmabuf->resv, write, &fence);
|
|
||||||
+ if (ret)
|
|
||||||
+ goto err_put_fd;
|
|
||||||
+
|
|
||||||
+ if (!fence)
|
|
||||||
+ fence = dma_fence_get_stub();
|
|
||||||
+
|
|
||||||
+ sync_file = sync_file_create(fence);
|
|
||||||
+
|
|
||||||
+ dma_fence_put(fence);
|
|
||||||
+
|
|
||||||
+ if (!sync_file) {
|
|
||||||
+ ret = -ENOMEM;
|
|
||||||
+ goto err_put_fd;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ arg.fd = fd;
|
|
||||||
+ if (copy_to_user(user_data, &arg, sizeof(arg))) {
|
|
||||||
+ ret = -EFAULT;
|
|
||||||
+ goto err_put_file;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ fd_install(fd, sync_file->file);
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+err_put_file:
|
|
||||||
+ fput(sync_file->file);
|
|
||||||
+err_put_fd:
|
|
||||||
+ put_unused_fd(fd);
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
static long dma_buf_ioctl(struct file *file,
|
|
||||||
unsigned int cmd, unsigned long arg)
|
|
||||||
{
|
|
||||||
@@ -545,6 +607,11 @@ static long dma_buf_ioctl(struct file *file,
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
+#if IS_ENABLED(CONFIG_SYNC_FILE)
|
|
||||||
+ case DMA_BUF_IOCTL_EXPORT_SYNC_FILE:
|
|
||||||
+ return dma_buf_export_sync_file(dmabuf, (void __user *)arg);
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
default:
|
|
||||||
return -ENOTTY;
|
|
||||||
}
|
|
||||||
diff --git a/include/uapi/linux/dma-buf.h b/include/uapi/linux/dma-buf.h
|
|
||||||
index 6236c644624d..522bcee5498e 100644
|
|
||||||
--- a/include/uapi/linux/dma-buf.h
|
|
||||||
+++ b/include/uapi/linux/dma-buf.h
|
|
||||||
@@ -37,6 +37,40 @@ struct dma_buf_sync {
|
|
||||||
|
|
||||||
#define DMA_BUF_NAME_LEN 32
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * struct dma_buf_export_sync_file - Get a sync_file from a dma-buf
|
|
||||||
+ *
|
|
||||||
+ * Userspace can perform a DMA_BUF_IOCTL_EXPORT_SYNC_FILE to retrieve the
|
|
||||||
+ * current set of fences on a dma-buf file descriptor as a sync_file. CPU
|
|
||||||
+ * waits via poll() or other driver-specific mechanisms typically wait on
|
|
||||||
+ * whatever fences are on the dma-buf at the time the wait begins. This
|
|
||||||
+ * is similar except that it takes a snapshot of the current fences on the
|
|
||||||
+ * dma-buf for waiting later instead of waiting immediately. This is
|
|
||||||
+ * useful for modern graphics APIs such as Vulkan which assume an explicit
|
|
||||||
+ * synchronization model but still need to inter-operate with dma-buf.
|
|
||||||
+ */
|
|
||||||
+struct dma_buf_export_sync_file {
|
|
||||||
+ /**
|
|
||||||
+ * @flags: Read/write flags
|
|
||||||
+ *
|
|
||||||
+ * Must be DMA_BUF_SYNC_READ, DMA_BUF_SYNC_WRITE, or both.
|
|
||||||
+ *
|
|
||||||
+ * If DMA_BUF_SYNC_READ is set and DMA_BUF_SYNC_WRITE is not set,
|
|
||||||
+ * the returned sync file waits on any writers of the dma-buf to
|
|
||||||
+ * complete. Waiting on the returned sync file is equivalent to
|
|
||||||
+ * poll() with POLLIN.
|
|
||||||
+ *
|
|
||||||
+ * If DMA_BUF_SYNC_WRITE is set, the returned sync file waits on
|
|
||||||
+ * any users of the dma-buf (read or write) to complete. Waiting
|
|
||||||
+ * on the returned sync file is equivalent to poll() with POLLOUT.
|
|
||||||
+ * If both DMA_BUF_SYNC_WRITE and DMA_BUF_SYNC_READ are set, this
|
|
||||||
+ * is equivalent to just DMA_BUF_SYNC_WRITE.
|
|
||||||
+ */
|
|
||||||
+ __u32 flags;
|
|
||||||
+ /** @fd: Returned sync file descriptor */
|
|
||||||
+ __s32 fd;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
#define DMA_BUF_BASE 'b'
|
|
||||||
#define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync)
|
|
||||||
|
|
||||||
@@ -46,6 +80,7 @@ struct dma_buf_sync {
|
|
||||||
#define DMA_BUF_SET_NAME _IOW(DMA_BUF_BASE, 1, const char *)
|
|
||||||
#define DMA_BUF_SET_NAME_A _IOW(DMA_BUF_BASE, 1, u32)
|
|
||||||
#define DMA_BUF_SET_NAME_B _IOW(DMA_BUF_BASE, 1, u64)
|
|
||||||
+#define DMA_BUF_IOCTL_EXPORT_SYNC_FILE _IOWR(DMA_BUF_BASE, 2, struct dma_buf_export_sync_file)
|
|
||||||
|
|
||||||
struct dma_buf_sync_partial {
|
|
||||||
__u64 flags;
|
|
||||||
--
|
|
||||||
2.38.1
|
|
||||||
|
|
@ -1,248 +0,0 @@
|
|||||||
From 520309591712f72a36f87d086f005e9f2c21f388 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jason Ekstrand <jason@jlekstrand.net>
|
|
||||||
Date: Wed, 8 Jun 2022 10:21:42 -0500
|
|
||||||
Subject: [PATCH 3/5] dma-buf: Add an API for importing sync files (v10)
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
This patch is analogous to the previous sync file export patch in that
|
|
||||||
it allows you to import a sync_file into a dma-buf. Unlike the previous
|
|
||||||
patch, however, this does add genuinely new functionality to dma-buf.
|
|
||||||
Without this, the only way to attach a sync_file to a dma-buf is to
|
|
||||||
submit a batch to your driver of choice which waits on the sync_file and
|
|
||||||
claims to write to the dma-buf. Even if said batch is a no-op, a submit
|
|
||||||
is typically way more overhead than just attaching a fence. A submit
|
|
||||||
may also imply extra synchronization with other work because it happens
|
|
||||||
on a hardware queue.
|
|
||||||
|
|
||||||
In the Vulkan world, this is useful for dealing with the out-fence from
|
|
||||||
vkQueuePresent. Current Linux window-systems (X11, Wayland, etc.) all
|
|
||||||
rely on dma-buf implicit sync. Since Vulkan is an explicit sync API, we
|
|
||||||
get a set of fences (VkSemaphores) in vkQueuePresent and have to stash
|
|
||||||
those as an exclusive (write) fence on the dma-buf. We handle it in
|
|
||||||
Mesa today with the above mentioned dummy submit trick. This ioctl
|
|
||||||
would allow us to set it directly without the dummy submit.
|
|
||||||
|
|
||||||
This may also open up possibilities for GPU drivers to move away from
|
|
||||||
implicit sync for their kernel driver uAPI and instead provide sync
|
|
||||||
files and rely on dma-buf import/export for communicating with other
|
|
||||||
implicit sync clients.
|
|
||||||
|
|
||||||
We make the explicit choice here to only allow setting RW fences which
|
|
||||||
translates to an exclusive fence on the dma_resv. There's no use for
|
|
||||||
read-only fences for communicating with other implicit sync userspace
|
|
||||||
and any such attempts are likely to be racy at best. When we got to
|
|
||||||
insert the RW fence, the actual fence we set as the new exclusive fence
|
|
||||||
is a combination of the sync_file provided by the user and all the other
|
|
||||||
fences on the dma_resv. This ensures that the newly added exclusive
|
|
||||||
fence will never signal before the old one would have and ensures that
|
|
||||||
we don't break any dma_resv contracts. We require userspace to specify
|
|
||||||
RW in the flags for symmetry with the export ioctl and in case we ever
|
|
||||||
want to support read fences in the future.
|
|
||||||
|
|
||||||
There is one downside here that's worth documenting: If two clients
|
|
||||||
writing to the same dma-buf using this API race with each other, their
|
|
||||||
actions on the dma-buf may happen in parallel or in an undefined order.
|
|
||||||
Both with and without this API, the pattern is the same: Collect all
|
|
||||||
the fences on dma-buf, submit work which depends on said fences, and
|
|
||||||
then set a new exclusive (write) fence on the dma-buf which depends on
|
|
||||||
said work. The difference is that, when it's all handled by the GPU
|
|
||||||
driver's submit ioctl, the three operations happen atomically under the
|
|
||||||
dma_resv lock. If two userspace submits race, one will happen before
|
|
||||||
the other. You aren't guaranteed which but you are guaranteed that
|
|
||||||
they're strictly ordered. If userspace manages the fences itself, then
|
|
||||||
these three operations happen separately and the two render operations
|
|
||||||
may happen genuinely in parallel or get interleaved. However, this is a
|
|
||||||
case of userspace racing with itself. As long as we ensure userspace
|
|
||||||
can't back the kernel into a corner, it should be fine.
|
|
||||||
|
|
||||||
v2 (Jason Ekstrand):
|
|
||||||
- Use a wrapper dma_fence_array of all fences including the new one
|
|
||||||
when importing an exclusive fence.
|
|
||||||
|
|
||||||
v3 (Jason Ekstrand):
|
|
||||||
- Lock around setting shared fences as well as exclusive
|
|
||||||
- Mark SIGNAL_SYNC_FILE as a read-write ioctl.
|
|
||||||
- Initialize ret to 0 in dma_buf_wait_sync_file
|
|
||||||
|
|
||||||
v4 (Jason Ekstrand):
|
|
||||||
- Use the new dma_resv_get_singleton helper
|
|
||||||
|
|
||||||
v5 (Jason Ekstrand):
|
|
||||||
- Rename the IOCTLs to import/export rather than wait/signal
|
|
||||||
- Drop the WRITE flag and always get/set the exclusive fence
|
|
||||||
|
|
||||||
v6 (Jason Ekstrand):
|
|
||||||
- Split import and export into separate patches
|
|
||||||
- New commit message
|
|
||||||
|
|
||||||
v7 (Daniel Vetter):
|
|
||||||
- Fix the uapi header to use the right struct in the ioctl
|
|
||||||
- Use a separate dma_buf_import_sync_file struct
|
|
||||||
- Add kerneldoc for dma_buf_import_sync_file
|
|
||||||
|
|
||||||
v8 (Jason Ekstrand):
|
|
||||||
- Rebase on Christian König's fence rework
|
|
||||||
|
|
||||||
v9 (Daniel Vetter):
|
|
||||||
- Fix -EINVAL checks for the flags parameter
|
|
||||||
- Add documentation about read/write fences
|
|
||||||
- Add documentation about the expected usage of import/export and
|
|
||||||
specifically call out the possible userspace race.
|
|
||||||
|
|
||||||
v10 (Simon Ser):
|
|
||||||
- Fix a typo in the docs
|
|
||||||
|
|
||||||
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
|
|
||||||
Signed-off-by: Jason Ekstrand <jason.ekstrand@intel.com>
|
|
||||||
Signed-off-by: Jason Ekstrand <jason.ekstrand@collabora.com>
|
|
||||||
Reviewed-by: Christian König <christian.koenig@amd.com>
|
|
||||||
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
||||||
Cc: Sumit Semwal <sumit.semwal@linaro.org>
|
|
||||||
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
|
|
||||||
Signed-off-by: Simon Ser <contact@emersion.fr>
|
|
||||||
Link: https://patchwork.freedesktop.org/patch/msgid/20220608152142.14495-3-jason@jlekstrand.net
|
|
||||||
(cherry picked from commit 594740497e998d30477ab26093bfb81c28cd3ff1)
|
|
||||||
---
|
|
||||||
drivers/dma-buf/dma-buf.c | 42 +++++++++++++++++++++++++++++++
|
|
||||||
include/uapi/linux/dma-buf.h | 49 ++++++++++++++++++++++++++++++++++++
|
|
||||||
2 files changed, 91 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
|
|
||||||
index 437f3620dce8..41ebb645efda 100644
|
|
||||||
--- a/drivers/dma-buf/dma-buf.c
|
|
||||||
+++ b/drivers/dma-buf/dma-buf.c
|
|
||||||
@@ -523,6 +523,46 @@ static long dma_buf_export_sync_file(struct dma_buf *dmabuf,
|
|
||||||
put_unused_fd(fd);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+static long dma_buf_import_sync_file(struct dma_buf *dmabuf,
|
|
||||||
+ const void __user *user_data)
|
|
||||||
+{
|
|
||||||
+ struct dma_buf_import_sync_file arg;
|
|
||||||
+ struct dma_fence *fence;
|
|
||||||
+ bool write;
|
|
||||||
+ int ret = 0;
|
|
||||||
+
|
|
||||||
+ if (copy_from_user(&arg, user_data, sizeof(arg)))
|
|
||||||
+ return -EFAULT;
|
|
||||||
+
|
|
||||||
+ if (arg.flags & ~DMA_BUF_SYNC_RW)
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ if ((arg.flags & DMA_BUF_SYNC_RW) == 0)
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ fence = sync_file_get_fence(arg.fd);
|
|
||||||
+ if (!fence)
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ write = (arg.flags & DMA_BUF_SYNC_WRITE);
|
|
||||||
+
|
|
||||||
+ dma_resv_lock(dmabuf->resv, NULL);
|
|
||||||
+
|
|
||||||
+ if (write) {
|
|
||||||
+ dma_resv_add_excl_fence(dmabuf->resv, fence);
|
|
||||||
+ } else {
|
|
||||||
+ ret = dma_resv_reserve_shared(dmabuf->resv, 1);
|
|
||||||
+ if (!ret)
|
|
||||||
+ dma_resv_add_shared_fence(dmabuf->resv, fence);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ dma_resv_unlock(dmabuf->resv);
|
|
||||||
+
|
|
||||||
+ dma_fence_put(fence);
|
|
||||||
+
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static long dma_buf_ioctl(struct file *file,
|
|
||||||
@@ -610,6 +650,8 @@ static long dma_buf_ioctl(struct file *file,
|
|
||||||
#if IS_ENABLED(CONFIG_SYNC_FILE)
|
|
||||||
case DMA_BUF_IOCTL_EXPORT_SYNC_FILE:
|
|
||||||
return dma_buf_export_sync_file(dmabuf, (void __user *)arg);
|
|
||||||
+ case DMA_BUF_IOCTL_IMPORT_SYNC_FILE:
|
|
||||||
+ return dma_buf_import_sync_file(dmabuf, (const void __user *)arg);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
default:
|
|
||||||
diff --git a/include/uapi/linux/dma-buf.h b/include/uapi/linux/dma-buf.h
|
|
||||||
index 522bcee5498e..b4ceeaedfa87 100644
|
|
||||||
--- a/include/uapi/linux/dma-buf.h
|
|
||||||
+++ b/include/uapi/linux/dma-buf.h
|
|
||||||
@@ -48,6 +48,24 @@ struct dma_buf_sync {
|
|
||||||
* dma-buf for waiting later instead of waiting immediately. This is
|
|
||||||
* useful for modern graphics APIs such as Vulkan which assume an explicit
|
|
||||||
* synchronization model but still need to inter-operate with dma-buf.
|
|
||||||
+ *
|
|
||||||
+ * The intended usage pattern is the following:
|
|
||||||
+ *
|
|
||||||
+ * 1. Export a sync_file with flags corresponding to the expected GPU usage
|
|
||||||
+ * via DMA_BUF_IOCTL_EXPORT_SYNC_FILE.
|
|
||||||
+ *
|
|
||||||
+ * 2. Submit rendering work which uses the dma-buf. The work should wait on
|
|
||||||
+ * the exported sync file before rendering and produce another sync_file
|
|
||||||
+ * when complete.
|
|
||||||
+ *
|
|
||||||
+ * 3. Import the rendering-complete sync_file into the dma-buf with flags
|
|
||||||
+ * corresponding to the GPU usage via DMA_BUF_IOCTL_IMPORT_SYNC_FILE.
|
|
||||||
+ *
|
|
||||||
+ * Unlike doing implicit synchronization via a GPU kernel driver's exec ioctl,
|
|
||||||
+ * the above is not a single atomic operation. If userspace wants to ensure
|
|
||||||
+ * ordering via these fences, it is the respnosibility of userspace to use
|
|
||||||
+ * locks or other mechanisms to ensure that no other context adds fences or
|
|
||||||
+ * submits work between steps 1 and 3 above.
|
|
||||||
*/
|
|
||||||
struct dma_buf_export_sync_file {
|
|
||||||
/**
|
|
||||||
@@ -71,6 +89,36 @@ struct dma_buf_export_sync_file {
|
|
||||||
__s32 fd;
|
|
||||||
};
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * struct dma_buf_import_sync_file - Insert a sync_file into a dma-buf
|
|
||||||
+ *
|
|
||||||
+ * Userspace can perform a DMA_BUF_IOCTL_IMPORT_SYNC_FILE to insert a
|
|
||||||
+ * sync_file into a dma-buf for the purposes of implicit synchronization
|
|
||||||
+ * with other dma-buf consumers. This allows clients using explicitly
|
|
||||||
+ * synchronized APIs such as Vulkan to inter-op with dma-buf consumers
|
|
||||||
+ * which expect implicit synchronization such as OpenGL or most media
|
|
||||||
+ * drivers/video.
|
|
||||||
+ */
|
|
||||||
+struct dma_buf_import_sync_file {
|
|
||||||
+ /**
|
|
||||||
+ * @flags: Read/write flags
|
|
||||||
+ *
|
|
||||||
+ * Must be DMA_BUF_SYNC_READ, DMA_BUF_SYNC_WRITE, or both.
|
|
||||||
+ *
|
|
||||||
+ * If DMA_BUF_SYNC_READ is set and DMA_BUF_SYNC_WRITE is not set,
|
|
||||||
+ * this inserts the sync_file as a read-only fence. Any subsequent
|
|
||||||
+ * implicitly synchronized writes to this dma-buf will wait on this
|
|
||||||
+ * fence but reads will not.
|
|
||||||
+ *
|
|
||||||
+ * If DMA_BUF_SYNC_WRITE is set, this inserts the sync_file as a
|
|
||||||
+ * write fence. All subsequent implicitly synchronized access to
|
|
||||||
+ * this dma-buf will wait on this fence.
|
|
||||||
+ */
|
|
||||||
+ __u32 flags;
|
|
||||||
+ /** @fd: Sync file descriptor */
|
|
||||||
+ __s32 fd;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
#define DMA_BUF_BASE 'b'
|
|
||||||
#define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync)
|
|
||||||
|
|
||||||
@@ -81,6 +129,7 @@ struct dma_buf_export_sync_file {
|
|
||||||
#define DMA_BUF_SET_NAME_A _IOW(DMA_BUF_BASE, 1, u32)
|
|
||||||
#define DMA_BUF_SET_NAME_B _IOW(DMA_BUF_BASE, 1, u64)
|
|
||||||
#define DMA_BUF_IOCTL_EXPORT_SYNC_FILE _IOWR(DMA_BUF_BASE, 2, struct dma_buf_export_sync_file)
|
|
||||||
+#define DMA_BUF_IOCTL_IMPORT_SYNC_FILE _IOW(DMA_BUF_BASE, 3, struct dma_buf_import_sync_file)
|
|
||||||
|
|
||||||
struct dma_buf_sync_partial {
|
|
||||||
__u64 flags;
|
|
||||||
--
|
|
||||||
2.38.1
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
|||||||
From d1ce2f15fac0e7c3ee27d312016c5fce0608bcae Mon Sep 17 00:00:00 2001
|
|
||||||
From: Icecream95 <ixn@disroot.org>
|
|
||||||
Date: Tue, 6 Dec 2022 15:17:33 +1300
|
|
||||||
Subject: [PATCH 8/9] MALI: bifrost: Avoid fence double-free
|
|
||||||
|
|
||||||
Probably this corresponds to CVE-2022-42716.
|
|
||||||
|
|
||||||
---
|
|
||||||
drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.c | 1 -
|
|
||||||
1 file changed, 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.c
|
|
||||||
index 6c43c029a324..715ccd62e375 100644
|
|
||||||
--- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.c
|
|
||||||
+++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.c
|
|
||||||
@@ -1550,7 +1550,6 @@ static int kbase_kcpu_fence_signal_prepare(
|
|
||||||
dma_fence_put(fence_out);
|
|
||||||
|
|
||||||
current_command->info.fence.fence = NULL;
|
|
||||||
- kfree(fence_out);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.38.1
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
|||||||
From 1a0e71a04479dbd6ef08f46b4911ddc64b47347d Mon Sep 17 00:00:00 2001
|
|
||||||
From: Icecream95 <ixn@disroot.org>
|
|
||||||
Date: Tue, 6 Dec 2022 16:52:06 +1300
|
|
||||||
Subject: [PATCH 5/5] drm/rockchip: Re-add implicit fencing support for planes
|
|
||||||
|
|
||||||
Similar to 63d5e06aa381 ("drm/rockchip: Add implicit fencing support
|
|
||||||
for planes") but after the code was removed and VOP2 was added in the
|
|
||||||
downstream kernel.
|
|
||||||
|
|
||||||
Note that upstream VOP2 does not have this line as it was added since
|
|
||||||
29a840842743 ("drm/<driver>: drm_gem_plane_helper_prepare_fb is now
|
|
||||||
the default") removed the need.
|
|
||||||
|
|
||||||
---
|
|
||||||
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 2 ++
|
|
||||||
1 file changed, 2 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
|
|
||||||
index df4a3291d3da..f9675d9320d4 100644
|
|
||||||
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
|
|
||||||
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
|
|
||||||
@@ -10,6 +10,7 @@
|
|
||||||
#include <drm/drm_crtc_helper.h>
|
|
||||||
#include <drm/drm_debugfs.h>
|
|
||||||
#include <drm/drm_flip_work.h>
|
|
||||||
+#include <drm/drm_gem_framebuffer_helper.h>
|
|
||||||
#include <drm/drm_fourcc.h>
|
|
||||||
#include <drm/drm_plane_helper.h>
|
|
||||||
#include <drm/drm_probe_helper.h>
|
|
||||||
@@ -4622,6 +4623,7 @@ static const struct drm_plane_helper_funcs vop2_plane_helper_funcs = {
|
|
||||||
.atomic_check = vop2_plane_atomic_check,
|
|
||||||
.atomic_update = vop2_plane_atomic_update,
|
|
||||||
.atomic_disable = vop2_plane_atomic_disable,
|
|
||||||
+ .prepare_fb = drm_gem_fb_prepare_fb,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
--
|
|
||||||
2.38.1
|
|
||||||
|
|
@ -1,418 +0,0 @@
|
|||||||
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
|
|
||||||
index 9c8c7511d..79aef50ed 100644
|
|
||||||
--- a/scripts/mod/modpost.c
|
|
||||||
+++ b/scripts/mod/modpost.c
|
|
||||||
@@ -17,6 +17,7 @@
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <limits.h>
|
|
||||||
+#include <stdbool.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include "modpost.h"
|
|
||||||
#include "../../include/linux/license.h"
|
|
||||||
@@ -29,20 +30,16 @@ static int have_vmlinux = 0;
|
|
||||||
static int all_versions = 0;
|
|
||||||
/* If we are modposting external module set to 1 */
|
|
||||||
static int external_module = 0;
|
|
||||||
-#define MODULE_SCMVERSION_SIZE 64
|
|
||||||
-static char module_scmversion[MODULE_SCMVERSION_SIZE];
|
|
||||||
/* Only warn about unresolved symbols */
|
|
||||||
static int warn_unresolved = 0;
|
|
||||||
/* How a symbol is exported */
|
|
||||||
static int sec_mismatch_count = 0;
|
|
||||||
-static int sec_mismatch_warn_only = true;
|
|
||||||
+static int sec_mismatch_fatal = 0;
|
|
||||||
/* ignore missing files */
|
|
||||||
static int ignore_missing_files;
|
|
||||||
/* If set to 1, only warn (instead of error) about missing ns imports */
|
|
||||||
static int allow_missing_ns_imports;
|
|
||||||
|
|
||||||
-static bool error_occurred;
|
|
||||||
-
|
|
||||||
enum export {
|
|
||||||
export_plain, export_unused, export_gpl,
|
|
||||||
export_unused_gpl, export_gpl_future, export_unknown
|
|
||||||
@@ -81,8 +78,14 @@ modpost_log(enum loglevel loglevel, const char *fmt, ...)
|
|
||||||
|
|
||||||
if (loglevel == LOG_FATAL)
|
|
||||||
exit(1);
|
|
||||||
- if (loglevel == LOG_ERROR)
|
|
||||||
- error_occurred = true;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline bool strends(const char *str, const char *postfix)
|
|
||||||
+{
|
|
||||||
+ if (strlen(str) < strlen(postfix))
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *do_nofail(void *ptr, const char *expr)
|
|
||||||
@@ -400,8 +403,8 @@ static void sym_update_namespace(const char *symname, const char *namespace)
|
|
||||||
* actually an assertion.
|
|
||||||
*/
|
|
||||||
if (!s) {
|
|
||||||
- error("Could not update namespace(%s) for symbol %s\n",
|
|
||||||
- namespace, symname);
|
|
||||||
+ merror("Could not update namespace(%s) for symbol %s\n",
|
|
||||||
+ namespace, symname);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -423,9 +426,10 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod,
|
|
||||||
s = new_symbol(name, mod, export);
|
|
||||||
} else if (!external_module || s->module->is_vmlinux ||
|
|
||||||
s->module == mod) {
|
|
||||||
- fatal("%s: '%s' exported twice. Previous export was in %s%s\n",
|
|
||||||
- mod->name, name, s->module->name,
|
|
||||||
- s->module->is_vmlinux ? "" : ".ko");
|
|
||||||
+ warn("%s: '%s' exported twice. Previous export was in %s%s\n",
|
|
||||||
+ mod->name, name, s->module->name,
|
|
||||||
+ s->module->is_vmlinux ? "" : ".ko");
|
|
||||||
+ return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
s->module = mod;
|
|
||||||
@@ -1267,7 +1271,8 @@ static int secref_whitelist(const struct sectioncheck *mismatch,
|
|
||||||
|
|
||||||
static inline int is_arm_mapping_symbol(const char *str)
|
|
||||||
{
|
|
||||||
- return str[0] == '$' && strchr("axtd", str[1])
|
|
||||||
+ return str[0] == '$' &&
|
|
||||||
+ (str[1] == 'a' || str[1] == 'd' || str[1] == 't' || str[1] == 'x')
|
|
||||||
&& (str[2] == '\0' || str[2] == '.');
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1978,12 +1983,8 @@ static char *remove_dot(char *s)
|
|
||||||
|
|
||||||
if (n && s[n]) {
|
|
||||||
size_t m = strspn(s + n + 1, "0123456789");
|
|
||||||
- if (m && (s[n + m] == '.' || s[n + m] == 0))
|
|
||||||
+ if (m && (s[n + m + 1] == '.' || s[n + m + 1] == 0))
|
|
||||||
s[n] = 0;
|
|
||||||
-
|
|
||||||
- /* strip trailing .lto */
|
|
||||||
- if (strends(s, ".lto"))
|
|
||||||
- s[strlen(s) - 4] = '\0';
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
@@ -2007,9 +2008,6 @@ static void read_symbols(const char *modname)
|
|
||||||
/* strip trailing .o */
|
|
||||||
tmp = NOFAIL(strdup(modname));
|
|
||||||
tmp[strlen(tmp) - 2] = '\0';
|
|
||||||
- /* strip trailing .lto */
|
|
||||||
- if (strends(tmp, ".lto"))
|
|
||||||
- tmp[strlen(tmp) - 4] = '\0';
|
|
||||||
mod = new_module(tmp);
|
|
||||||
free(tmp);
|
|
||||||
}
|
|
||||||
@@ -2017,7 +2015,7 @@ static void read_symbols(const char *modname)
|
|
||||||
if (!mod->is_vmlinux) {
|
|
||||||
license = get_modinfo(&info, "license");
|
|
||||||
if (!license)
|
|
||||||
- error("missing MODULE_LICENSE() in %s\n", modname);
|
|
||||||
+ warn("missing MODULE_LICENSE() in %s\n", modname);
|
|
||||||
while (license) {
|
|
||||||
if (license_is_gpl_compatible(license))
|
|
||||||
mod->gpl_compatible = 1;
|
|
||||||
@@ -2144,11 +2142,11 @@ static void check_for_gpl_usage(enum export exp, const char *m, const char *s)
|
|
||||||
{
|
|
||||||
switch (exp) {
|
|
||||||
case export_gpl:
|
|
||||||
- error("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n",
|
|
||||||
+ fatal("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n",
|
|
||||||
m, s);
|
|
||||||
break;
|
|
||||||
case export_unused_gpl:
|
|
||||||
- error("GPL-incompatible module %s.ko uses GPL-only symbol marked UNUSED '%s'\n",
|
|
||||||
+ fatal("GPL-incompatible module %s.ko uses GPL-only symbol marked UNUSED '%s'\n",
|
|
||||||
m, s);
|
|
||||||
break;
|
|
||||||
case export_gpl_future:
|
|
||||||
@@ -2177,18 +2175,22 @@ static void check_for_unused(enum export exp, const char *m, const char *s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void check_exports(struct module *mod)
|
|
||||||
+static int check_exports(struct module *mod)
|
|
||||||
{
|
|
||||||
struct symbol *s, *exp;
|
|
||||||
+ int err = 0;
|
|
||||||
|
|
||||||
for (s = mod->unres; s; s = s->next) {
|
|
||||||
const char *basename;
|
|
||||||
exp = find_symbol(s->name);
|
|
||||||
if (!exp || exp->module == mod) {
|
|
||||||
- if (have_vmlinux && !s->weak)
|
|
||||||
+ if (have_vmlinux && !s->weak) {
|
|
||||||
modpost_log(warn_unresolved ? LOG_WARN : LOG_ERROR,
|
|
||||||
"\"%s\" [%s.ko] undefined!\n",
|
|
||||||
s->name, mod->name);
|
|
||||||
+ if (!warn_unresolved)
|
|
||||||
+ err = 1;
|
|
||||||
+ }
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
basename = strrchr(mod->name, '/');
|
|
||||||
@@ -2202,6 +2204,8 @@ static void check_exports(struct module *mod)
|
|
||||||
modpost_log(allow_missing_ns_imports ? LOG_WARN : LOG_ERROR,
|
|
||||||
"module %s uses symbol %s from namespace %s, but does not import it.\n",
|
|
||||||
basename, exp->name, exp->namespace);
|
|
||||||
+ if (!allow_missing_ns_imports)
|
|
||||||
+ err = 1;
|
|
||||||
add_namespace(&mod->missing_namespaces, exp->namespace);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -2209,9 +2213,11 @@ static void check_exports(struct module *mod)
|
|
||||||
check_for_gpl_usage(exp->export, basename, exp->name);
|
|
||||||
check_for_unused(exp->export, basename, exp->name);
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void check_modname_len(struct module *mod)
|
|
||||||
+static int check_modname_len(struct module *mod)
|
|
||||||
{
|
|
||||||
const char *mod_name;
|
|
||||||
|
|
||||||
@@ -2220,8 +2226,12 @@ static void check_modname_len(struct module *mod)
|
|
||||||
mod_name = mod->name;
|
|
||||||
else
|
|
||||||
mod_name++;
|
|
||||||
- if (strlen(mod_name) >= MODULE_NAME_LEN)
|
|
||||||
- error("module name is too long [%s.ko]\n", mod->name);
|
|
||||||
+ if (strlen(mod_name) >= MODULE_NAME_LEN) {
|
|
||||||
+ merror("module name is too long [%s.ko]\n", mod->name);
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@@ -2263,20 +2273,6 @@ static void add_intree_flag(struct buffer *b, int is_intree)
|
|
||||||
buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
-/**
|
|
||||||
- * add_scmversion() - Adds the MODULE_INFO macro for the scmversion.
|
|
||||||
- * @b: Buffer to append to.
|
|
||||||
- *
|
|
||||||
- * This function fills in the module attribute `scmversion` for the kernel
|
|
||||||
- * module. This is useful for determining a given module's SCM version on
|
|
||||||
- * device via /sys/modules/<module>/scmversion and/or using the modinfo tool.
|
|
||||||
- */
|
|
||||||
-static void add_scmversion(struct buffer *b)
|
|
||||||
-{
|
|
||||||
- if (module_scmversion[0] != '\0')
|
|
||||||
- buf_printf(b, "\nMODULE_INFO(scmversion, \"%s\");\n", module_scmversion);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
/* Cannot check for assembler */
|
|
||||||
static void add_retpoline(struct buffer *b)
|
|
||||||
{
|
|
||||||
@@ -2294,9 +2290,10 @@ static void add_staging_flag(struct buffer *b, const char *name)
|
|
||||||
/**
|
|
||||||
* Record CRCs for unresolved symbols
|
|
||||||
**/
|
|
||||||
-static void add_versions(struct buffer *b, struct module *mod)
|
|
||||||
+static int add_versions(struct buffer *b, struct module *mod)
|
|
||||||
{
|
|
||||||
struct symbol *s, *exp;
|
|
||||||
+ int err = 0;
|
|
||||||
|
|
||||||
for (s = mod->unres; s; s = s->next) {
|
|
||||||
exp = find_symbol(s->name);
|
|
||||||
@@ -2308,7 +2305,7 @@ static void add_versions(struct buffer *b, struct module *mod)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!modversions)
|
|
||||||
- return;
|
|
||||||
+ return err;
|
|
||||||
|
|
||||||
buf_printf(b, "\n");
|
|
||||||
buf_printf(b, "static const struct modversion_info ____versions[]\n");
|
|
||||||
@@ -2323,8 +2320,9 @@ static void add_versions(struct buffer *b, struct module *mod)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (strlen(s->name) >= MODULE_NAME_LEN) {
|
|
||||||
- error("too long symbol \"%s\" [%s.ko]\n",
|
|
||||||
- s->name, mod->name);
|
|
||||||
+ merror("too long symbol \"%s\" [%s.ko]\n",
|
|
||||||
+ s->name, mod->name);
|
|
||||||
+ err = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
buf_printf(b, "\t{ %#8x, \"%s\" },\n",
|
|
||||||
@@ -2332,6 +2330,8 @@ static void add_versions(struct buffer *b, struct module *mod)
|
|
||||||
}
|
|
||||||
|
|
||||||
buf_printf(b, "};\n");
|
|
||||||
+
|
|
||||||
+ return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void add_depends(struct buffer *b, struct module *mod)
|
|
||||||
@@ -2542,11 +2542,12 @@ int main(int argc, char **argv)
|
|
||||||
char *missing_namespace_deps = NULL;
|
|
||||||
char *dump_write = NULL, *files_source = NULL;
|
|
||||||
int opt;
|
|
||||||
+ int err;
|
|
||||||
int n;
|
|
||||||
struct dump_list *dump_read_start = NULL;
|
|
||||||
struct dump_list **dump_read_iter = &dump_read_start;
|
|
||||||
|
|
||||||
- while ((opt = getopt(argc, argv, "ei:mnT:o:awENd:v:")) != -1) {
|
|
||||||
+ while ((opt = getopt(argc, argv, "ei:mnT:o:awENd:")) != -1) {
|
|
||||||
switch (opt) {
|
|
||||||
case 'e':
|
|
||||||
external_module = 1;
|
|
||||||
@@ -2576,7 +2577,7 @@ int main(int argc, char **argv)
|
|
||||||
warn_unresolved = 1;
|
|
||||||
break;
|
|
||||||
case 'E':
|
|
||||||
- sec_mismatch_warn_only = false;
|
|
||||||
+ sec_mismatch_fatal = 1;
|
|
||||||
break;
|
|
||||||
case 'N':
|
|
||||||
allow_missing_ns_imports = 1;
|
|
||||||
@@ -2584,9 +2585,6 @@ int main(int argc, char **argv)
|
|
||||||
case 'd':
|
|
||||||
missing_namespace_deps = optarg;
|
|
||||||
break;
|
|
||||||
- case 'v':
|
|
||||||
- strncpy(module_scmversion, optarg, sizeof(module_scmversion) - 1);
|
|
||||||
- break;
|
|
||||||
default:
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
@@ -2614,6 +2612,8 @@ int main(int argc, char **argv)
|
|
||||||
if (!have_vmlinux)
|
|
||||||
warn("Symbol info of vmlinux is missing. Unresolved symbol check will be entirely skipped.\n");
|
|
||||||
|
|
||||||
+ err = 0;
|
|
||||||
+
|
|
||||||
for (mod = modules; mod; mod = mod->next) {
|
|
||||||
char fname[PATH_MAX];
|
|
||||||
|
|
||||||
@@ -2622,18 +2622,17 @@ int main(int argc, char **argv)
|
|
||||||
|
|
||||||
buf.pos = 0;
|
|
||||||
|
|
||||||
- check_modname_len(mod);
|
|
||||||
- check_exports(mod);
|
|
||||||
+ err |= check_modname_len(mod);
|
|
||||||
+ err |= check_exports(mod);
|
|
||||||
|
|
||||||
add_header(&buf, mod);
|
|
||||||
add_intree_flag(&buf, !external_module);
|
|
||||||
add_retpoline(&buf);
|
|
||||||
add_staging_flag(&buf, mod->name);
|
|
||||||
- add_versions(&buf, mod);
|
|
||||||
+ err |= add_versions(&buf, mod);
|
|
||||||
add_depends(&buf, mod);
|
|
||||||
add_moddevtable(&buf, mod);
|
|
||||||
add_srcversion(&buf, mod);
|
|
||||||
- add_scmversion(&buf);
|
|
||||||
|
|
||||||
sprintf(fname, "%s.mod.c", mod->name);
|
|
||||||
write_if_changed(&buf, fname);
|
|
||||||
@@ -2644,21 +2643,21 @@ int main(int argc, char **argv)
|
|
||||||
|
|
||||||
if (dump_write)
|
|
||||||
write_dump(dump_write);
|
|
||||||
- if (sec_mismatch_count && !sec_mismatch_warn_only)
|
|
||||||
- error("Section mismatches detected.\n"
|
|
||||||
+ if (sec_mismatch_count && sec_mismatch_fatal)
|
|
||||||
+ fatal("Section mismatches detected.\n"
|
|
||||||
"Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n");
|
|
||||||
for (n = 0; n < SYMBOL_HASH_SIZE; n++) {
|
|
||||||
struct symbol *s;
|
|
||||||
|
|
||||||
for (s = symbolhash[n]; s; s = s->next) {
|
|
||||||
if (s->is_static)
|
|
||||||
- error("\"%s\" [%s] is a static %s\n",
|
|
||||||
- s->name, s->module->name,
|
|
||||||
- export_str(s->export));
|
|
||||||
+ warn("\"%s\" [%s] is a static %s\n",
|
|
||||||
+ s->name, s->module->name,
|
|
||||||
+ export_str(s->export));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buf.p);
|
|
||||||
|
|
||||||
- return error_occurred ? 1 : 0;
|
|
||||||
+ return err;
|
|
||||||
}
|
|
||||||
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
|
|
||||||
index 1f76eea7c..3aa052722 100644
|
|
||||||
--- a/scripts/mod/modpost.h
|
|
||||||
+++ b/scripts/mod/modpost.h
|
|
||||||
@@ -2,7 +2,6 @@
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
-#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
@@ -181,14 +180,6 @@ static inline unsigned int get_secindex(const struct elf_info *info,
|
|
||||||
return info->symtab_shndx_start[sym - info->symtab_start];
|
|
||||||
}
|
|
||||||
|
|
||||||
-static inline bool strends(const char *str, const char *postfix)
|
|
||||||
-{
|
|
||||||
- if (strlen(str) < strlen(postfix))
|
|
||||||
- return false;
|
|
||||||
-
|
|
||||||
- return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
/* file2alias.c */
|
|
||||||
extern unsigned int cross_build;
|
|
||||||
void handle_moddevtable(struct module *mod, struct elf_info *info,
|
|
||||||
@@ -210,19 +201,6 @@ enum loglevel {
|
|
||||||
|
|
||||||
void modpost_log(enum loglevel loglevel, const char *fmt, ...);
|
|
||||||
|
|
||||||
-/*
|
|
||||||
- * warn - show the given message, then let modpost continue running, still
|
|
||||||
- * allowing modpost to exit successfully. This should be used when
|
|
||||||
- * we still allow to generate vmlinux and modules.
|
|
||||||
- *
|
|
||||||
- * error - show the given message, then let modpost continue running, but fail
|
|
||||||
- * in the end. This should be used when we should stop building vmlinux
|
|
||||||
- * or modules, but we can continue running modpost to catch as many
|
|
||||||
- * issues as possible.
|
|
||||||
- *
|
|
||||||
- * fatal - show the given message, and bail out immediately. This should be
|
|
||||||
- * used when there is no point to continue running modpost.
|
|
||||||
- */
|
|
||||||
#define warn(fmt, args...) modpost_log(LOG_WARN, fmt, ##args)
|
|
||||||
-#define error(fmt, args...) modpost_log(LOG_ERROR, fmt, ##args)
|
|
||||||
+#define merror(fmt, args...) modpost_log(LOG_ERROR, fmt, ##args)
|
|
||||||
#define fatal(fmt, args...) modpost_log(LOG_FATAL, fmt, ##args)
|
|
||||||
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
|
|
||||||
index 760e6baa7..d587f40f1 100644
|
|
||||||
--- a/scripts/mod/sumversion.c
|
|
||||||
+++ b/scripts/mod/sumversion.c
|
|
||||||
@@ -391,14 +391,10 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen)
|
|
||||||
struct md4_ctx md;
|
|
||||||
char *fname;
|
|
||||||
char filelist[PATH_MAX + 1];
|
|
||||||
- int postfix_len = 1;
|
|
||||||
-
|
|
||||||
- if (strends(modname, ".lto.o"))
|
|
||||||
- postfix_len = 5;
|
|
||||||
|
|
||||||
/* objects for a module are listed in the first line of *.mod file. */
|
|
||||||
snprintf(filelist, sizeof(filelist), "%.*smod",
|
|
||||||
- (int)strlen(modname) - postfix_len, modname);
|
|
||||||
+ (int)strlen(modname) - 1, modname);
|
|
||||||
|
|
||||||
buf = read_text_file(filelist);
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
|||||||
diff --git a/drivers/usb/gadget/legacy/webcam.c b/drivers/usb/gadget/legacy/webcam.c
|
|
||||||
index b18e011b5..87ca1f031 100644
|
|
||||||
--- a/drivers/usb/gadget/legacy/webcam.c
|
|
||||||
+++ b/drivers/usb/gadget/legacy/webcam.c
|
|
||||||
@@ -12,6 +12,7 @@
|
|
||||||
#include <linux/usb/video.h>
|
|
||||||
|
|
||||||
#include "u_uvc.h"
|
|
||||||
+#include "../function/uvc.h"
|
|
||||||
|
|
||||||
USB_GADGET_COMPOSITE_OPTIONS();
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
|||||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
|
|
||||||
index fc4445771c05..145da79f1316 100644
|
|
||||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
|
|
||||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
|
|
||||||
@@ -2741,6 +2741,15 @@ void dw_hdmi_qp_cec_set_hpd(struct dw_hdmi_qp *hdmi, bool plug_in, bool change)
|
|
||||||
if (!plug_in)
|
|
||||||
cec_notifier_set_phys_addr(hdmi->cec_notifier,
|
|
||||||
CEC_PHYS_ADDR_INVALID);
|
|
||||||
+ else if (hdmi->ddc) {
|
|
||||||
+ struct edid *edid = drm_get_edid(&hdmi->connector, hdmi->ddc);
|
|
||||||
+ if (edid) {
|
|
||||||
+ if (hdmi->cec_notifier)
|
|
||||||
+ cec_notifier_set_phys_addr_from_edid(
|
|
||||||
+ hdmi->cec_notifier, edid);
|
|
||||||
+ kfree(edid);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (hdmi->bridge.dev) {
|
|
||||||
if (change && hdmi->cec_adap && hdmi->cec_adap->devnode.registered)
|
|
File diff suppressed because it is too large
Load Diff
@ -1,25 +0,0 @@
|
|||||||
From f95cae35b981643788cd5330e588cdbb22292769 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ricardo Pardini <ricardo@pardini.net>
|
|
||||||
Date: Sun, 18 Dec 2022 04:02:10 +0100
|
|
||||||
Subject: OrangePi5; dubious pl330 stuff extracted from Xunlong tree
|
|
||||||
|
|
||||||
---
|
|
||||||
drivers/dma/pl330.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
|
||||||
index 2e9440955b66..51214c2e6d8f 100644
|
|
||||||
--- a/drivers/dma/pl330.c
|
|
||||||
+++ b/drivers/dma/pl330.c
|
|
||||||
@@ -247,7 +247,7 @@ enum pl330_byteswap {
|
|
||||||
* For typical scenario, at 1word/burst, 10MB and 20MB xfers per req
|
|
||||||
* should be enough for P<->M and M<->M respectively.
|
|
||||||
*/
|
|
||||||
-#define MCODE_BUFF_PER_REQ 256
|
|
||||||
+#define MCODE_BUFF_PER_REQ 512
|
|
||||||
|
|
||||||
/* Use this _only_ to wait on transient states */
|
|
||||||
#define UNTIL(t, s) while (!(_state(t) & (s))) cpu_relax();
|
|
||||||
--
|
|
||||||
Armbian
|
|
||||||
|
|
@ -1,323 +0,0 @@
|
|||||||
From 1426726d9e42394feefab5eb7d4c32222046da4a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ricardo Pardini <ricardo@pardini.net>
|
|
||||||
Date: Sun, 18 Dec 2022 04:02:38 +0100
|
|
||||||
Subject: OrangePi5; dubious `cdn-dp-core` stuff extracted from Xunlong tree
|
|
||||||
|
|
||||||
---
|
|
||||||
drivers/gpu/drm/rockchip/cdn-dp-core.c | 119 +++-------
|
|
||||||
drivers/gpu/drm/rockchip/cdn-dp-core.h | 5 +-
|
|
||||||
2 files changed, 31 insertions(+), 93 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
|
|
||||||
index 89b309d4e9bd..3333003d1556 100644
|
|
||||||
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
|
|
||||||
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
|
|
||||||
@@ -6,7 +6,6 @@
|
|
||||||
|
|
||||||
#include <linux/clk.h>
|
|
||||||
#include <linux/component.h>
|
|
||||||
-#include <linux/extcon.h>
|
|
||||||
#include <linux/firmware.h>
|
|
||||||
#include <linux/mfd/syscon.h>
|
|
||||||
#include <linux/phy/phy.h>
|
|
||||||
@@ -143,24 +142,7 @@ static void cdn_dp_clk_disable(struct cdn_dp_device *dp)
|
|
||||||
|
|
||||||
static int cdn_dp_get_port_lanes(struct cdn_dp_port *port)
|
|
||||||
{
|
|
||||||
- struct extcon_dev *edev = port->extcon;
|
|
||||||
- union extcon_property_value property;
|
|
||||||
- int dptx;
|
|
||||||
- u8 lanes;
|
|
||||||
-
|
|
||||||
- dptx = extcon_get_state(edev, EXTCON_DISP_DP);
|
|
||||||
- if (dptx > 0) {
|
|
||||||
- extcon_get_property(edev, EXTCON_DISP_DP,
|
|
||||||
- EXTCON_PROP_USB_SS, &property);
|
|
||||||
- if (property.intval)
|
|
||||||
- lanes = 2;
|
|
||||||
- else
|
|
||||||
- lanes = 4;
|
|
||||||
- } else {
|
|
||||||
- lanes = 0;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- return lanes;
|
|
||||||
+ return phy_get_bus_width(port->phy);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cdn_dp_get_sink_count(struct cdn_dp_device *dp, u8 *sink_count)
|
|
||||||
@@ -194,7 +176,6 @@ static struct cdn_dp_port *cdn_dp_connected_port(struct cdn_dp_device *dp)
|
|
||||||
static bool cdn_dp_check_sink_connection(struct cdn_dp_device *dp)
|
|
||||||
{
|
|
||||||
unsigned long timeout = jiffies + msecs_to_jiffies(CDN_DPCD_TIMEOUT_MS);
|
|
||||||
- struct cdn_dp_port *port;
|
|
||||||
u8 sink_count = 0;
|
|
||||||
|
|
||||||
if (dp->active_port < 0 || dp->active_port >= dp->ports) {
|
|
||||||
@@ -202,8 +183,6 @@ static bool cdn_dp_check_sink_connection(struct cdn_dp_device *dp)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
- port = dp->port[dp->active_port];
|
|
||||||
-
|
|
||||||
/*
|
|
||||||
* Attempt to read sink count, retry in case the sink may not be ready.
|
|
||||||
*
|
|
||||||
@@ -211,9 +190,6 @@ static bool cdn_dp_check_sink_connection(struct cdn_dp_device *dp)
|
|
||||||
* some docks need more time to power up.
|
|
||||||
*/
|
|
||||||
while (time_before(jiffies, timeout)) {
|
|
||||||
- if (!extcon_get_state(port->extcon, EXTCON_DISP_DP))
|
|
||||||
- return false;
|
|
||||||
-
|
|
||||||
if (!cdn_dp_get_sink_count(dp, &sink_count))
|
|
||||||
return sink_count ? true : false;
|
|
||||||
|
|
||||||
@@ -244,6 +220,13 @@ static void cdn_dp_connector_destroy(struct drm_connector *connector)
|
|
||||||
drm_connector_cleanup(connector);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void cdn_dp_oob_hotplug_event(struct drm_connector *connector)
|
|
||||||
+{
|
|
||||||
+ struct cdn_dp_device *dp = connector_to_dp(connector);
|
|
||||||
+
|
|
||||||
+ schedule_delayed_work(&dp->event_work, msecs_to_jiffies(100));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static const struct drm_connector_funcs cdn_dp_atomic_connector_funcs = {
|
|
||||||
.detect = cdn_dp_connector_detect,
|
|
||||||
.destroy = cdn_dp_connector_destroy,
|
|
||||||
@@ -276,8 +259,9 @@ static int cdn_dp_connector_get_modes(struct drm_connector *connector)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int cdn_dp_connector_mode_valid(struct drm_connector *connector,
|
|
||||||
- struct drm_display_mode *mode)
|
|
||||||
+static enum drm_mode_status
|
|
||||||
+cdn_dp_connector_mode_valid(struct drm_connector *connector,
|
|
||||||
+ struct drm_display_mode *mode)
|
|
||||||
{
|
|
||||||
struct cdn_dp_device *dp = connector_to_dp(connector);
|
|
||||||
struct drm_display_info *display_info = &dp->connector.display_info;
|
|
||||||
@@ -382,7 +366,6 @@ static int cdn_dp_get_sink_capability(struct cdn_dp_device *dp)
|
|
||||||
|
|
||||||
static int cdn_dp_enable_phy(struct cdn_dp_device *dp, struct cdn_dp_port *port)
|
|
||||||
{
|
|
||||||
- union extcon_property_value property;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!port->phy_enabled) {
|
|
||||||
@@ -409,15 +392,8 @@ static int cdn_dp_enable_phy(struct cdn_dp_device *dp, struct cdn_dp_port *port)
|
|
||||||
goto err_power_on;
|
|
||||||
}
|
|
||||||
|
|
||||||
- ret = extcon_get_property(port->extcon, EXTCON_DISP_DP,
|
|
||||||
- EXTCON_PROP_USB_TYPEC_POLARITY, &property);
|
|
||||||
- if (ret) {
|
|
||||||
- DRM_DEV_ERROR(dp->dev, "get property failed\n");
|
|
||||||
- goto err_power_on;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
port->lanes = cdn_dp_get_port_lanes(port);
|
|
||||||
- ret = cdn_dp_set_host_cap(dp, port->lanes, property.intval);
|
|
||||||
+ ret = cdn_dp_set_host_cap(dp, port->lanes, 0);
|
|
||||||
if (ret) {
|
|
||||||
DRM_DEV_ERROR(dp->dev, "set host capabilities failed: %d\n",
|
|
||||||
ret);
|
|
||||||
@@ -669,7 +645,7 @@ static void cdn_dp_encoder_disable(struct drm_encoder *encoder)
|
|
||||||
* run the event_work to re-connect it.
|
|
||||||
*/
|
|
||||||
if (!dp->connected && cdn_dp_connected_port(dp))
|
|
||||||
- schedule_work(&dp->event_work);
|
|
||||||
+ schedule_delayed_work(&dp->event_work, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cdn_dp_encoder_atomic_check(struct drm_encoder *encoder,
|
|
||||||
@@ -680,13 +656,7 @@ static int cdn_dp_encoder_atomic_check(struct drm_encoder *encoder,
|
|
||||||
|
|
||||||
s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
|
|
||||||
s->output_type = DRM_MODE_CONNECTOR_DisplayPort;
|
|
||||||
-
|
|
||||||
- /*
|
|
||||||
- * Do a full modeset if crtc_state->active is changed to be true.
|
|
||||||
- * This ensures our ->mode_set() is called to get the CDN controller
|
|
||||||
- * and the PHY ready to send video data.
|
|
||||||
- */
|
|
||||||
- crtc_state->mode_changed = true;
|
|
||||||
+ s->tv_state = &conn_state->tv;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -919,7 +889,7 @@ static int cdn_dp_request_firmware(struct cdn_dp_device *dp)
|
|
||||||
|
|
||||||
static void cdn_dp_pd_event_work(struct work_struct *work)
|
|
||||||
{
|
|
||||||
- struct cdn_dp_device *dp = container_of(work, struct cdn_dp_device,
|
|
||||||
+ struct cdn_dp_device *dp = container_of(to_delayed_work(work), struct cdn_dp_device,
|
|
||||||
event_work);
|
|
||||||
struct drm_connector *connector = &dp->connector;
|
|
||||||
enum drm_connector_status old_status;
|
|
||||||
@@ -992,31 +962,13 @@ static void cdn_dp_pd_event_work(struct work_struct *work)
|
|
||||||
drm_kms_helper_hotplug_event(dp->drm_dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int cdn_dp_pd_event(struct notifier_block *nb,
|
|
||||||
- unsigned long event, void *priv)
|
|
||||||
-{
|
|
||||||
- struct cdn_dp_port *port = container_of(nb, struct cdn_dp_port,
|
|
||||||
- event_nb);
|
|
||||||
- struct cdn_dp_device *dp = port->dp;
|
|
||||||
-
|
|
||||||
- /*
|
|
||||||
- * It would be nice to be able to just do the work inline right here.
|
|
||||||
- * However, we need to make a bunch of calls that might sleep in order
|
|
||||||
- * to turn on the block/phy, so use a worker instead.
|
|
||||||
- */
|
|
||||||
- schedule_work(&dp->event_work);
|
|
||||||
-
|
|
||||||
- return NOTIFY_DONE;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
static int cdn_dp_bind(struct device *dev, struct device *master, void *data)
|
|
||||||
{
|
|
||||||
struct cdn_dp_device *dp = dev_get_drvdata(dev);
|
|
||||||
struct drm_encoder *encoder;
|
|
||||||
struct drm_connector *connector;
|
|
||||||
- struct cdn_dp_port *port;
|
|
||||||
struct drm_device *drm_dev = data;
|
|
||||||
- int ret, i;
|
|
||||||
+ int ret;
|
|
||||||
|
|
||||||
ret = cdn_dp_parse_dt(dp);
|
|
||||||
if (ret < 0)
|
|
||||||
@@ -1028,12 +980,12 @@ static int cdn_dp_bind(struct device *dev, struct device *master, void *data)
|
|
||||||
dp->active_port = -1;
|
|
||||||
dp->fw_loaded = false;
|
|
||||||
|
|
||||||
- INIT_WORK(&dp->event_work, cdn_dp_pd_event_work);
|
|
||||||
+ INIT_DELAYED_WORK(&dp->event_work, cdn_dp_pd_event_work);
|
|
||||||
|
|
||||||
encoder = &dp->encoder;
|
|
||||||
|
|
||||||
- encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev,
|
|
||||||
- dev->of_node);
|
|
||||||
+ encoder->possible_crtcs = rockchip_drm_of_find_possible_crtcs(drm_dev,
|
|
||||||
+ dev->of_node);
|
|
||||||
DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
|
|
||||||
|
|
||||||
ret = drm_simple_encoder_init(drm_dev, encoder,
|
|
||||||
@@ -1065,23 +1017,14 @@ static int cdn_dp_bind(struct device *dev, struct device *master, void *data)
|
|
||||||
goto err_free_connector;
|
|
||||||
}
|
|
||||||
|
|
||||||
- for (i = 0; i < dp->ports; i++) {
|
|
||||||
- port = dp->port[i];
|
|
||||||
-
|
|
||||||
- port->event_nb.notifier_call = cdn_dp_pd_event;
|
|
||||||
- ret = devm_extcon_register_notifier(dp->dev, port->extcon,
|
|
||||||
- EXTCON_DISP_DP,
|
|
||||||
- &port->event_nb);
|
|
||||||
- if (ret) {
|
|
||||||
- DRM_DEV_ERROR(dev,
|
|
||||||
- "register EXTCON_DISP_DP notifier err\n");
|
|
||||||
- goto err_free_connector;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
+ dp->sub_dev.connector = &dp->connector;
|
|
||||||
+ dp->sub_dev.of_node = dev->of_node;
|
|
||||||
+ dp->sub_dev.oob_hotplug_event = cdn_dp_oob_hotplug_event;
|
|
||||||
+ rockchip_drm_register_sub_dev(&dp->sub_dev);
|
|
||||||
|
|
||||||
pm_runtime_enable(dev);
|
|
||||||
|
|
||||||
- schedule_work(&dp->event_work);
|
|
||||||
+ schedule_delayed_work(&dp->event_work, 0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
@@ -1098,7 +1041,7 @@ static void cdn_dp_unbind(struct device *dev, struct device *master, void *data)
|
|
||||||
struct drm_encoder *encoder = &dp->encoder;
|
|
||||||
struct drm_connector *connector = &dp->connector;
|
|
||||||
|
|
||||||
- cancel_work_sync(&dp->event_work);
|
|
||||||
+ cancel_delayed_work_sync(&dp->event_work);
|
|
||||||
cdn_dp_encoder_disable(encoder);
|
|
||||||
encoder->funcs->destroy(encoder);
|
|
||||||
connector->funcs->destroy(connector);
|
|
||||||
@@ -1136,7 +1079,7 @@ static __maybe_unused int cdn_dp_resume(struct device *dev)
|
|
||||||
mutex_lock(&dp->lock);
|
|
||||||
dp->suspended = false;
|
|
||||||
if (dp->fw_loaded)
|
|
||||||
- schedule_work(&dp->event_work);
|
|
||||||
+ schedule_delayed_work(&dp->event_work, 0);
|
|
||||||
mutex_unlock(&dp->lock);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
@@ -1149,7 +1092,6 @@ static int cdn_dp_probe(struct platform_device *pdev)
|
|
||||||
struct cdn_dp_data *dp_data;
|
|
||||||
struct cdn_dp_port *port;
|
|
||||||
struct cdn_dp_device *dp;
|
|
||||||
- struct extcon_dev *extcon;
|
|
||||||
struct phy *phy;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
@@ -1162,21 +1104,18 @@ static int cdn_dp_probe(struct platform_device *pdev)
|
|
||||||
dp_data = (struct cdn_dp_data *)match->data;
|
|
||||||
|
|
||||||
for (i = 0; i < dp_data->max_phy; i++) {
|
|
||||||
- extcon = extcon_get_edev_by_phandle(dev, i);
|
|
||||||
phy = devm_of_phy_get_by_index(dev, dev->of_node, i);
|
|
||||||
|
|
||||||
- if (PTR_ERR(extcon) == -EPROBE_DEFER ||
|
|
||||||
- PTR_ERR(phy) == -EPROBE_DEFER)
|
|
||||||
+ if (PTR_ERR(phy) == -EPROBE_DEFER)
|
|
||||||
return -EPROBE_DEFER;
|
|
||||||
|
|
||||||
- if (IS_ERR(extcon) || IS_ERR(phy))
|
|
||||||
+ if (IS_ERR(phy))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
|
|
||||||
if (!port)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
- port->extcon = extcon;
|
|
||||||
port->phy = phy;
|
|
||||||
port->dp = dp;
|
|
||||||
port->id = i;
|
|
||||||
@@ -1184,7 +1123,7 @@ static int cdn_dp_probe(struct platform_device *pdev)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dp->ports) {
|
|
||||||
- DRM_DEV_ERROR(dev, "missing extcon or phy\n");
|
|
||||||
+ DRM_DEV_ERROR(dev, "missing phy\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h b/drivers/gpu/drm/rockchip/cdn-dp-core.h
|
|
||||||
index 81ac9b658a70..519900c673cb 100644
|
|
||||||
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
|
|
||||||
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
|
|
||||||
@@ -53,8 +53,6 @@ struct cdn_firmware_header {
|
|
||||||
|
|
||||||
struct cdn_dp_port {
|
|
||||||
struct cdn_dp_device *dp;
|
|
||||||
- struct notifier_block event_nb;
|
|
||||||
- struct extcon_dev *extcon;
|
|
||||||
struct phy *phy;
|
|
||||||
u8 lanes;
|
|
||||||
bool phy_enabled;
|
|
||||||
@@ -68,8 +66,9 @@ struct cdn_dp_device {
|
|
||||||
struct drm_encoder encoder;
|
|
||||||
struct drm_display_mode mode;
|
|
||||||
struct platform_device *audio_pdev;
|
|
||||||
- struct work_struct event_work;
|
|
||||||
+ struct delayed_work event_work;
|
|
||||||
struct edid *edid;
|
|
||||||
+ struct rockchip_drm_sub_dev sub_dev;
|
|
||||||
|
|
||||||
struct mutex lock;
|
|
||||||
bool connected;
|
|
||||||
--
|
|
||||||
Armbian
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
|||||||
From 94e7dfcdff58dc32cd50f3e95220c89c469d213d Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ricardo Pardini <ricardo@pardini.net>
|
|
||||||
Date: Sun, 18 Dec 2022 04:02:59 +0100
|
|
||||||
Subject: OrangePi5; dubious `hdmi` stuff extracted from Xunlong tree
|
|
||||||
|
|
||||||
---
|
|
||||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 16 ++++++++++
|
|
||||||
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +-
|
|
||||||
2 files changed, 17 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
|
|
||||||
index fc4445771c05..c64e0aa095ca 100644
|
|
||||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
|
|
||||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
|
|
||||||
@@ -1952,6 +1952,22 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
|
|
||||||
result = connector_status_disconnected;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ mutex_lock(&hdmi->mutex);
|
|
||||||
+ if (result != hdmi->last_connector_result) {
|
|
||||||
+ dev_dbg(hdmi->dev, "read_hpd result: %d", result);
|
|
||||||
+ handle_plugged_change(hdmi,
|
|
||||||
+ result == connector_status_connected);
|
|
||||||
+ hdmi->last_connector_result = result;
|
|
||||||
+ }
|
|
||||||
+ mutex_unlock(&hdmi->mutex);
|
|
||||||
+
|
|
||||||
+ if (result == connector_status_connected){
|
|
||||||
+ extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, true); //change for uboot-logo
|
|
||||||
+ }
|
|
||||||
+ else {
|
|
||||||
+ extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, false);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
|
||||||
index ed06757c8280..e73b0b2bc036 100644
|
|
||||||
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
|
||||||
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
|
||||||
@@ -806,7 +806,7 @@ static void hdmi_select_link_config(struct rockchip_hdmi *hdmi,
|
|
||||||
hdmi->link_cfg.add_func = hdmi->add_func;
|
|
||||||
|
|
||||||
if (!max_frl_rate || (tmdsclk < HDMI20_MAX_RATE && mode.clock < HDMI20_MAX_RATE)) {
|
|
||||||
- dev_info(hdmi->dev, "use tmds mode\n");
|
|
||||||
+ //dev_info(hdmi->dev, "use tmds mode\n");
|
|
||||||
hdmi->link_cfg.frl_mode = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
Armbian
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user