[PATCH 2/6] drm/exynos: ipp: Add IPP v2 framework
Emil Velikov
emil.l.velikov at gmail.com
Tue Sep 12 15:02:01 UTC 2017
Hi Marek,
Just a couple of small suggestions - this is by no means a proper review.
On 12 September 2017 at 09:08, Marek Szyprowski
<m.szyprowski at samsung.com> wrote:
> This patch adds Exynos IPP v2 subsystem and userspace API.
>
> New userspace API is focused ONLY on memory-to-memory image processing.
> The two remainging IPP operation modes (framebuffer writeback and
s/remainging/remaining/
> local-path output with image processing) can be implemented using
> standard DRM features: writeback connectors and additional DRM planes with
> scaling features.
>
> V2 IPP userspace API is not compatible with old IPP ioctls. This is a
> significant change, but the old IPP subsystem in mainline Linux kernel was
> partially disfunctional anyway and not used in any open-source project.
>
s/disfunctional/dysfunctional/
> V2 IPP userspace API is based on stateless approach, which much better fits
> to memory-to-memory image processing model. It also provides support for
> all image formats, which are both already defined in DRM API and supported
> by the existing IPP hardware modules.
>
> The API consists of the following ioctls:
> - DRM_IOCTL_EXYNOS_IPP_GET_RESOURCES: to enumerate all available image
> processing modules,
> - DRM_IOCTL_EXYNOS_IPP_GET_CAPS: to query capabilities and supported image
> formats of given IPP module,
> - DRM_IOCTL_EXYNOS_IPP_GET_LIMITS: to query hardware limitiations for
s/limitiations/limitations/
> +int exynos_drm_ipp_get_limits_ioctl(struct drm_device *dev, void *data,
> + struct drm_file *file_priv)
> +{
> + struct drm_exynos_ioctl_ipp_get_limits *resp = data;
> + void __user *ptr = (void __user *)(unsigned long)resp->limits_ptr;
We have the u64_to_user_ptr helper for these casts. Please use it
through the codebase.
> +struct exynos_drm_param_map {
static const?
> + unsigned int id;
> + unsigned int size;
> + unsigned int offset;
> +} exynos_drm_ipp_params_maps[] = {
> + {
> + DRM_EXYNOS_IPP_TASK_BUFFER | DRM_EXYNOS_IPP_TASK_TYPE_SOURCE,
> + sizeof(struct drm_exynos_ipp_task_buffer),
> + offsetof(struct exynos_drm_ipp_task, src.buf),
> + }, {
> + DRM_EXYNOS_IPP_TASK_BUFFER | DRM_EXYNOS_IPP_TASK_TYPE_DESTINATION,
> + sizeof(struct drm_exynos_ipp_task_buffer),
> + offsetof(struct exynos_drm_ipp_task, dst.buf),
> + }, {
> + DRM_EXYNOS_IPP_TASK_RECTANGLE | DRM_EXYNOS_IPP_TASK_TYPE_SOURCE,
> + sizeof(struct drm_exynos_ipp_task_rect),
> + offsetof(struct exynos_drm_ipp_task, src.rect),
> + }, {
> + DRM_EXYNOS_IPP_TASK_RECTANGLE | DRM_EXYNOS_IPP_TASK_TYPE_DESTINATION,
> + sizeof(struct drm_exynos_ipp_task_rect),
> + offsetof(struct exynos_drm_ipp_task, dst.rect),
> + }, {
> + DRM_EXYNOS_IPP_TASK_TRANSFORM,
> + sizeof(struct drm_exynos_ipp_task_transform),
> + offsetof(struct exynos_drm_ipp_task, transform),
> + }, {
> + DRM_EXYNOS_IPP_TASK_ALPHA,
> + sizeof(struct drm_exynos_ipp_task_alpha),
> + offsetof(struct exynos_drm_ipp_task, alpha),
> + },
> +};
> +
> +static int exynos_drm_ipp_task_set(struct exynos_drm_ipp_task *task,
> + struct drm_exynos_ioctl_ipp_commit *arg)
> +{
> + unsigned int size = arg->params_size;
> + void *p, *params;
> + int ret = 0;
> +
> + if (size > PAGE_SIZE)
> + return -ERANGE;
> +
> + p = kmalloc(size, GFP_KERNEL);
> + if (!p)
> + return -ENOMEM;
> +
> + if (copy_from_user(p, (void __user *)(unsigned long)arg->params_ptr,
> + size)) {
> + ret = -EFAULT;
> + DRM_DEBUG_DRIVER("Failed to copy configuration from userspace\n");
> + goto free;
> + }
> +
> + params = p;
> + while (size) {
> + struct exynos_drm_param_map *map = exynos_drm_ipp_params_maps;
I'd just drop this since...
> + u32 *id = params;
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(exynos_drm_ipp_params_maps); i++)
... using ARRAY_SIZE(foo) only to access bar[] is quite misleading.
> + if (map[i].id == *id)
> + break;
> +
> + if (i < ARRAY_SIZE(exynos_drm_ipp_params_maps) &&
> + map[i].size <= size) {
> + memcpy((void *)task + map[i].offset, params,
> + map[i].size);
> + params += map[i].size;
> + size -= map[i].size;
> + } else {
> + ret = -EINVAL;
> + goto free;
> + }
Maybe flip the condition order?
if (!foo)
ret = -EINVAL;
goto xx;
map[i]...
> + }
> +
> + DRM_DEBUG_DRIVER("Got task %pK configuration from userspace\n", task);
> +free:
> + kfree(p);
> + return ret;
> +}
> +
> +
> +struct drm_exynos_ipp_limit_val {
> + __u32 min, max, align;
Having these one per line, will make it harder to miss alignment issues.
> +struct drm_exynos_ipp_limit {
> + __u32 type;
> + struct drm_exynos_ipp_limit_val h;
> + struct drm_exynos_ipp_limit_val v;
If you extend the struct by appending 64bit variable it will break
compat ioctls.
One could add a note/warning above the struct?
> +struct drm_exynos_ipp_task_rect {
> + __u32 id;
> + __u32 x, y, w, h;
Ditto - separate lines, note about future compat ioctl breakage?
HTH
Emil
More information about the dri-devel
mailing list