From nobody Wed Apr 1 09:43:50 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 276E93B47F0 for ; Tue, 31 Mar 2026 21:46:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774993573; cv=none; b=ezfCpIlTzh70MoIi2zqVFlx6fRITrqi1CpBUGY8hMQHPS/fN9n/NT0PmvacloRCQyg9ZcUs8rdZptrxfGW6XZB6W583mWDgQHswCwsXIPC3bzlAfiURrqx975bXebwQVfZA10NEmEP3iVCQLgDOcu/xt7TSJSWQhVsmDI+v26ls= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774993573; c=relaxed/simple; bh=gowBNd4qTiC2ofhSRWjD/B5uht4noy52ERGZ4+EpXmM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=axG2vvBv+dSA79Nq2gDEewXdcCZDuJkPT8+pW9+uhQyR6OpNC1RyaIwgj/cxRS/RPQQwb2nicOPdLqCx0YYjMnrarZGr0UaMNtYSAJislmKa7P7fuk2qsDXEWQmyCUxdzeVNd0b/K1RC/WJn8YnBQ5wLxQH0/7HrRAOE2Jaf+eI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=MzBCJId1; arc=none smtp.client-ip=198.175.65.15 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="MzBCJId1" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774993572; x=1806529572; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=gowBNd4qTiC2ofhSRWjD/B5uht4noy52ERGZ4+EpXmM=; b=MzBCJId19nGSOmKbLGf1JjvuzAcFGQF7SW1jAw5NHk8rO3ZuPURjNZTM /ayppRVkpIo9VE5gsPmnMpurXcMFkNeks9V2USVdEWTQ65XZePyJQEpvz 4SsiIyGEV58asMrJE8xQZSiUX8t7xYFOMLPt9VnTvf4y8djP7lbH2NREc NghK4L+r9DFgIPLsnGAvtT26RP3YHFXOX8Jw2eC/QTwEuKtVIOBvwo7s4 dAcQlwRiocwd4/aR3RwB4zSvK8WXBehGkp8pOohTp1Du4j/gDqqWmYzHd Ky1R0z0v/Bzf44HtT0JhjZxL0ps727J5exGekt8sugjs2j/s7xwf/2/f6 g==; X-CSE-ConnectionGUID: /YSiE2oNTNWp7NLgpsDV9w== X-CSE-MsgGUID: Z38HbWd5SkSuoAVfd91+6w== X-IronPort-AV: E=McAfee;i="6800,10657,11745"; a="79627245" X-IronPort-AV: E=Sophos;i="6.23,152,1770624000"; d="scan'208";a="79627245" Received: from fmviesa001.fm.intel.com ([10.60.135.141]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Mar 2026 14:46:11 -0700 X-CSE-ConnectionGUID: jDOlQ0vhQCK2m1eqqTQB1g== X-CSE-MsgGUID: bDjpSupjTu6aI5FZQus6CQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,152,1770624000"; d="scan'208";a="249701122" Received: from dwillia2-desk.jf.intel.com ([10.88.27.145]) by fmviesa001.fm.intel.com with ESMTP; 31 Mar 2026 14:46:10 -0700 From: Dan Williams To: mcgrof@kernel.org, russ.weight@linux.dev, dakr@kernel.org Cc: linux-kernel@vger.kernel.org, Greg Kroah-Hartman , "Rafael J. Wysocki" , Chao Gao Subject: [PATCH 1/3] firmware_loader: Stop pinning modules on registration Date: Tue, 31 Mar 2026 14:47:24 -0700 Message-ID: <20260331214726.903274-2-dan.j.williams@intel.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260331214726.903274-1-dan.j.williams@intel.com> References: <20260331214726.903274-1-dan.j.williams@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The module reference counting can result in callers pinning themselves in a circular loop. The module reference counting is unnecessary. firmware_upload_unregister() must be able to guarantee that all ops are idle at return. All ops are either called from sysfs or the workqueue, so unregister sysfs to stop submissions, cancel any started transfers, flush cancelled transfers, and then release the device. This also solves a theoretical race of new submissions starting between flush_work() and device_unregister(). The module reference was not protecting against that race. Cc: Luis Chamberlain Cc: Russ Weight Cc: Danilo Krummrich Cc: Greg Kroah-Hartman Cc: "Rafael J. Wysocki" Reported-by: Chao Gao Tested-by: Chao Gao Closes: https://sashiko.dev/#/patchset/20260326084448.29947-1-chao.gao%40in= tel.com?patch=3D10705 Fixes: 97730bbb242c ("firmware_loader: Add firmware-upload support") Signed-off-by: Dan Williams --- drivers/base/firmware_loader/sysfs_upload.c | 31 ++++++++++----------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/drivers/base/firmware_loader/sysfs_upload.c b/drivers/base/fir= mware_loader/sysfs_upload.c index f59a7856934c..87c4f2a9a21b 100644 --- a/drivers/base/firmware_loader/sysfs_upload.c +++ b/drivers/base/firmware_loader/sysfs_upload.c @@ -312,14 +312,9 @@ firmware_upload_register(struct module *module, struct= device *parent, return ERR_PTR(-EINVAL); } =20 - if (!try_module_get(module)) - return ERR_PTR(-EFAULT); - fw_upload =3D kzalloc_obj(*fw_upload); - if (!fw_upload) { - ret =3D -ENOMEM; - goto exit_module_put; - } + if (!fw_upload) + return ERR_PTR(-ENOMEM); =20 fw_upload_priv =3D kzalloc_obj(*fw_upload_priv); if (!fw_upload_priv) { @@ -360,7 +355,7 @@ firmware_upload_register(struct module *module, struct = device *parent, if (ret) { dev_err(fw_dev, "%s: device_register failed\n", __func__); put_device(fw_dev); - goto exit_module_put; + return ERR_PTR(ret); } =20 return fw_upload; @@ -374,9 +369,6 @@ firmware_upload_register(struct module *module, struct = device *parent, free_fw_upload: kfree(fw_upload); =20 -exit_module_put: - module_put(module); - return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(firmware_upload_register); @@ -388,23 +380,28 @@ EXPORT_SYMBOL_GPL(firmware_upload_register); void firmware_upload_unregister(struct fw_upload *fw_upload) { struct fw_sysfs *fw_sysfs =3D fw_upload->priv; + struct device *parent =3D fw_sysfs->dev.parent; struct fw_upload_priv *fw_upload_priv =3D fw_sysfs->fw_upload_priv; - struct module *module =3D fw_upload_priv->module; + + /* hold a parent reference while child is unregistered */ + get_device(parent); + + /* shutdown the sysfs interface to block new requests */ + device_del(&fw_sysfs->dev); =20 mutex_lock(&fw_upload_priv->lock); if (fw_upload_priv->progress =3D=3D FW_UPLOAD_PROG_IDLE) { mutex_unlock(&fw_upload_priv->lock); - goto unregister; + goto release; } =20 fw_upload_priv->ops->cancel(fw_upload); mutex_unlock(&fw_upload_priv->lock); =20 +release: /* Ensure lower-level device-driver is finished */ flush_work(&fw_upload_priv->work); - -unregister: - device_unregister(&fw_sysfs->dev); - module_put(module); + put_device(&fw_sysfs->dev); + put_device(parent); } EXPORT_SYMBOL_GPL(firmware_upload_unregister); --=20 2.53.0