]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
media: staging/intel-ipu3-v4l: reduce kernel stack usage
authorArnd Bergmann <arnd@arndb.de>
Mon, 4 Mar 2019 20:28:42 +0000 (15:28 -0500)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Wed, 20 Mar 2019 10:30:17 +0000 (06:30 -0400)
The v4l2_pix_format_mplane structure is too large to be put on the kernel
stack, as we can see in 32-bit builds:

drivers/staging/media/ipu3/ipu3-v4l2.c: In function 'imgu_fmt':
drivers/staging/media/ipu3/ipu3-v4l2.c:753:1: error: the frame size of 1028 bytes is larger than 1024 bytes [-Werror=frame-larger-than=]

By dynamically allocating this array, the stack usage goes down to an
acceptable 272 bytes for the same x86-32 configuration.

Fixes: a0ca1627b450 ("media: staging/intel-ipu3: Add v4l2 driver based on media framework")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/staging/media/ipu3/ipu3-v4l2.c

index 9c0352b193a7ee1a599d33472afa9c4ccbf0c3dd..c34b433539c4cd36306ee5fdc06d263085645011 100644 (file)
@@ -664,12 +664,11 @@ static int imgu_fmt(struct imgu_device *imgu, unsigned int pipe, int node,
                    struct v4l2_format *f, bool try)
 {
        struct device *dev = &imgu->pci_dev->dev;
-       struct v4l2_pix_format_mplane try_fmts[IPU3_CSS_QUEUES];
        struct v4l2_pix_format_mplane *fmts[IPU3_CSS_QUEUES] = { NULL };
        struct v4l2_rect *rects[IPU3_CSS_RECTS] = { NULL };
        struct v4l2_mbus_framefmt pad_fmt;
        unsigned int i, css_q;
-       int r;
+       int ret;
        struct imgu_css_pipe *css_pipe = &imgu->css.pipes[pipe];
        struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe];
        struct imgu_v4l2_subdev *imgu_sd = &imgu_pipe->imgu_sd;
@@ -698,9 +697,13 @@ static int imgu_fmt(struct imgu_device *imgu, unsigned int pipe, int node,
                        continue;
 
                if (try) {
-                       try_fmts[i] =
-                               imgu_pipe->nodes[inode].vdev_fmt.fmt.pix_mp;
-                       fmts[i] = &try_fmts[i];
+                       fmts[i] = kmemdup(&imgu_pipe->nodes[inode].vdev_fmt.fmt.pix_mp,
+                                         sizeof(struct v4l2_pix_format_mplane),
+                                         GFP_KERNEL);
+                       if (!fmts[i]) {
+                               ret = -ENOMEM;
+                               goto out;
+                       }
                } else {
                        fmts[i] = &imgu_pipe->nodes[inode].vdev_fmt.fmt.pix_mp;
                }
@@ -730,26 +733,33 @@ static int imgu_fmt(struct imgu_device *imgu, unsigned int pipe, int node,
         * before we return success from this function, so set it here.
         */
        css_q = imgu_node_to_queue(node);
-       if (fmts[css_q])
-               *fmts[css_q] = f->fmt.pix_mp;
-       else
-               return -EINVAL;
+       if (!fmts[css_q]) {
+               ret = -EINVAL;
+               goto out;
+       }
+       *fmts[css_q] = f->fmt.pix_mp;
 
        if (try)
-               r = imgu_css_fmt_try(&imgu->css, fmts, rects, pipe);
+               ret = imgu_css_fmt_try(&imgu->css, fmts, rects, pipe);
        else
-               r = imgu_css_fmt_set(&imgu->css, fmts, rects, pipe);
+               ret = imgu_css_fmt_set(&imgu->css, fmts, rects, pipe);
 
-       /* r is the binary number in the firmware blob */
-       if (r < 0)
-               return r;
+       /* ret is the binary number in the firmware blob */
+       if (ret < 0)
+               goto out;
 
        if (try)
                f->fmt.pix_mp = *fmts[css_q];
        else
                f->fmt = imgu_pipe->nodes[node].vdev_fmt.fmt;
 
-       return 0;
+out:
+       if (try) {
+               for (i = 0; i < IPU3_CSS_QUEUES; i++)
+                       kfree(fmts[i]);
+       }
+
+       return ret;
 }
 
 static int imgu_try_fmt(struct file *file, void *fh, struct v4l2_format *f)