• Rafael J. Wysocki's avatar
    driver core: Fix handling of runtime PM flags in device_link_add() · e2f3cd83
    Rafael J. Wysocki authored
    After commit ead18c23 ("driver core: Introduce device links
    reference counting"), if there is a link between the given supplier
    and the given consumer already, device_link_add() will refcount it
    and return it unconditionally without updating its flags.  It is
    possible, however, that the second (or any subsequent) caller of
    device_link_add() for the same consumer-supplier pair will pass
    DL_FLAG_PM_RUNTIME, possibly along with DL_FLAG_RPM_ACTIVE, in flags
    to it and the existing link may not behave as expected then.
    
    First, if DL_FLAG_PM_RUNTIME is not set in the existing link's flags
    at all, it needs to be set like during the original initialization of
    the link.
    
    Second, if DL_FLAG_RPM_ACTIVE is passed to device_link_add() in flags
    (in addition to DL_FLAG_PM_RUNTIME), the existing link should to be
    updated to reflect the "active" runtime PM configuration of the
    consumer-supplier pair and extra care must be taken here to avoid
    possible destructive races with runtime PM of the consumer.
    
    To that end, redefine the rpm_active field in struct device_link
    as a refcount, initialize it to 1 and make rpm_resume() (for the
    consumer) and device_link_add() increment it whenever they acquire
    a runtime PM reference on the supplier device.  Accordingly, make
    rpm_suspend() (for the consumer) and pm_runtime_clean_up_links()
    decrement it and drop runtime PM references to the supplier
    device in a loop until rpm_active becones 1 again.
    
    Fixes: ead18c23 ("driver core: Introduce device links reference counting")
    Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    e2f3cd83
runtime.c 47.2 KB