[PATCH 2/6] drm/exynos: ipp: Add IPP v2 framework
Marek Szyprowski
m.szyprowski at samsung.com
Wed Sep 13 06:08:32 UTC 2017
Hi Emil,
On 2017-09-12 17:02, Emil Velikov wrote:
> Hi Marek,
>
> Just a couple of small suggestions - this is by no means a proper review.
Thanks, I really appreciate your suggestions! I've tried to make userspace
API 32/64bit agnostic, but it looks that I still need to learn a bit in this
area.
> 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
>
>
>
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
More information about the dri-devel
mailing list