bcm27xx: add kernel 5.10 support
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-5.10 / 950-0477-staging-rpivid-Fix-crash-when-CMA-alloc-fails.patch
1 From 8ae4692aefa338ae3fff89c513fddd0400ea7a2a Mon Sep 17 00:00:00 2001
2 From: John Cox <jc@kynesim.co.uk>
3 Date: Mon, 8 Feb 2021 16:01:37 +0000
4 Subject: [PATCH] staging: rpivid: Fix crash when CMA alloc fails
5
6 If realloc to increase coeff size fails then attempt to re-allocate
7 the original size. If that also fails then flag a fatal error to abort
8 all further decode.
9
10 Signed-off-by: John Cox <jc@kynesim.co.uk>
11 ---
12 drivers/staging/media/rpivid/rpivid.h | 3 ++
13 drivers/staging/media/rpivid/rpivid_h265.c | 44 +++++++++++++++++++++-
14 2 files changed, 45 insertions(+), 2 deletions(-)
15
16 --- a/drivers/staging/media/rpivid/rpivid.h
17 +++ b/drivers/staging/media/rpivid/rpivid.h
18 @@ -88,6 +88,9 @@ struct rpivid_ctx {
19 struct v4l2_pix_format src_fmt;
20 struct v4l2_pix_format dst_fmt;
21 int dst_fmt_set;
22 + // fatal_err is set if an error has occurred s.t. decode cannot
23 + // continue (such as running out of CMA)
24 + int fatal_err;
25
26 struct v4l2_ctrl_handler hdl;
27 struct v4l2_ctrl **ctrls;
28 --- a/drivers/staging/media/rpivid/rpivid_h265.c
29 +++ b/drivers/staging/media/rpivid/rpivid_h265.c
30 @@ -73,10 +73,18 @@ static void gptr_free(struct rpivid_dev
31 gptr->attrs = 0;
32 }
33
34 -/* Realloc but do not copy */
35 +/* Realloc but do not copy
36 + *
37 + * Frees then allocs.
38 + * If the alloc fails then it attempts to re-allocote the old size
39 + * On error then check gptr->ptr to determine if anything is currently
40 + * allocated.
41 + */
42 static int gptr_realloc_new(struct rpivid_dev * const dev,
43 struct rpivid_gptr * const gptr, size_t size)
44 {
45 + const size_t old_size = gptr->size;
46 +
47 if (size == gptr->size)
48 return 0;
49
50 @@ -88,7 +96,21 @@ static int gptr_realloc_new(struct rpivi
51 gptr->size = size;
52 gptr->ptr = dma_alloc_attrs(dev->dev, gptr->size,
53 &gptr->addr, GFP_KERNEL, gptr->attrs);
54 - return gptr->ptr ? 0 : -ENOMEM;
55 +
56 + if (!gptr->ptr) {
57 + gptr->addr = 0;
58 + gptr->size = old_size;
59 + gptr->ptr = dma_alloc_attrs(dev->dev, gptr->size,
60 + &gptr->addr, GFP_KERNEL, gptr->attrs);
61 + if (!gptr->ptr) {
62 + gptr->size = 0;
63 + gptr->addr = 0;
64 + gptr->attrs = 0;
65 + }
66 + return -ENOMEM;
67 + }
68 +
69 + return 0;
70 }
71
72 /* floor(log2(x)) */
73 @@ -2020,6 +2042,12 @@ static void phase1_thread(struct rpivid_
74 return;
75
76 fail:
77 + if (!pu_gptr->addr || !coeff_gptr->addr) {
78 + v4l2_err(&dev->v4l2_dev,
79 + "%s: Fatal: failed to reclaim old alloc\n",
80 + __func__);
81 + ctx->fatal_err = 1;
82 + }
83 dec_env_delete(de);
84 xtrace_fin(dev, de);
85 v4l2_m2m_buf_done_and_job_finish(dev->m2m_dev, ctx->fh.m2m_ctx,
86 @@ -2093,6 +2121,9 @@ static void phase1_claimed(struct rpivid
87
88 xtrace_in(dev, de);
89
90 + if (ctx->fatal_err)
91 + goto fail;
92 +
93 de->pu_base_vc = pu_gptr->addr;
94 de->pu_stride =
95 ALIGN_DOWN(pu_gptr->size / de->pic_height_in_ctbs_y, 64);
96 @@ -2116,6 +2147,14 @@ static void phase1_claimed(struct rpivid
97 apb_write_vc_addr_final(dev, RPI_CFBASE, de->cmd_copy_gptr->addr);
98
99 xtrace_ok(dev, de);
100 + return;
101 +
102 +fail:
103 + dec_env_delete(de);
104 + xtrace_fin(dev, de);
105 + v4l2_m2m_buf_done_and_job_finish(dev->m2m_dev, ctx->fh.m2m_ctx,
106 + VB2_BUF_STATE_ERROR);
107 + xtrace_fail(dev, de);
108 }
109
110 static void dec_state_delete(struct rpivid_ctx *const ctx)
111 @@ -2186,6 +2225,7 @@ static int rpivid_h265_start(struct rpiv
112 v4l2_info(&dev->v4l2_dev, "%s: (%dx%d)\n", __func__,
113 ctx->dst_fmt.width, ctx->dst_fmt.height);
114
115 + ctx->fatal_err = 0;
116 ctx->dec0 = NULL;
117 ctx->state = kzalloc(sizeof(*ctx->state), GFP_KERNEL);
118 if (!ctx->state) {