lkml.org 
[lkml]   [2021]   [Jul]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v7 1/5] drm: avoid circular locks in drm_mode_getconnector
    Date
    In preparation for a future patch to take a lock on
    drm_device.master_mutex inside drm_is_current_master(), we first move
    the call to drm_is_current_master() in drm_mode_getconnector out from the
    section locked by &dev->mode_config.mutex. This avoids creating a
    circular lock dependency.

    Failing to avoid this lock dependency produces the following lockdep
    splat:

    ======================================================
    WARNING: possible circular locking dependency detected
    5.13.0-rc7-CI-CI_DRM_10254+ #1 Not tainted
    ------------------------------------------------------
    kms_frontbuffer/1087 is trying to acquire lock:
    ffff88810dcd01a8 (&dev->master_mutex){+.+.}-{3:3}, at: drm_is_current_master+0x1b/0x40
    but task is already holding lock:
    ffff88810dcd0488 (&dev->mode_config.mutex){+.+.}-{3:3}, at: drm_mode_getconnector+0x1c6/0x4a0
    which lock already depends on the new lock.
    the existing dependency chain (in reverse order) is:
    -> #2 (&dev->mode_config.mutex){+.+.}-{3:3}:
    __mutex_lock+0xab/0x970
    drm_client_modeset_probe+0x22e/0xca0
    __drm_fb_helper_initial_config_and_unlock+0x42/0x540
    intel_fbdev_initial_config+0xf/0x20 [i915]
    async_run_entry_fn+0x28/0x130
    process_one_work+0x26d/0x5c0
    worker_thread+0x37/0x380
    kthread+0x144/0x170
    ret_from_fork+0x1f/0x30
    -> #1 (&client->modeset_mutex){+.+.}-{3:3}:
    __mutex_lock+0xab/0x970
    drm_client_modeset_commit_locked+0x1c/0x180
    drm_client_modeset_commit+0x1c/0x40
    __drm_fb_helper_restore_fbdev_mode_unlocked+0x88/0xb0
    drm_fb_helper_set_par+0x34/0x40
    intel_fbdev_set_par+0x11/0x40 [i915]
    fbcon_init+0x270/0x4f0
    visual_init+0xc6/0x130
    do_bind_con_driver+0x1e5/0x2d0
    do_take_over_console+0x10e/0x180
    do_fbcon_takeover+0x53/0xb0
    register_framebuffer+0x22d/0x310
    __drm_fb_helper_initial_config_and_unlock+0x36c/0x540
    intel_fbdev_initial_config+0xf/0x20 [i915]
    async_run_entry_fn+0x28/0x130
    process_one_work+0x26d/0x5c0
    worker_thread+0x37/0x380
    kthread+0x144/0x170
    ret_from_fork+0x1f/0x30
    -> #0 (&dev->master_mutex){+.+.}-{3:3}:
    __lock_acquire+0x151e/0x2590
    lock_acquire+0xd1/0x3d0
    __mutex_lock+0xab/0x970
    drm_is_current_master+0x1b/0x40
    drm_mode_getconnector+0x37e/0x4a0
    drm_ioctl_kernel+0xa8/0xf0
    drm_ioctl+0x1e8/0x390
    __x64_sys_ioctl+0x6a/0xa0
    do_syscall_64+0x39/0xb0
    entry_SYSCALL_64_after_hwframe+0x44/0xae
    other info that might help us debug this:
    Chain exists of: &dev->master_mutex --> &client->modeset_mutex --> &dev->mode_config.mutex
    Possible unsafe locking scenario:
    CPU0 CPU1
    ---- ----
    lock(&dev->mode_config.mutex);
    lock(&client->modeset_mutex);
    lock(&dev->mode_config.mutex);
    lock(&dev->master_mutex);
    *** DEADLOCK ***
    1 lock held by kms_frontbuffer/1087:
    #0: ffff88810dcd0488 (&dev->mode_config.mutex){+.+.}-{3:3}, at: drm_mode_getconnector+0x1c6/0x4a0
    stack backtrace:
    CPU: 7 PID: 1087 Comm: kms_frontbuffer Not tainted 5.13.0-rc7-CI-CI_DRM_10254+ #1
    Hardware name: Intel Corporation Ice Lake Client Platform/IceLake U DDR4 SODIMM PD RVP TLC, BIOS ICLSFWR1.R00.3234.A01.1906141750 06/14/2019
    Call Trace:
    dump_stack+0x7f/0xad
    check_noncircular+0x12e/0x150
    __lock_acquire+0x151e/0x2590
    lock_acquire+0xd1/0x3d0
    __mutex_lock+0xab/0x970
    drm_is_current_master+0x1b/0x40
    drm_mode_getconnector+0x37e/0x4a0
    drm_ioctl_kernel+0xa8/0xf0
    drm_ioctl+0x1e8/0x390
    __x64_sys_ioctl+0x6a/0xa0
    do_syscall_64+0x39/0xb0
    entry_SYSCALL_64_after_hwframe+0x44/0xae

    Reported-by: Daniel Vetter <daniel.vetter@ffwll.ch>
    Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com>
    Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
    ---
    drivers/gpu/drm/drm_connector.c | 5 ++++-
    1 file changed, 4 insertions(+), 1 deletion(-)

    diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
    index da39e7ff6965..2ba257b1ae20 100644
    --- a/drivers/gpu/drm/drm_connector.c
    +++ b/drivers/gpu/drm/drm_connector.c
    @@ -2414,6 +2414,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
    struct drm_mode_modeinfo u_mode;
    struct drm_mode_modeinfo __user *mode_ptr;
    uint32_t __user *encoder_ptr;
    + bool is_current_master;

    if (!drm_core_check_feature(dev, DRIVER_MODESET))
    return -EOPNOTSUPP;
    @@ -2444,9 +2445,11 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
    out_resp->connector_type = connector->connector_type;
    out_resp->connector_type_id = connector->connector_type_id;

    + is_current_master = drm_is_current_master(file_priv);
    +
    mutex_lock(&dev->mode_config.mutex);
    if (out_resp->count_modes == 0) {
    - if (drm_is_current_master(file_priv))
    + if (is_current_master)
    connector->funcs->fill_modes(connector,
    dev->mode_config.max_width,
    dev->mode_config.max_height);
    --
    2.25.1
    \
     
     \ /
      Last update: 2021-07-01 18:54    [W:8.709 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site