lkml.org 
[lkml]   [2017]   [Jun]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 17/46] PM / runtime: Avoid false-positive warnings from might_sleep_if()
    Date
    4.4-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>


    [ Upstream commit a9306a63631493afc75893a4ac405d4e1cbae6aa ]

    The might_sleep_if() assertions in __pm_runtime_idle(),
    __pm_runtime_suspend() and __pm_runtime_resume() may generate
    false-positive warnings in some situations. For example, that
    happens if a nested pm_runtime_get_sync()/pm_runtime_put() pair
    is executed with disabled interrupts within an outer
    pm_runtime_get_sync()/pm_runtime_put() section for the same device.
    [Generally, pm_runtime_get_sync() may sleep, so it should not be
    called with disabled interrupts, but in this particular case the
    previous pm_runtime_get_sync() guarantees that the device will not
    be suspended, so the inner pm_runtime_get_sync() will return
    immediately after incrementing the device's usage counter.]

    That started to happen in the i915 driver in 4.10-rc, leading to
    the following splat:

    BUG: sleeping function called from invalid context at drivers/base/power/runtime.c:1032
    in_atomic(): 1, irqs_disabled(): 0, pid: 1500, name: Xorg
    1 lock held by Xorg/1500:
    #0: (&dev->struct_mutex){+.+.+.}, at:
    [<ffffffffa0680c13>] i915_mutex_lock_interruptible+0x43/0x140 [i915]
    CPU: 0 PID: 1500 Comm: Xorg Not tainted
    Call Trace:
    dump_stack+0x85/0xc2
    ___might_sleep+0x196/0x260
    __might_sleep+0x53/0xb0
    __pm_runtime_resume+0x7a/0x90
    intel_runtime_pm_get+0x25/0x90 [i915]
    aliasing_gtt_bind_vma+0xaa/0xf0 [i915]
    i915_vma_bind+0xaf/0x1e0 [i915]
    i915_gem_execbuffer_relocate_entry+0x513/0x6f0 [i915]
    i915_gem_execbuffer_relocate_vma.isra.34+0x188/0x250 [i915]
    ? trace_hardirqs_on+0xd/0x10
    ? i915_gem_execbuffer_reserve_vma.isra.31+0x152/0x1f0 [i915]
    ? i915_gem_execbuffer_reserve.isra.32+0x372/0x3a0 [i915]
    i915_gem_do_execbuffer.isra.38+0xa70/0x1a40 [i915]
    ? __might_fault+0x4e/0xb0
    i915_gem_execbuffer2+0xc5/0x260 [i915]
    ? __might_fault+0x4e/0xb0
    drm_ioctl+0x206/0x450 [drm]
    ? i915_gem_execbuffer+0x340/0x340 [i915]
    ? __fget+0x5/0x200
    do_vfs_ioctl+0x91/0x6f0
    ? __fget+0x111/0x200
    ? __fget+0x5/0x200
    SyS_ioctl+0x79/0x90
    entry_SYSCALL_64_fastpath+0x23/0xc6

    even though the code triggering it is correct.

    Unfortunately, the might_sleep_if() assertions in question are
    too coarse-grained to cover such cases correctly, so make them
    a bit less sensitive in order to avoid the false-positives.

    Reported-and-tested-by: Sedat Dilek <sedat.dilek@gmail.com>
    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
    Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/base/power/runtime.c | 11 ++++++-----
    1 file changed, 6 insertions(+), 5 deletions(-)

    --- a/drivers/base/power/runtime.c
    +++ b/drivers/base/power/runtime.c
    @@ -889,13 +889,13 @@ int __pm_runtime_idle(struct device *dev
    unsigned long flags;
    int retval;

    - might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
    -
    if (rpmflags & RPM_GET_PUT) {
    if (!atomic_dec_and_test(&dev->power.usage_count))
    return 0;
    }

    + might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
    +
    spin_lock_irqsave(&dev->power.lock, flags);
    retval = rpm_idle(dev, rpmflags);
    spin_unlock_irqrestore(&dev->power.lock, flags);
    @@ -921,13 +921,13 @@ int __pm_runtime_suspend(struct device *
    unsigned long flags;
    int retval;

    - might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
    -
    if (rpmflags & RPM_GET_PUT) {
    if (!atomic_dec_and_test(&dev->power.usage_count))
    return 0;
    }

    + might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
    +
    spin_lock_irqsave(&dev->power.lock, flags);
    retval = rpm_suspend(dev, rpmflags);
    spin_unlock_irqrestore(&dev->power.lock, flags);
    @@ -952,7 +952,8 @@ int __pm_runtime_resume(struct device *d
    unsigned long flags;
    int retval;

    - might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
    + might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe &&
    + dev->power.runtime_status != RPM_ACTIVE);

    if (rpmflags & RPM_GET_PUT)
    atomic_inc(&dev->power.usage_count);

    \
     
     \ /
      Last update: 2017-06-15 20:39    [W:3.586 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site