Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp3326259pxf; Mon, 5 Apr 2021 09:06:05 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyLQwjVKlOPpbcUMp022ilAJV2OYb0fC6FdFC4R2wVF/dMOinE02XOt0cdawEnqeulpfzbL X-Received: by 2002:adf:f3cf:: with SMTP id g15mr30200928wrp.57.1617638765019; Mon, 05 Apr 2021 09:06:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1617638765; cv=none; d=google.com; s=arc-20160816; b=cnw/Ps5nYTVTl8romVvgFSqzSIJ6An0kziBDARub2IcCrV5fjp3Ir79gTokmrcwCKh EPvYp4rK9aY4UAiLDiwc9bq66dJnKPxZk1K7CooPSo4ZGHJM2UPHKVF1/2fL5wMj1FP5 F2Bn4ASIaZiwtczxnvvRSR28LOe6/o7CY/SwdD3puUd6ZqMmoLx5jllwh/2Jp2PuOLzA zhRpWkS2VVircbkgcod0r5AxeQ9GvVUj2Uh/4aNvUYDP0Xbv9ZDG5EM5eajVMSCXK42f rrxRyo6X/xA+OjVINaC8KWdjIeBc8gPUK0Qz7x+bhc0/26eD1lwCm23PtAkDIRz5Q9U6 bjwA== 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=L05QPMgZb5Qvk1g6zDzxkxcrIzVb08F9rhLGSazL4M8=; b=yviXK/w8kK+qqwh/FITYO5TWPAYVzE6XG9iThLmbOYkYF/i6dV41IM+S4snapjcWIA 1YijnIcs8OwJdlstpPXhz96yzjBOnWTYUvRT2AlDoAEOtiC6U8wIPSsE7VdZ88l5nxKH 8Sru2el7LsG0NC4dXlLuQFjSx+N+o98sidHhFrGweWc8wpcTGgwTd7kUXZdBELpp9G9J 6EC/VVVTbw5mFwsM2iXZdbLOZ2t5hpJrxpV/8w5J2x9L3VSrObC08AFb9wFJKtaBoVxI oWE8ZcgzUBpjwu9AMM1XfeK1ow9NZ3opuQGS/IPYsNGIzHoqUao2isrmBhy5qGQjEpjj 3lCA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b="CwJsHRD/"; 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 y7si12971936ejd.159.2021.04.05.09.05.41; Mon, 05 Apr 2021 09:06:05 -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="CwJsHRD/"; 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 S239042AbhDEJLt (ORCPT + 99 others); Mon, 5 Apr 2021 05:11:49 -0400 Received: from mail.kernel.org ([198.145.29.99]:53378 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238706AbhDEJIu (ORCPT ); Mon, 5 Apr 2021 05:08:50 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id B3FF761399; Mon, 5 Apr 2021 09:08:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1617613724; bh=N35o62fbSEOSuqmsqry1AgPULNdNIjR4VW3kwET2dVk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CwJsHRD/CFondDvz2QmztcD9553/0BFBeZahPrKViikAENPe8tIm48K4QOrnNW1cd tDIE57uMbmedXmD0e0Efwl8pTduVTdd0jzAkNpp6m4olKn+losQzSiDF8bij2moUT7 CjphTWAWM9X54XoTwrisjwSNAzH3zxBf+/H/Bq2w= 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.10 067/126] PM: runtime: Fix race getting/putting suppliers at probe Date: Mon, 5 Apr 2021 10:53:49 +0200 Message-Id: <20210405085033.273872417@linuxfoundation.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210405085031.040238881@linuxfoundation.org> References: <20210405085031.040238881@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 @@ -1704,6 +1704,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(); @@ -1712,7 +1714,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); }