diff options
author | Tomasz Figa <tfiga@chromium.org> | 2017-06-19 00:53:43 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-06-20 09:11:48 -0300 |
commit | 758d90e161382c134b7cbd5f724df4de02f3c67e (patch) | |
tree | b2e6d2940b2f6b161560d2d2fbeafeb78e7cfac3 /drivers/media/v4l2-core/v4l2-subdev.c | |
parent | d295c6a460cd2ac63597691288ed044f5cfa8a6e (diff) | |
download | linux-758d90e161382c134b7cbd5f724df4de02f3c67e.tar.bz2 |
[media] v4l2-core: Use kvmalloc() for potentially big allocations
There are multiple places where arrays or otherwise variable sized
buffer are allocated through V4L2 core code, including things like
controls, memory pages, staging buffers for ioctls and so on. Such
allocations can potentially require an order > 0 allocation from the
page allocator, which is not guaranteed to be fulfilled and is likely to
fail on a system with severe memory fragmentation (e.g. a system with
very long uptime).
Since the memory being allocated is intended to be used by the CPU
exclusively, we can consider using vmalloc() as a fallback and this is
exactly what the recently merged kvmalloc() helpers do. A kmalloc() call
is still attempted, even for order > 0 allocations, but it is done
with __GFP_NORETRY and __GFP_NOWARN, with expectation of failing if
requested memory is not available instantly. Only then the vmalloc()
fallback is used. This should give us fast and more reliable allocations
even on systems with higher memory pressure and/or more fragmentation,
while still retaining the same performance level on systems not
suffering from such conditions.
While at it, replace explicit array size calculations on changed
allocations with kvmalloc_array().
Purposedly not touching videobuf1, as it is deprecated, has only few
users remaining and would rather be seen removed instead.
Signed-off-by: Tomasz Figa <tfiga@chromium.org>
Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-subdev.c')
-rw-r--r-- | drivers/media/v4l2-core/v4l2-subdev.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index da78497ae5ed..43fefa73e0a3 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -17,6 +17,7 @@ */ #include <linux/ioctl.h> +#include <linux/mm.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/videodev2.h> @@ -577,13 +578,14 @@ v4l2_subdev_alloc_pad_config(struct v4l2_subdev *sd) if (!sd->entity.num_pads) return NULL; - cfg = kcalloc(sd->entity.num_pads, sizeof(*cfg), GFP_KERNEL); + cfg = kvmalloc_array(sd->entity.num_pads, sizeof(*cfg), + GFP_KERNEL | __GFP_ZERO); if (!cfg) return NULL; ret = v4l2_subdev_call(sd, pad, init_cfg, cfg); if (ret < 0 && ret != -ENOIOCTLCMD) { - kfree(cfg); + kvfree(cfg); return NULL; } @@ -593,7 +595,7 @@ EXPORT_SYMBOL_GPL(v4l2_subdev_alloc_pad_config); void v4l2_subdev_free_pad_config(struct v4l2_subdev_pad_config *cfg) { - kfree(cfg); + kvfree(cfg); } EXPORT_SYMBOL_GPL(v4l2_subdev_free_pad_config); #endif /* CONFIG_MEDIA_CONTROLLER */ |