Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: v4l: subdev: Add len_routes field to struct v4l2_subdev_routing

The len_routes field is used to tell the size of the routes array in
struct v4l2_subdev_routing. This way the number of routes returned from
S_ROUTING IOCTL may be larger than the number of routes provided, in case
there are more routes returned by the driver.

Note that this uAPI is still disabled in the code, so this change can
safely be done. Anyone who manually patched the code to enable this uAPI
must update their code.

The patch also increases the number of reserved fields in struct
v4l2_subdev_routing.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>

authored by

Sakari Ailus and committed by
Hans Verkuil
83a22a07 38c84932

+48 -24
+31 -13
Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst
··· 43 43 Drivers report their current routing tables using the 44 44 ``VIDIOC_SUBDEV_G_ROUTING`` ioctl and application may enable or disable routes 45 45 with the ``VIDIOC_SUBDEV_S_ROUTING`` ioctl, by adding or removing routes and 46 - setting or clearing flags of the ``flags`` field of a 47 - struct :c:type:`v4l2_subdev_route`. 46 + setting or clearing flags of the ``flags`` field of a struct 47 + :c:type:`v4l2_subdev_route`. 48 48 49 - All stream configurations are reset when ``VIDIOC_SUBDEV_S_ROUTING`` is called. This 50 - means that the userspace must reconfigure all streams after calling the ioctl 51 - with e.g. ``VIDIOC_SUBDEV_S_FMT``. 49 + All stream configurations are reset when ``VIDIOC_SUBDEV_S_ROUTING`` is called. 50 + This means that the userspace must reconfigure all stream formats and selections 51 + after calling the ioctl with e.g. ``VIDIOC_SUBDEV_S_FMT``. 52 52 53 53 Only subdevices which have both sink and source pads can support routing. 54 54 55 - When inspecting routes through ``VIDIOC_SUBDEV_G_ROUTING`` and the application 56 - provided ``num_routes`` is not big enough to contain all the available routes 57 - the subdevice exposes, drivers return the ENOSPC error code and adjust the 58 - value of the ``num_routes`` field. Application should then reserve enough memory 59 - for all the route entries and call ``VIDIOC_SUBDEV_G_ROUTING`` again. 55 + The ``len_routes`` field indicates the number of routes that can fit in the 56 + ``routes`` array allocated by userspace. It is set by applications for both 57 + ioctls to indicate how many routes the kernel can return, and is never modified 58 + by the kernel. 60 59 61 - On a successful ``VIDIOC_SUBDEV_G_ROUTING`` call the driver updates the 62 - ``num_routes`` field to reflect the actual number of routes returned. 60 + The ``num_routes`` field indicates the number of routes in the routing 61 + table. For ``VIDIOC_SUBDEV_S_ROUTING``, it is set by userspace to the number of 62 + routes that the application stored in the ``routes`` array. For both ioctls, it 63 + is returned by the kernel and indicates how many routes are stored in the 64 + subdevice routing table. This may be smaller or larger than the value of 65 + ``num_routes`` set by the application for ``VIDIOC_SUBDEV_S_ROUTING``, as 66 + drivers may adjust the requested routing table. 67 + 68 + The kernel can return a ``num_routes`` value larger than ``len_routes`` from 69 + both ioctls. This indicates thare are more routes in the routing table than fits 70 + the ``routes`` array. In this case, the ``routes`` array is filled by the kernel 71 + with the first ``len_routes`` entries of the subdevice routing table. This is 72 + not considered to be an error, and the ioctl call succeeds. If the applications 73 + wants to retrieve the missing routes, it can issue a new 74 + ``VIDIOC_SUBDEV_G_ROUTING`` call with a large enough ``routes`` array. 75 + 76 + ``VIDIOC_SUBDEV_S_ROUTING`` may return more routes than the user provided in 77 + ``num_routes`` field due to e.g. hardware properties. 63 78 64 79 .. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}| 65 80 ··· 89 74 - ``which`` 90 75 - Routing table to be accessed, from enum 91 76 :ref:`v4l2_subdev_format_whence <v4l2-subdev-format-whence>`. 77 + * - __u32 78 + - ``len_routes`` 79 + - The length of the array (as in memory reserved for the array) 92 80 * - struct :c:type:`v4l2_subdev_route` 93 81 - ``routes[]`` 94 82 - Array of struct :c:type:`v4l2_subdev_route` entries ··· 99 81 - ``num_routes`` 100 82 - Number of entries of the routes array 101 83 * - __u32 102 - - ``reserved``\ [5] 84 + - ``reserved``\ [11] 103 85 - Reserved for future extensions. Applications and drivers must set 104 86 the array to zero. 105 87
+2 -2
drivers/media/v4l2-core/v4l2-ioctl.c
··· 3201 3201 case VIDIOC_SUBDEV_S_ROUTING: { 3202 3202 struct v4l2_subdev_routing *routing = parg; 3203 3203 3204 - if (routing->num_routes > 256) 3204 + if (routing->len_routes > 256) 3205 3205 return -E2BIG; 3206 3206 3207 3207 *user_ptr = u64_to_user_ptr(routing->routes); 3208 3208 *kernel_ptr = (void **)&routing->routes; 3209 3209 *array_size = sizeof(struct v4l2_subdev_route) 3210 - * routing->num_routes; 3210 + * routing->len_routes; 3211 3211 ret = 1; 3212 3212 break; 3213 3213 }
+6 -6
drivers/media/v4l2-core/v4l2-subdev.c
··· 960 960 961 961 krouting = &state->routing; 962 962 963 - if (routing->num_routes < krouting->num_routes) { 964 - routing->num_routes = krouting->num_routes; 965 - return -ENOSPC; 966 - } 967 - 968 963 memcpy((struct v4l2_subdev_route *)(uintptr_t)routing->routes, 969 964 krouting->routes, 970 - krouting->num_routes * sizeof(*krouting->routes)); 965 + min(krouting->num_routes, routing->len_routes) * 966 + sizeof(*krouting->routes)); 971 967 routing->num_routes = krouting->num_routes; 972 968 973 969 return 0; ··· 984 988 985 989 if (routing->which != V4L2_SUBDEV_FORMAT_TRY && ro_subdev) 986 990 return -EPERM; 991 + 992 + if (routing->num_routes > routing->len_routes) 993 + return -EINVAL; 987 994 988 995 memset(routing->reserved, 0, sizeof(routing->reserved)); 989 996 ··· 1014 1015 } 1015 1016 1016 1017 krouting.num_routes = routing->num_routes; 1018 + krouting.len_routes = routing->len_routes; 1017 1019 krouting.routes = routes; 1018 1020 1019 1021 return v4l2_subdev_call(sd, pad, set_routing, state,
+2
include/media/v4l2-subdev.h
··· 714 714 /** 715 715 * struct v4l2_subdev_krouting - subdev routing table 716 716 * 717 + * @len_routes: length of routes array, in routes 717 718 * @num_routes: number of routes 718 719 * @routes: &struct v4l2_subdev_route 719 720 * 720 721 * This structure contains the routing table for a subdev. 721 722 */ 722 723 struct v4l2_subdev_krouting { 724 + unsigned int len_routes; 723 725 unsigned int num_routes; 724 726 struct v4l2_subdev_route *routes; 725 727 };
+7 -3
include/uapi/linux/v4l2-subdev.h
··· 228 228 * struct v4l2_subdev_routing - Subdev routing information 229 229 * 230 230 * @which: configuration type (from enum v4l2_subdev_format_whence) 231 - * @num_routes: the total number of routes in the routes array 231 + * @len_routes: the length of the routes array, in routes; set by the user, not 232 + * modified by the kernel 232 233 * @routes: pointer to the routes array 234 + * @num_routes: the total number of routes, possibly more than fits in the 235 + * routes array 233 236 * @reserved: drivers and applications must zero this array 234 237 */ 235 238 struct v4l2_subdev_routing { 236 239 __u32 which; 237 - __u32 num_routes; 240 + __u32 len_routes; 238 241 __u64 routes; 239 - __u32 reserved[6]; 242 + __u32 num_routes; 243 + __u32 reserved[11]; 240 244 }; 241 245 242 246 /*