mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-28 21:26:49 +00:00
Merge pull request #5389 from heitbaum/kernel10rc
[Allwinner,Generic,Rockchip] linux: Update to 5.10.41
This commit is contained in:
commit
9f36748e13
@ -28,8 +28,8 @@ case "${LINUX}" in
|
||||
PKG_SOURCE_NAME="linux-${LINUX}-${PKG_VERSION}.tar.gz"
|
||||
;;
|
||||
*)
|
||||
PKG_VERSION="5.10.35"
|
||||
PKG_SHA256="ac37a19d45b77a87e58e3aae8b127a6e7eb85ed7467fc8e58474b387bfd498fd"
|
||||
PKG_VERSION="5.10.41"
|
||||
PKG_SHA256="f604759de80767c4f8bdc500eec730dc161bc914a48bd366b748c176701a6771"
|
||||
PKG_URL="https://www.kernel.org/pub/linux/kernel/v5.x/${PKG_NAME}-${PKG_VERSION}.tar.xz"
|
||||
PKG_PATCH_DIRS="default"
|
||||
;;
|
||||
|
@ -1,40 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Sat, 10 Apr 2021 18:55:09 +0200
|
||||
Subject: [PATCH] media: cedrus: Fix HEVC status macros
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
.../staging/media/sunxi/cedrus/cedrus_regs.h | 17 +++++++++--------
|
||||
1 file changed, 9 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
||||
index 6cb1c279790f..7ab3a2b0aa10 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
||||
@@ -443,16 +443,17 @@
|
||||
#define VE_DEC_H265_STATUS_STCD_BUSY BIT(21)
|
||||
#define VE_DEC_H265_STATUS_WB_BUSY BIT(20)
|
||||
#define VE_DEC_H265_STATUS_BS_DMA_BUSY BIT(19)
|
||||
-#define VE_DEC_H265_STATUS_IQIT_BUSY BIT(18)
|
||||
+#define VE_DEC_H265_STATUS_IT_BUSY BIT(18)
|
||||
#define VE_DEC_H265_STATUS_INTER_BUSY BIT(17)
|
||||
#define VE_DEC_H265_STATUS_MORE_DATA BIT(16)
|
||||
-#define VE_DEC_H265_STATUS_VLD_BUSY BIT(14)
|
||||
-#define VE_DEC_H265_STATUS_DEBLOCKING_BUSY BIT(13)
|
||||
-#define VE_DEC_H265_STATUS_DEBLOCKING_DRAM_BUSY BIT(12)
|
||||
-#define VE_DEC_H265_STATUS_INTRA_BUSY BIT(11)
|
||||
-#define VE_DEC_H265_STATUS_SAO_BUSY BIT(10)
|
||||
-#define VE_DEC_H265_STATUS_MVP_BUSY BIT(9)
|
||||
-#define VE_DEC_H265_STATUS_SWDEC_BUSY BIT(8)
|
||||
+#define VE_DEC_H265_STATUS_DBLK_BUSY BIT(15)
|
||||
+#define VE_DEC_H265_STATUS_IREC_BUSY BIT(14)
|
||||
+#define VE_DEC_H265_STATUS_INTRA_BUSY BIT(13)
|
||||
+#define VE_DEC_H265_STATUS_MCRI_BUSY BIT(12)
|
||||
+#define VE_DEC_H265_STATUS_IQIT_BUSY BIT(11)
|
||||
+#define VE_DEC_H265_STATUS_MVP_BUSY BIT(10)
|
||||
+#define VE_DEC_H265_STATUS_IS_BUSY BIT(9)
|
||||
+#define VE_DEC_H265_STATUS_VLD_BUSY BIT(8)
|
||||
#define VE_DEC_H265_STATUS_OVER_TIME BIT(3)
|
||||
#define VE_DEC_H265_STATUS_VLD_DATA_REQ BIT(2)
|
||||
#define VE_DEC_H265_STATUS_ERROR BIT(1)
|
@ -1,109 +0,0 @@
|
||||
From be7e8af98f3af729aa9f08b1053f9533a5cceb91 Mon Sep 17 00:00:00 2001
|
||||
From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
|
||||
Date: Sat, 27 Mar 2021 12:27:40 +0100
|
||||
Subject: [PATCH] media: v4l2-ctrls.c: fix race condition in hdl->requests list
|
||||
|
||||
When a request is re-inited it will release all control handler
|
||||
objects that are still in the request. It does that by unbinding
|
||||
and putting all those objects. When the object is unbound the
|
||||
obj->req pointer is set to NULL, and the object's unbind op is
|
||||
called. When the object it put the object's release op is called
|
||||
to free the memory.
|
||||
|
||||
For a request object that contains a control handler that means
|
||||
that v4l2_ctrl_handler_free() is called in the release op.
|
||||
|
||||
A control handler used in a request has a pointer to the main
|
||||
control handler that is created by the driver and contains the
|
||||
current state of all controls. If the device is unbound (due to
|
||||
rmmod or a forced unbind), then that main handler is freed, again
|
||||
by calling v4l2_ctrl_handler_free(), and any outstanding request
|
||||
objects that refer to that main handler have to be unbound and put
|
||||
as well.
|
||||
|
||||
It does that by this test:
|
||||
|
||||
if (!hdl->req_obj.req && !list_empty(&hdl->requests)) {
|
||||
|
||||
I.e. the handler has no pointer to a request, so is the main
|
||||
handler, and one or more request objects refer to this main
|
||||
handler.
|
||||
|
||||
However, this test is wrong since hdl->req_obj.req is actually
|
||||
NULL when re-initing a request (the object unbind will set req to
|
||||
NULL), and the only reason this seemingly worked is that the
|
||||
requests list is typically empty since the request's unbind op
|
||||
will remove the handler from the requests list.
|
||||
|
||||
But if another thread is at the same time adding a new control
|
||||
to a request, then there is a race condition where one thread
|
||||
is removing a control handler object from the requests list and
|
||||
another thread is adding one. The result is that hdl->requests
|
||||
is no longer empty and the code thinks that a main handler is
|
||||
being freed instead of a control handler that is part of a request.
|
||||
|
||||
There are two bugs here: first the test for hdl->req_obj.req: this
|
||||
should be hdl->req_obj.ops since only the main control handler will
|
||||
have a NULL pointer there.
|
||||
|
||||
The second is that adding or deleting request objects from the
|
||||
requests list of the main handler isn't protected by taking the
|
||||
main handler's lock.
|
||||
|
||||
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
|
||||
Reported-by: John Cox <jc@kynesim.co.uk>
|
||||
Fixes: 6fa6f831f095 ("media: v4l2-ctrls: add core request support")
|
||||
Tested-by: John Cox <jc@kynesim.co.uk>
|
||||
Reported-by: John Cox <jc@kynesim.co.uk>
|
||||
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
||||
---
|
||||
drivers/media/v4l2-core/v4l2-ctrls.c | 17 ++++++++++++++---
|
||||
1 file changed, 14 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
index e7fcbaeec0ae..c7bcc5c25771 100644
|
||||
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
@@ -2650,7 +2650,15 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl)
|
||||
if (hdl == NULL || hdl->buckets == NULL)
|
||||
return;
|
||||
|
||||
- if (!hdl->req_obj.req && !list_empty(&hdl->requests)) {
|
||||
+ /*
|
||||
+ * If the main handler is freed and it is used by handler objects in
|
||||
+ * outstanding requests, then unbind and put those objects before
|
||||
+ * freeing the main handler.
|
||||
+ *
|
||||
+ * The main handler can be identified by having a NULL ops pointer in
|
||||
+ * the request object.
|
||||
+ */
|
||||
+ if (!hdl->req_obj.ops && !list_empty(&hdl->requests)) {
|
||||
struct v4l2_ctrl_handler *req, *next_req;
|
||||
|
||||
list_for_each_entry_safe(req, next_req, &hdl->requests, requests) {
|
||||
@@ -3730,8 +3738,8 @@ static void v4l2_ctrl_request_unbind(struct media_request_object *obj)
|
||||
container_of(obj, struct v4l2_ctrl_handler, req_obj);
|
||||
struct v4l2_ctrl_handler *main_hdl = obj->priv;
|
||||
|
||||
+ mutex_lock(main_hdl->lock);
|
||||
list_del_init(&hdl->requests);
|
||||
- mutex_lock(main_hdl->lock);
|
||||
if (hdl->request_is_queued) {
|
||||
list_del_init(&hdl->requests_queued);
|
||||
hdl->request_is_queued = false;
|
||||
@@ -3790,8 +3798,11 @@ static int v4l2_ctrl_request_bind(struct media_request *req,
|
||||
if (!ret) {
|
||||
ret = media_request_object_bind(req, &req_ops,
|
||||
from, false, &hdl->req_obj);
|
||||
- if (!ret)
|
||||
+ if (!ret) {
|
||||
+ mutex_lock(from->lock);
|
||||
list_add_tail(&hdl->requests, &from->requests);
|
||||
+ mutex_unlock(from->lock);
|
||||
+ }
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
2.31.1
|
||||
|
@ -1,332 +0,0 @@
|
||||
From ac34b79da14d67a9b494f6125186becbd067e225 Mon Sep 17 00:00:00 2001
|
||||
From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
|
||||
Date: Mon, 12 Apr 2021 13:51:23 +0200
|
||||
Subject: [PATCH] media: v4l2-ctrls: fix reference to freed memory
|
||||
|
||||
When controls are used together with the Request API, then for
|
||||
each request a v4l2_ctrl_handler struct is allocated. This contains
|
||||
the controls that can be set in a request. If a control is *not* set in
|
||||
the request, then the value used in the most recent previous request
|
||||
must be used, or the current value if it is not found in any outstanding
|
||||
requests.
|
||||
|
||||
The framework tried to find such a previous request and it would set
|
||||
the 'req' pointer in struct v4l2_ctrl_ref to the v4l2_ctrl_ref of the
|
||||
control in such a previous request. So far, so good. However, when that
|
||||
previous request was applied to the hardware, returned to userspace, and
|
||||
then userspace would re-init or free that request, any 'ref' pointer in
|
||||
still-queued requests would suddenly point to freed memory.
|
||||
|
||||
This was not noticed before since the drivers that use this expected
|
||||
that each request would always have the controls set, so there was
|
||||
never any need to find a control in older requests. This requirement
|
||||
was relaxed, and now this bug surfaced.
|
||||
|
||||
It was also made worse by changeset
|
||||
2fae4d6aabc8 ("media: v4l2-ctrls: v4l2_ctrl_request_complete() should always set ref->req")
|
||||
which increased the chance of this happening.
|
||||
|
||||
The use of the 'req' pointer in v4l2_ctrl_ref was very fragile, so
|
||||
drop this entirely. Instead add a valid_p_req bool to indicate that
|
||||
p_req contains a valid value for this control. And if it is false,
|
||||
then just use the current value of the control.
|
||||
|
||||
Note that VIDIOC_G_EXT_CTRLS will always return -EACCES when attempting
|
||||
to get a control from a request until the request is completed. And in
|
||||
that case, all controls in the request will have the control value set
|
||||
(i.e. valid_p_req is true). This means that the whole 'find the most
|
||||
recent previous request containing a control' idea is pointless, and
|
||||
the code can be simplified considerably.
|
||||
|
||||
The v4l2_g_ext_ctrls_common() function was refactored a bit to make
|
||||
it more understandable. It also avoids updating volatile controls
|
||||
in a completed request since that was already done when the request
|
||||
was completed.
|
||||
|
||||
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
|
||||
Fixes: 2fae4d6aabc8 ("media: v4l2-ctrls: v4l2_ctrl_request_complete() should always set ref->req")
|
||||
Fixes: 6fa6f831f095 ("media: v4l2-ctrls: add core request support")
|
||||
Cc: <stable@vger.kernel.org> # for v5.9 and up
|
||||
Tested-by: Alexandre Courbot <acourbot@chromium.org>
|
||||
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
||||
---
|
||||
drivers/media/v4l2-core/v4l2-ctrls.c | 137 ++++++++++++---------------
|
||||
include/media/v4l2-ctrls.h | 12 ++-
|
||||
2 files changed, 70 insertions(+), 79 deletions(-)
|
||||
|
||||
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
index c7bcc5c25771..0d7fe1bd975a 100644
|
||||
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
@@ -2504,7 +2504,16 @@ static void new_to_req(struct v4l2_ctrl_ref *ref)
|
||||
if (!ref)
|
||||
return;
|
||||
ptr_to_ptr(ref->ctrl, ref->ctrl->p_new, ref->p_req);
|
||||
- ref->req = ref;
|
||||
+ ref->valid_p_req = true;
|
||||
+}
|
||||
+
|
||||
+/* Copy the current value to the request value */
|
||||
+static void cur_to_req(struct v4l2_ctrl_ref *ref)
|
||||
+{
|
||||
+ if (!ref)
|
||||
+ return;
|
||||
+ ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->p_req);
|
||||
+ ref->valid_p_req = true;
|
||||
}
|
||||
|
||||
/* Copy the request value to the new value */
|
||||
@@ -2512,8 +2521,8 @@ static void req_to_new(struct v4l2_ctrl_ref *ref)
|
||||
{
|
||||
if (!ref)
|
||||
return;
|
||||
- if (ref->req)
|
||||
- ptr_to_ptr(ref->ctrl, ref->req->p_req, ref->ctrl->p_new);
|
||||
+ if (ref->valid_p_req)
|
||||
+ ptr_to_ptr(ref->ctrl, ref->p_req, ref->ctrl->p_new);
|
||||
else
|
||||
ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->ctrl->p_new);
|
||||
}
|
||||
@@ -3694,39 +3703,8 @@ static void v4l2_ctrl_request_queue(struct media_request_object *obj)
|
||||
struct v4l2_ctrl_handler *hdl =
|
||||
container_of(obj, struct v4l2_ctrl_handler, req_obj);
|
||||
struct v4l2_ctrl_handler *main_hdl = obj->priv;
|
||||
- struct v4l2_ctrl_handler *prev_hdl = NULL;
|
||||
- struct v4l2_ctrl_ref *ref_ctrl, *ref_ctrl_prev = NULL;
|
||||
|
||||
mutex_lock(main_hdl->lock);
|
||||
- if (list_empty(&main_hdl->requests_queued))
|
||||
- goto queue;
|
||||
-
|
||||
- prev_hdl = list_last_entry(&main_hdl->requests_queued,
|
||||
- struct v4l2_ctrl_handler, requests_queued);
|
||||
- /*
|
||||
- * Note: prev_hdl and hdl must contain the same list of control
|
||||
- * references, so if any differences are detected then that is a
|
||||
- * driver bug and the WARN_ON is triggered.
|
||||
- */
|
||||
- mutex_lock(prev_hdl->lock);
|
||||
- ref_ctrl_prev = list_first_entry(&prev_hdl->ctrl_refs,
|
||||
- struct v4l2_ctrl_ref, node);
|
||||
- list_for_each_entry(ref_ctrl, &hdl->ctrl_refs, node) {
|
||||
- if (ref_ctrl->req)
|
||||
- continue;
|
||||
- while (ref_ctrl_prev->ctrl->id < ref_ctrl->ctrl->id) {
|
||||
- /* Should never happen, but just in case... */
|
||||
- if (list_is_last(&ref_ctrl_prev->node,
|
||||
- &prev_hdl->ctrl_refs))
|
||||
- break;
|
||||
- ref_ctrl_prev = list_next_entry(ref_ctrl_prev, node);
|
||||
- }
|
||||
- if (WARN_ON(ref_ctrl_prev->ctrl->id != ref_ctrl->ctrl->id))
|
||||
- break;
|
||||
- ref_ctrl->req = ref_ctrl_prev->req;
|
||||
- }
|
||||
- mutex_unlock(prev_hdl->lock);
|
||||
-queue:
|
||||
list_add_tail(&hdl->requests_queued, &main_hdl->requests_queued);
|
||||
hdl->request_is_queued = true;
|
||||
mutex_unlock(main_hdl->lock);
|
||||
@@ -3783,7 +3761,7 @@ v4l2_ctrl_request_hdl_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id)
|
||||
{
|
||||
struct v4l2_ctrl_ref *ref = find_ref_lock(hdl, id);
|
||||
|
||||
- return (ref && ref->req == ref) ? ref->ctrl : NULL;
|
||||
+ return (ref && ref->valid_p_req) ? ref->ctrl : NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_ctrl_find);
|
||||
|
||||
@@ -3972,7 +3950,13 @@ static int class_check(struct v4l2_ctrl_handler *hdl, u32 which)
|
||||
return find_ref_lock(hdl, which | 1) ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
-/* Get extended controls. Allocates the helpers array if needed. */
|
||||
+/*
|
||||
+ * Get extended controls. Allocates the helpers array if needed.
|
||||
+ *
|
||||
+ * Note that v4l2_g_ext_ctrls_common() with 'which' set to
|
||||
+ * V4L2_CTRL_WHICH_REQUEST_VAL is only called if the request was
|
||||
+ * completed, and in that case valid_p_req is true for all controls.
|
||||
+ */
|
||||
static int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,
|
||||
struct v4l2_ext_controls *cs,
|
||||
struct video_device *vdev)
|
||||
@@ -3981,9 +3965,10 @@ static int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,
|
||||
struct v4l2_ctrl_helper *helpers = helper;
|
||||
int ret;
|
||||
int i, j;
|
||||
- bool def_value;
|
||||
+ bool is_default, is_request;
|
||||
|
||||
- def_value = (cs->which == V4L2_CTRL_WHICH_DEF_VAL);
|
||||
+ is_default = (cs->which == V4L2_CTRL_WHICH_DEF_VAL);
|
||||
+ is_request = (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL);
|
||||
|
||||
cs->error_idx = cs->count;
|
||||
cs->which = V4L2_CTRL_ID2WHICH(cs->which);
|
||||
@@ -4009,11 +3994,9 @@ static int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,
|
||||
ret = -EACCES;
|
||||
|
||||
for (i = 0; !ret && i < cs->count; i++) {
|
||||
- int (*ctrl_to_user)(struct v4l2_ext_control *c,
|
||||
- struct v4l2_ctrl *ctrl);
|
||||
struct v4l2_ctrl *master;
|
||||
-
|
||||
- ctrl_to_user = def_value ? def_to_user : cur_to_user;
|
||||
+ bool is_volatile = false;
|
||||
+ u32 idx = i;
|
||||
|
||||
if (helpers[i].mref == NULL)
|
||||
continue;
|
||||
@@ -4023,31 +4006,48 @@ static int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,
|
||||
|
||||
v4l2_ctrl_lock(master);
|
||||
|
||||
- /* g_volatile_ctrl will update the new control values */
|
||||
- if (!def_value &&
|
||||
+ /*
|
||||
+ * g_volatile_ctrl will update the new control values.
|
||||
+ * This makes no sense for V4L2_CTRL_WHICH_DEF_VAL and
|
||||
+ * V4L2_CTRL_WHICH_REQUEST_VAL. In the case of requests
|
||||
+ * it is v4l2_ctrl_request_complete() that copies the
|
||||
+ * volatile controls at the time of request completion
|
||||
+ * to the request, so you don't want to do that again.
|
||||
+ */
|
||||
+ if (!is_default && !is_request &&
|
||||
((master->flags & V4L2_CTRL_FLAG_VOLATILE) ||
|
||||
(master->has_volatiles && !is_cur_manual(master)))) {
|
||||
for (j = 0; j < master->ncontrols; j++)
|
||||
cur_to_new(master->cluster[j]);
|
||||
ret = call_op(master, g_volatile_ctrl);
|
||||
- ctrl_to_user = new_to_user;
|
||||
+ is_volatile = true;
|
||||
}
|
||||
- /* If OK, then copy the current (for non-volatile controls)
|
||||
- or the new (for volatile controls) control values to the
|
||||
- caller */
|
||||
- if (!ret) {
|
||||
- u32 idx = i;
|
||||
|
||||
- do {
|
||||
- if (helpers[idx].ref->req)
|
||||
- ret = req_to_user(cs->controls + idx,
|
||||
- helpers[idx].ref->req);
|
||||
- else
|
||||
- ret = ctrl_to_user(cs->controls + idx,
|
||||
- helpers[idx].ref->ctrl);
|
||||
- idx = helpers[idx].next;
|
||||
- } while (!ret && idx);
|
||||
+ if (ret) {
|
||||
+ v4l2_ctrl_unlock(master);
|
||||
+ break;
|
||||
}
|
||||
+
|
||||
+ /*
|
||||
+ * Copy the default value (if is_default is true), the
|
||||
+ * request value (if is_request is true and p_req is valid),
|
||||
+ * the new volatile value (if is_volatile is true) or the
|
||||
+ * current value.
|
||||
+ */
|
||||
+ do {
|
||||
+ struct v4l2_ctrl_ref *ref = helpers[idx].ref;
|
||||
+
|
||||
+ if (is_default)
|
||||
+ ret = def_to_user(cs->controls + idx, ref->ctrl);
|
||||
+ else if (is_request && ref->valid_p_req)
|
||||
+ ret = req_to_user(cs->controls + idx, ref);
|
||||
+ else if (is_volatile)
|
||||
+ ret = new_to_user(cs->controls + idx, ref->ctrl);
|
||||
+ else
|
||||
+ ret = cur_to_user(cs->controls + idx, ref->ctrl);
|
||||
+ idx = helpers[idx].next;
|
||||
+ } while (!ret && idx);
|
||||
+
|
||||
v4l2_ctrl_unlock(master);
|
||||
}
|
||||
|
||||
@@ -4690,8 +4690,6 @@ void v4l2_ctrl_request_complete(struct media_request *req,
|
||||
unsigned int i;
|
||||
|
||||
if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) {
|
||||
- ref->req = ref;
|
||||
-
|
||||
v4l2_ctrl_lock(master);
|
||||
/* g_volatile_ctrl will update the current control values */
|
||||
for (i = 0; i < master->ncontrols; i++)
|
||||
@@ -4701,21 +4699,12 @@ void v4l2_ctrl_request_complete(struct media_request *req,
|
||||
v4l2_ctrl_unlock(master);
|
||||
continue;
|
||||
}
|
||||
- if (ref->req == ref)
|
||||
+ if (ref->valid_p_req)
|
||||
continue;
|
||||
|
||||
+ /* Copy the current control value into the request */
|
||||
v4l2_ctrl_lock(ctrl);
|
||||
- if (ref->req) {
|
||||
- ptr_to_ptr(ctrl, ref->req->p_req, ref->p_req);
|
||||
- } else {
|
||||
- ptr_to_ptr(ctrl, ctrl->p_cur, ref->p_req);
|
||||
- /*
|
||||
- * Set ref->req to ensure that when userspace wants to
|
||||
- * obtain the controls of this request it will take
|
||||
- * this value and not the current value of the control.
|
||||
- */
|
||||
- ref->req = ref;
|
||||
- }
|
||||
+ cur_to_req(ref);
|
||||
v4l2_ctrl_unlock(ctrl);
|
||||
}
|
||||
|
||||
@@ -4779,7 +4768,7 @@ int v4l2_ctrl_request_setup(struct media_request *req,
|
||||
struct v4l2_ctrl_ref *r =
|
||||
find_ref(hdl, master->cluster[i]->id);
|
||||
|
||||
- if (r->req && r == r->req) {
|
||||
+ if (r->valid_p_req) {
|
||||
have_new_data = true;
|
||||
break;
|
||||
}
|
||||
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
|
||||
index c1d20bd8f25f..a5953b812878 100644
|
||||
--- a/include/media/v4l2-ctrls.h
|
||||
+++ b/include/media/v4l2-ctrls.h
|
||||
@@ -304,12 +304,14 @@ struct v4l2_ctrl {
|
||||
* the control has been applied. This prevents applying controls
|
||||
* from a cluster with multiple controls twice (when the first
|
||||
* control of a cluster is applied, they all are).
|
||||
- * @req: If set, this refers to another request that sets this control.
|
||||
+ * @valid_p_req: If set, then p_req contains the control value for the request.
|
||||
* @p_req: If the control handler containing this control reference
|
||||
* is bound to a media request, then this points to the
|
||||
- * value of the control that should be applied when the request
|
||||
+ * value of the control that must be applied when the request
|
||||
* is executed, or to the value of the control at the time
|
||||
- * that the request was completed.
|
||||
+ * that the request was completed. If @valid_p_req is false,
|
||||
+ * then this control was never set for this request and the
|
||||
+ * control will not be updated when this request is applied.
|
||||
*
|
||||
* Each control handler has a list of these refs. The list_head is used to
|
||||
* keep a sorted-by-control-ID list of all controls, while the next pointer
|
||||
@@ -322,7 +324,7 @@ struct v4l2_ctrl_ref {
|
||||
struct v4l2_ctrl_helper *helper;
|
||||
bool from_other_dev;
|
||||
bool req_done;
|
||||
- struct v4l2_ctrl_ref *req;
|
||||
+ bool valid_p_req;
|
||||
union v4l2_ctrl_ptr p_req;
|
||||
};
|
||||
|
||||
@@ -349,7 +351,7 @@ struct v4l2_ctrl_ref {
|
||||
* @error: The error code of the first failed control addition.
|
||||
* @request_is_queued: True if the request was queued.
|
||||
* @requests: List to keep track of open control handler request objects.
|
||||
- * For the parent control handler (@req_obj.req == NULL) this
|
||||
+ * For the parent control handler (@req_obj.ops == NULL) this
|
||||
* is the list header. When the parent control handler is
|
||||
* removed, it has to unbind and put all these requests since
|
||||
* they refer to the parent.
|
||||
--
|
||||
2.31.1
|
||||
|
@ -451,94 +451,6 @@ index db6ea48e21f9..1e2a4de941aa 100644
|
||||
|
||||
ktime_t busy_time;
|
||||
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Boris Brezillon <boris.brezillon@collabora.com>
|
||||
Date: Fri, 5 Feb 2021 12:17:55 +0100
|
||||
Subject: [PATCH] drm/panfrost: Clear MMU irqs before handling the fault
|
||||
|
||||
When a fault is handled it will unblock the GPU which will continue
|
||||
executing its shader and might fault almost immediately on a different
|
||||
page. If we clear interrupts after handling the fault we might miss new
|
||||
faults, so clear them before.
|
||||
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Fixes: 187d2929206e ("drm/panfrost: Add support for GPU heap allocations")
|
||||
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
|
||||
Reviewed-by: Steven Price <steven.price@arm.com>
|
||||
---
|
||||
drivers/gpu/drm/panfrost/panfrost_mmu.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
|
||||
index be8d68fb0e11..e5f7f647430f 100644
|
||||
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
|
||||
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
|
||||
@@ -600,6 +600,8 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
|
||||
access_type = (fault_status >> 8) & 0x3;
|
||||
source_id = (fault_status >> 16);
|
||||
|
||||
+ mmu_write(pfdev, MMU_INT_CLEAR, mask);
|
||||
+
|
||||
/* Page fault only */
|
||||
ret = -1;
|
||||
if ((status & mask) == BIT(i) && (exception_type & 0xF8) == 0xC0)
|
||||
@@ -623,8 +625,6 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
|
||||
access_type, access_type_name(pfdev, fault_status),
|
||||
source_id);
|
||||
|
||||
- mmu_write(pfdev, MMU_INT_CLEAR, mask);
|
||||
-
|
||||
status &= ~mask;
|
||||
}
|
||||
|
||||
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Boris Brezillon <boris.brezillon@collabora.com>
|
||||
Date: Fri, 5 Feb 2021 12:17:56 +0100
|
||||
Subject: [PATCH] drm/panfrost: Don't try to map pages that are already mapped
|
||||
|
||||
We allocate 2MB chunks at a time, so it might appear that a page fault
|
||||
has already been handled by a previous page fault when we reach
|
||||
panfrost_mmu_map_fault_addr(). Bail out in that case to avoid mapping the
|
||||
same area twice.
|
||||
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Fixes: 187d2929206e ("drm/panfrost: Add support for GPU heap allocations")
|
||||
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
|
||||
Reviewed-by: Steven Price <steven.price@arm.com>
|
||||
---
|
||||
drivers/gpu/drm/panfrost/panfrost_mmu.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
|
||||
index e5f7f647430f..198686216317 100644
|
||||
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
|
||||
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
|
||||
@@ -495,8 +495,14 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
|
||||
}
|
||||
bo->base.pages = pages;
|
||||
bo->base.pages_use_count = 1;
|
||||
- } else
|
||||
+ } else {
|
||||
pages = bo->base.pages;
|
||||
+ if (pages[page_offset]) {
|
||||
+ /* Pages are already mapped, bail out. */
|
||||
+ mutex_unlock(&bo->base.pages_lock);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
mapping = bo->base.base.filp->f_mapping;
|
||||
mapping_set_unevictable(mapping);
|
||||
@@ -529,6 +535,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
|
||||
|
||||
dev_dbg(pfdev->dev, "mapped page fault @ AS%d %llx", as, addr);
|
||||
|
||||
+out:
|
||||
panfrost_gem_mapping_put(bomapping);
|
||||
|
||||
return 0;
|
||||
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Boris Brezillon <boris.brezillon@collabora.com>
|
||||
Date: Fri, 5 Feb 2021 12:17:57 +0100
|
||||
|
Loading…
x
Reference in New Issue
Block a user