Hey,

Op 27-07-18 om 12:12 schreef Satendra Singh Thakur:
> Following changes are done to this func:
> 1. Currently there are many redundant error checks for
> count_connectors, mode, fb and mode_valid.
> if (crtc_req->mode_valid)
> if (crtc_req->count_connectors == 0 && mode)
> if (crtc_req->count_connectors > 0 && (!mode || !fb))
> if (crtc_req->count_connectors > 0)
> if (crtc_req->count_connectors > config->num_connector)
>
> These 5 checks are replaced by just 2 checks.
> if (!crtc_req->mode_valid)
> if (!crtc_req->count_connectors ||
> crtc_req->count_connectors > config->num_connector)

>
> 2. Also, currently, if user pass invalid args
> count_connectors=0, mode=NULL, fb=NULL, code wont throw
> any errors and eventually __drm_mode_set_config_internal
> will be called.
> With the modified code, this will be taken care.
>
> 3. Also, these error checks alongwith following
> if (!file_priv->aspect_ratio_allowed &&
> (crtc_req->mode.flags & DRM_MODE_FLAG_PIC_AR_MASK)
>
> has been  moved  before taking mutex and modeset lock
> because they don't need any lock. Moreover, after grabbing locks,
> if its found that user supplied  invalid args, it will
> be too late as getting lock may require considerable time.
>
> 4. Also, if modeset_lock is tried many times in case of EDEADLK
> error, then this will be the code flow
>
> retry:
>       ret = drm_modeset_lock_all_ctx(crtc->dev, &ctx);
>
> if (ret)-->this is true
>               goto out;
>
> out:
>       if (fb)
>       if (connector_set)
>       drm_mode_destroy(dev, mode);
>       if (ret == -EDEADLK)
>               goto retry;
> It can be observed that checks on fb, connector_set and call to
> mode_destroy are redundant in retry-case.
> If we keep if (ret == -EDEADLK) just after out:,
> that will avoid redundant checks.
>
> In the normal case (non-retry), all checks will be required.
> Thus shifting of if (ret == -EDEADLK) right after out label
> won't affect normal case.
>
> 5. Also, kfree is moved inside if (connector_set).
> 6. Also, if major error checks are in the beginning of the func
> and if user supplied invalid params,  we will exit the func sooner
> without wasting much effort in finding crtc and framebuffer etc.
>
> Signed-off-by: Satendra Singh Thakur <satendr...@samsung.com>
> ---
>  drivers/gpu/drm/drm_crtc.c | 207 
> +++++++++++++++++++++------------------------
>  1 file changed, 98 insertions(+), 109 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 98a36e6..15927e7 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -578,7 +578,25 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
>        */
>       if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)
>               return -ERANGE;
> -
> +     if (!file_priv->aspect_ratio_allowed &&
> +             (crtc_req->mode.flags & DRM_MODE_FLAG_PIC_AR_MASK) !=
> +             DRM_MODE_FLAG_PIC_AR_NONE) {
> +             DRM_DEBUG_KMS("Unexpected aspect-ratio flag bits\n");
> +             return -EINVAL;
> +     }
> +     /* Check if the flag is set*/
> +     if (!crtc_req->mode_valid) {
> +             DRM_DEBUG_KMS("mode_valid flag [%d] is not set\n",
> +             crtc_req->mode_valid);
> +             return -EINVAL;
> +     }
It is allowed to pass crtc_id, mode_valid = false and count_connectors == 0, 
you're missing this check now.
It's used to disable a crtc:

https://cgit.freedesktop.org/drm/igt-gpu-tools/tree/lib/igt_kms.c#n1452


> +     /* Check the validity of count_connectors supplied by user */
> +     if (!crtc_req->count_connectors ||
> +             crtc_req->count_connectors > config->num_connector) {
> +             DRM_DEBUG_KMS("Invalid connectors' count %d\n",
> +             crtc_req->count_connectors);
> +             return -EINVAL;
> +     }
>       crtc = drm_crtc_find(dev, file_priv, crtc_req->crtc_id);
>       if (!crtc) {
>               DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
> @@ -595,134 +613,105 @@ int drm_mode_setcrtc(struct drm_device *dev, void 
> *data,
>       if (ret)
>               goto out;
>  
> -     if (crtc_req->mode_valid) {
> -             /* If we have a mode we need a framebuffer. */
> -             /* If we pass -1, set the mode with the currently bound fb */
> -             if (crtc_req->fb_id == -1) {
> -                     struct drm_framebuffer *old_fb;
> +     /* If we have a mode we need a framebuffer. */
> +     /* If we pass -1, set the mode with the currently bound fb */
> +     if (crtc_req->fb_id == -1) {
> +             struct drm_framebuffer *old_fb;
>  
> -                     if (plane->state)
> -                             old_fb = plane->state->fb;
> -                     else
> -                             old_fb = plane->fb;
> +             if (plane->state)
> +                     old_fb = plane->state->fb;
> +             else
> +                     old_fb = plane->fb;
>  
> -                     if (!old_fb) {
> -                             DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
> -                             ret = -EINVAL;
> -                             goto out;
> -                     }
> -
> -                     fb = old_fb;
> -                     /* Make refcounting symmetric with the lookup path. */
> -                     drm_framebuffer_get(fb);
> -             } else {
> -                     fb = drm_framebuffer_lookup(dev, file_priv, 
> crtc_req->fb_id);
> -                     if (!fb) {
> -                             DRM_DEBUG_KMS("Unknown FB ID%d\n",
> -                                             crtc_req->fb_id);
> -                             ret = -ENOENT;
> -                             goto out;
> -                     }
> -             }
> -
> -             mode = drm_mode_create(dev);
> -             if (!mode) {
> -                     ret = -ENOMEM;
> -                     goto out;
> -             }
> -             if (!file_priv->aspect_ratio_allowed &&
> -                 (crtc_req->mode.flags & DRM_MODE_FLAG_PIC_AR_MASK) != 
> DRM_MODE_FLAG_PIC_AR_NONE) {
> -                     DRM_DEBUG_KMS("Unexpected aspect-ratio flag bits\n");
> +             if (!old_fb) {
> +                     DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
>                       ret = -EINVAL;
>                       goto out;
>               }
>  
> -
> -             ret = drm_mode_convert_umode(dev, mode, &crtc_req->mode);
> -             if (ret) {
> -                     DRM_DEBUG_KMS("Invalid mode\n");
> +             fb = old_fb;
> +             /* Make refcounting symmetric with the lookup path. */
> +             drm_framebuffer_get(fb);
> +     } else {
> +             fb = drm_framebuffer_lookup(dev, file_priv, crtc_req->fb_id);
> +             if (!fb) {
> +                     DRM_DEBUG_KMS("Unknown FB ID%d\n",
> +                                     crtc_req->fb_id);
> +                     ret = -ENOENT;
>                       goto out;
>               }
> -
> -             /*
> -              * Check whether the primary plane supports the fb pixel format.
> -              * Drivers not implementing the universal planes API use a
> -              * default formats list provided by the DRM core which doesn't
> -              * match real hardware capabilities. Skip the check in that
> -              * case.
> -              */
> -             if (!plane->format_default) {
> -                     ret = drm_plane_check_pixel_format(plane,
> -                                                        fb->format->format,
> -                                                        fb->modifier);
> -                     if (ret) {
> -                             struct drm_format_name_buf format_name;
> -                             DRM_DEBUG_KMS("Invalid pixel format %s, 
> modifier 0x%llx\n",
> -                                           
> drm_get_format_name(fb->format->format,
> -                                                               &format_name),
> -                                           fb->modifier);
> -                             goto out;
> -                     }
> -             }
> -
> -             ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
> -                                           mode, fb);
> -             if (ret)
> -                     goto out;
> -
>       }
>  
> -     if (crtc_req->count_connectors == 0 && mode) {
> -             DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
> -             ret = -EINVAL;
> +     mode = drm_mode_create(dev);
> +     if (!mode) {
> +             ret = -ENOMEM;
>               goto out;
>       }
>  
> -     if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
> -             DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
> -                       crtc_req->count_connectors);
> -             ret = -EINVAL;
> +     ret = drm_mode_convert_umode(dev, mode, &crtc_req->mode);
> +     if (ret) {
> +             DRM_DEBUG_KMS("Invalid mode\n");
>               goto out;
>       }
>  
> -     if (crtc_req->count_connectors > 0) {
> -             u32 out_id;
> +     /*
> +      * Check whether the primary plane supports the fb pixel format.
> +      * Drivers not implementing the universal planes API use a
> +      * default formats list provided by the DRM core which doesn't
> +      * match real hardware capabilities. Skip the check in that
> +      * case.
> +      */
> +     if (!plane->format_default) {
> +             ret = drm_plane_check_pixel_format(plane,
> +                                                fb->format->format,
> +                                                fb->modifier);
> +             if (ret) {
> +                     struct drm_format_name_buf format_name;
>  
> -             /* Avoid unbounded kernel memory allocation */
> -             if (crtc_req->count_connectors > config->num_connector) {
> -                     ret = -EINVAL;
> +                     DRM_DEBUG_KMS("Invalid pixel format %s, modifier 
> 0x%llx\n",
> +                                   drm_get_format_name(fb->format->format,
> +                                                       &format_name),
> +                                   fb->modifier);
>                       goto out;
>               }
> +     }
>  
> -             connector_set = kmalloc_array(crtc_req->count_connectors,
> +     ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
> +                                   mode, fb);
> +     if (ret)
> +             goto out;
> +
> +     connector_set = kmalloc_array(crtc_req->count_connectors,
>                                             sizeof(struct drm_connector *),
>                                             GFP_KERNEL);
> -             if (!connector_set) {
> -                     ret = -ENOMEM;
> -                     goto out;
> -             }
> +     if (!connector_set) {
> +             ret = -ENOMEM;
> +             goto out;
> +     }
>  
> -             for (i = 0; i < crtc_req->count_connectors; i++) {
> -                     connector_set[i] = NULL;
> -                     set_connectors_ptr = (uint32_t __user *)(unsigned 
> long)crtc_req->set_connectors_ptr;
> -                     if (get_user(out_id, &set_connectors_ptr[i])) {
> -                             ret = -EFAULT;
> -                             goto out;
> -                     }
> +     for (i = 0; i < crtc_req->count_connectors; i++) {
> +             u32 out_id;
>  
> -                     connector = drm_connector_lookup(dev, file_priv, 
> out_id);
> -                     if (!connector) {
> -                             DRM_DEBUG_KMS("Connector id %d unknown\n",
> -                                             out_id);
> -                             ret = -ENOENT;
> -                             goto out;
> -                     }
> -                     DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
> -                                     connector->base.id,
> -                                     connector->name);
> +             connector_set[i] = NULL;
> +             set_connectors_ptr =
> +             (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
> +             if (get_user(out_id, &set_connectors_ptr[i])) {
> +                     ret = -EFAULT;
> +                     goto out;
> +             }
>  
> -                     connector_set[i] = connector;
> +             connector = drm_connector_lookup(dev, file_priv, out_id);
> +             if (!connector) {
> +                     DRM_DEBUG_KMS("Connector id %d unknown\n",
> +                                     out_id);
> +                     ret = -ENOENT;
> +                     goto out;
>               }
> +             DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
> +                             connector->base.id,
> +                             connector->name);
> +
> +             connector_set[i] = connector;
>       }
>  
>       set.crtc = crtc;
> @@ -735,6 +724,11 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
>       ret = __drm_mode_set_config_internal(&set, &ctx);
>  
>  out:
> +     if (ret == -EDEADLK) {
> +             ret = drm_modeset_backoff(&ctx);
> +             if (!ret)
> +                     goto retry;
> +     }
>       if (fb)
>               drm_framebuffer_put(fb);
>  
> @@ -743,14 +737,9 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
>                       if (connector_set[i])
>                               drm_connector_put(connector_set[i]);
>               }
> +             kfree(connector_set);
>       }
> -     kfree(connector_set);
>       drm_mode_destroy(dev, mode);
> -     if (ret == -EDEADLK) {
> -             ret = drm_modeset_backoff(&ctx);
> -             if (!ret)
> -                     goto retry;
> -     }
>       drm_modeset_drop_locks(&ctx);
>       drm_modeset_acquire_fini(&ctx);
>       mutex_unlock(&crtc->dev->mode_config.mutex);


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to