Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp3064988pxf; Mon, 5 Apr 2021 02:09:23 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwVIb/imWw4pYQRay76yU3WET9DixS/h/024rFLHVqmbimIA+beBHJRB/Lx/zo9kbJPLp2T X-Received: by 2002:a6b:e809:: with SMTP id f9mr19028185ioh.97.1617613763103; Mon, 05 Apr 2021 02:09:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1617613763; cv=none; d=google.com; s=arc-20160816; b=qpLyzRhvBVi7om7+bCEuFTmXerMofXsmXXQ4YwOLu2S+MiOn2aH5ZLweFJ74v1yeiw +ypOG0DiWDkW4dzmqdsoyU+2SwRP4BG0zzXeO73OEWStJRAPLsE9oJZecBrDNlzkitun /6hpFG2Rg1o2NjEodPHYb4+plSp29jWb5VNeAqaOXDuM4qvh0/SKmCa2JsS8XPLXNosX uriZwv2ZUZy741feasiMs3XAiruOfyALPPVoIZVm4bgq6PhGKfdKF5ujJgcQqkjhSZ3A ot6uyGwkbxdNqMXYtMg1eVt97AoRj3pSJ1irC7oupl0A9KMyabi8oBFhLfBKIycVYVUp crDQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=l4mBeVDjCDGW2orivUtCo70EWvPd4JzdubF8dwqfNRI=; b=xdE6YKa6MkjfSdjpmqsXHl5s0marx9LVOnMENAbRiaZVX9kscwPIoxg3X/5zATbsAZ gfh6ICJIJ18k+42qfPwOvzBukuTeNXKceGya/gLHKAh7IhUGSIKJwgOQDyuY7bRz0Auq gPPJgI7/Up06L3OEboNxmLAfnGl3+dJ6ODqHdgUNfWyABppjGKcBQAGw7Dgsj6sqac+b nD1AJWWWZNH9JIawSP1LGj+bxJmBdCP3JwLXNRqtYoEikXXACokxf+JV+cPiNctLsrFy kW27bRo3It2poqKC9+OP74OcN6+7Z0xiCdB7MBPGxtC7sffsyY0IKSh2sKko/uHepP7o upqw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=fyMGvb1b; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id n12si8034327ilk.24.2021.04.05.02.09.11; Mon, 05 Apr 2021 02:09:23 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=fyMGvb1b; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238474AbhDEJIT (ORCPT + 99 others); Mon, 5 Apr 2021 05:08:19 -0400 Received: from mail.kernel.org ([198.145.29.99]:50520 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238653AbhDEJGG (ORCPT ); Mon, 5 Apr 2021 05:06:06 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 76292613AC; Mon, 5 Apr 2021 09:05:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1617613560; bh=IlKt/dVckqwdd0z4Lk8SteKUQDoIgcCvhX7Rnru/USs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fyMGvb1bQy8Y8ATUSRO2dwTee3+M6/U8knLfNhHObom8aycACPF13Ff9B/7ZuhsqT NkUwv68aoX8J7v1HgNShsiAIpdUxFLTLjkXuQR5ce1+FwOJlFoWA3oUvVTm1xMJv4Q HP/JTJ5VQST0/i4r5+gwaADpq0bZ0+/ukygwcMQs= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Asutosh Das , Adrian Hunter , "Rafael J. Wysocki" Subject: [PATCH 5.4 47/74] PM: runtime: Fix race getting/putting suppliers at probe Date: Mon, 5 Apr 2021 10:54:11 +0200 Message-Id: <20210405085026.262535427@linuxfoundation.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210405085024.703004126@linuxfoundation.org> References: <20210405085024.703004126@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Adrian Hunter commit 9dfacc54a8661bc8be6e08cffee59596ec59f263 upstream. pm_runtime_put_suppliers() must not decrement rpm_active unless the consumer is suspended. That is because, otherwise, it could suspend suppliers for an active consumer. That can happen as follows: static int driver_probe_device(struct device_driver *drv, struct device *dev) { int ret = 0; if (!device_is_registered(dev)) return -ENODEV; dev->can_match = true; pr_debug("bus: '%s': %s: matched device %s with driver %s\n", drv->bus->name, __func__, dev_name(dev), drv->name); pm_runtime_get_suppliers(dev); if (dev->parent) pm_runtime_get_sync(dev->parent); At this point, dev can runtime suspend so rpm_put_suppliers() can run, rpm_active becomes 1 (the lowest value). pm_runtime_barrier(dev); if (initcall_debug) ret = really_probe_debug(dev, drv); else ret = really_probe(dev, drv); Probe callback can have runtime resumed dev, and then runtime put so dev is awaiting autosuspend, but rpm_active is 2. pm_request_idle(dev); if (dev->parent) pm_runtime_put(dev->parent); pm_runtime_put_suppliers(dev); Now pm_runtime_put_suppliers() will put the supplier i.e. rpm_active 2 -> 1, but consumer can still be active. return ret; } Fix by checking the runtime status. For any status other than RPM_SUSPENDED, rpm_active can be considered to be "owned" by rpm_[get/put]_suppliers() and pm_runtime_put_suppliers() need do nothing. Reported-by: Asutosh Das Fixes: 4c06c4e6cf63 ("driver core: Fix possible supplier PM-usage counter imbalance") Signed-off-by: Adrian Hunter Cc: 5.1+ # 5.1+ Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/runtime.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1677,6 +1677,8 @@ void pm_runtime_get_suppliers(struct dev void pm_runtime_put_suppliers(struct device *dev) { struct device_link *link; + unsigned long flags; + bool put; int idx; idx = device_links_read_lock(); @@ -1685,7 +1687,11 @@ void pm_runtime_put_suppliers(struct dev device_links_read_lock_held()) if (link->supplier_preactivated) { link->supplier_preactivated = false; - if (refcount_dec_not_one(&link->rpm_active)) + spin_lock_irqsave(&dev->power.lock, flags); + put = pm_runtime_status_suspended(dev) && + refcount_dec_not_one(&link->rpm_active); + spin_unlock_irqrestore(&dev->power.lock, flags); + if (put) pm_runtime_put(link->supplier); }