From nobody Fri Sep 25 18:27:11 2026 Received: from mail-wm2-f12.google.com (mail-wm2-f12.google.com [74.125.225.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0898456B849 for ; Wed, 9 Sep 2026 15:42:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.225.140 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788968530; cv=none; b=EOOhGwRmcrSpmFDNdTjfgInfbDwcmSOKrI85A/nunri1sCKyCAxl9FHfHJuRfno3VllDz9KtwgTB9ITK9JDlZwhBzmyyRJ9ZplUVR4+w/4Z69m9bhKppw/u+pHeJhYkLP/Wn0/FfkX0QWIHT1ZKpjK2KFf6uQJEpp5XHvbxfPM8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788968530; c=relaxed/simple; bh=uu+2lcKvfJGi/5CNbofvvGBfTiVgP3doGLL1WgijQqw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Rqub69KLSki8wz8WTOfXzQjwjdXQRvJCVvI3dnGSYBCK6unwhdDqZgwSOlv2XvIsd24G70+BeFwiMmDSyhQMOiOak0Xb+CkkeZhJAVqEa3xE8YDt6hEjHKrY21U+xtKFUKX6SXUMpf6CXVhF91yZ9YwzT8AJuhwiGU03cHCmqcQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=flipper.net; spf=pass smtp.mailfrom=flipper.net; dkim=pass (2048-bit key) header.d=flipper.net header.i=@flipper.net header.b=GQLMDJdt; arc=none smtp.client-ip=74.125.225.140 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=flipper.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flipper.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=flipper.net header.i=@flipper.net header.b="GQLMDJdt" Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49ce364488dso8189125e9.0 for ; Wed, 09 Sep 2026 08:42:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=flipper.net; s=google; t=1788968526; x=1789573326; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=ATWBzXgtximDnM1arJgBep/Ega/TVarG2T9lOXViDEw=; b=GQLMDJdt4gyoDqitmHKquozQjRKCMJ1K28XyxlWLK4fVOzQQc39QZ3pxFpH2rg1/rw huH8CaGU319IcC4Po+vqK3mVqR4vl5FkrzE6mo0EqY8xUvDjPfmvGdeotc5122jpItnh s1hQWFyF+en8MI0qeCrVHHsfnhUBHtNt6ECbFY3snMrqU9wKe1QKh2/XLnXEKn1lA7A5 4vF+h4DAxQuo0R4z1F8CmzvteNtj78XDEXLcla+JAlZTLhwUoq8jbPhx8V7KCCnNP6fO +RolKcpJRCZ7GeIrvP1pxJZAQ4NOWHcaIA7wIl7dBgbsi8EDtzPBXdAL3BAQTSOXDO6j NOWA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788968526; x=1789573326; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=ATWBzXgtximDnM1arJgBep/Ega/TVarG2T9lOXViDEw=; b=Fyr1SGCNew+8B0LYOpi7gzZjjSkdRfU8120x7on5cQYWXIsWiPgzgwLgbxdGBkflEz jqTtJ6KqCeIFdemSmFpdXkvKWFB92tkSE063ARao1gG28/LGJ1ZoG67pavEUqx9NkzQy yVuFhzOajf424lnh2XPi87nqdAc+2R7BZJ+jKMphUJWGfPKFYhOXm32/eaQASQDR9Uqd 3whga5wtKGtDEMRcshQzzMvZGmCMzxdEkiX9i/XLG8irYiNo+1amFLN/S5KCxXy3+4sW KlnSqOWEGFoUlSuIJUtDyM63JS5wxUv/4nq2XPF5X/dPpQNHpa51Jk30hX7GL7qH4en/ cTEw== X-Forwarded-Encrypted: i=1; AKwUvBxDW04NwNC56g55uxLK8+096cy+F/vjUjIQt4QwRfml33tGbl+WNbG2s/MFvSF1wSDu5eeY9/8wgeBnP0w=@vger.kernel.org X-Gm-Message-State: AFuF++km+DP0gFwcNSz4tLS7L4fAaRNaZ6tgXyhUJSppcN45SF6cDoTp wHDc5iJsAvt42gptE6n7HZwH5snC0gc7+u0aepfWZbgcxe3Tuo3eiQn467bPOzM3wt0= X-Gm-Gg: AYBFou1FXiky+qlzq6T158qY9cRLDbH4/F9jSiX6RyN3m/OpSl+GV7eH21mUkyRqZIP tAdy/C+3aY0OGS+ECsUwEguvEdIjvVQ801qpFopKW09Z7vvjQ/0VjRuBY8JaS7ZvUWbDzw+Jt8p H74zaB9aDm0CH0fK3nq1RVUvvAlWpN66yFmzQ+moCSIr+bW6q2hNhjUEiy7VwpgPk62+dzVD6/q zFIxyRksJLRoukax0s/YcpgoS7ZpvgB1xvHKnfsZuGdL0hee4LIUZ2j2i1Gmk0nXMt0LA42kL0R Ee57bi82o+O5DMQ5oNSgLGR2iGbhfPlGtbABPEx6njUaab3cqNkwwqoH58MevoZCUYIuOQEqYkR Se1NjIzetDEzFegR0L05eP/5PMbJTdLfoektlWpSI3CgSMSj0AfChj5j0Ys7mxfg6WU8LtgY09s PCZ6IWBsdyC2UOAZbs4+D+URFUbHAzzE8jgG8oV8oSgUCNLRsOAsPSjYaqXEqtN04tXZ9ifYOQq FHI0jXxvJ8FpT/qez9AjtHXXqswNIqg/30fVxsdWI0HYfg3dmw= X-Received: by 2002:a05:600c:3145:b0:49c:f13e:e4c with SMTP id 5b1f17b1804b1-49d1757294bmr150353495e9.9.1788968526173; Wed, 09 Sep 2026 08:42:06 -0700 (PDT) Received: from alchark-surface.localdomain (bba-2-51-220-108.alshamil.net.ae. [2.51.220.108]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49cf7740d44sm1042068015e9.15.2026.09.09.08.42.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 08:42:05 -0700 (PDT) From: Alexey Charkov Date: Wed, 09 Sep 2026 19:41:44 +0400 Subject: [PATCH v2 1/4] power: supply: core: prevent unregistering a power supply while a callback runs Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-bq257xx-init-v2-1-deb4076b1f02@flipper.net> References: <20260909-bq257xx-init-v2-0-deb4076b1f02@flipper.net> In-Reply-To: <20260909-bq257xx-init-v2-0-deb4076b1f02@flipper.net> To: Sebastian Reichel , Lee Jones , Chris Morgan , Pavel Machek , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz Cc: Sebastian Reichel , linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, Alexey Charkov X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=7060; i=alchark@flipper.net; h=from:subject:message-id; bh=uu+2lcKvfJGi/5CNbofvvGBfTiVgP3doGLL1WgijQqw=; b=owGbwMvMwCW2adGNfoHIK0sZT6slMWQtrHP7JRdy5OU0dY65SkVS+Y2sCk8k3zQbTr970WZla HHutYAVHRNZGMS4GCzFFFnmfltiO9WIb9YuD4+vMHNYmUCGSIs0MAABCwNfbmJeqZGOkZ6ptqGe oZGOsY4RAxenAEx160KG/+WP2RPOLpo09cii5NQT2q8fbKw9EZibn/zu97sHQVb7U2YxMrQJ5C1 /cKLKs3zZrdBy0wWvI47HMnxw+XvFRe3Wr5k3NjMCAA== X-Developer-Key: i=alchark@flipper.net; a=openpgp; fpr=9DF6A43D95320E9ABA4848F5B2A2D88F1059D4A5 Once a power supply is registered, its callbacks can immediately start firing from other contexts, such as external_power_changed() triggered by the TCPM stack. If a power supply is unregistered while the callback is still running, the driver data can already be freed when the callback tries to access it, leading to a use-after-free. This happens e.g. when the hardware bus carrying the power supply device malfunctions (e.g. I2C is hogged down by another malfunctioning device) immediately after the power supply is registered, and thus the core is still processing the callbacks which were queued up when the driver starts the removal, leading in some cases to a kernel crash, e.g.: [ 11.645942] Unable to handle kernel NULL pointer dereference at virtual = address 0000000000000005 [ 11.646751] Mem abort info: [ 11.647006] ESR =3D 0x0000000096000004 [ 11.647338] EC =3D 0x25: DABT (current EL), IL =3D 32 bits [ 11.647806] SET =3D 0, FnV =3D 0 [ 11.648077] EA =3D 0, S1PTW =3D 0 [ 11.648356] FSC =3D 0x04: level 0 translation fault [ 11.648785] Data abort info: [ 11.649041] ISV =3D 0, ISS =3D 0x00000004, ISS2 =3D 0x00000000 [ 11.649524] CM =3D 0, WnR =3D 0, TnD =3D 0, TagAccess =3D 0 [ 11.649981] GCS =3D 0, Overlay =3D 0, DirtyBit =3D 0 [ 11.650390] [0000000000000005] user address but active_mm is swapper [ 11.650955] Internal error: Oops: 0000000096000004 [#1] SMP [ 11.651460] Modules linked in: [ 11.651742] CPU: 1 UID: 0 PID: 144 Comm: kworker/1:2 Not tainted 7.2.0-r= c6-g62a9297af2cd #1 PREEMPT [ 11.652553] Hardware name: Flipper One rev. F0B1C2 (DT) [ 11.653024] Workqueue: events power_supply_changed_work [ 11.653511] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE= =3D--) [ 11.654135] pc : __power_supply_is_supplied_by+0x18/0x100 [ 11.654624] lr : __power_supply_am_i_supplied+0x40/0xb8 [ 11.655098] sp : ffff80008192bb30 [ 11.655399] x29: ffff80008192bb30 x28: 0000000000000000 x27: 00000000000= 00000 [ 11.656049] x26: 0000000000000000 x25: 0000000000000000 x24: 00000000000= 00000 [ 11.656695] x23: ffff0000c19f4200 x22: ffffdb2232ba4ea8 x21: ffff8000819= 2bc28 [ 11.657344] x20: ffff0000c1eef000 x19: ffff80008192bc18 x18: 00000000a08= 86e62 [ 11.657991] x17: 000000040044ffff x16: 04500072b5503510 x15: 00000000000= 00000 [ 11.658639] x14: 0000000000000000 x13: 0000000000000220 x12: 00000000000= 00000 [ 11.659286] x11: 0000000000000000 x10: ffff0000c1fdb2b0 x9 : ffffdb2232b= a5590 [ 11.659934] x8 : 00000000e5b906e6 x7 : ffff0000c2502778 x6 : ffffdb22339= 793d0 [ 11.660581] x5 : ffff80008192bc18 x4 : ffff0000c19cbca0 x3 : 00000000000= 00000 [ 11.661228] x2 : ffff0000c1fdaf40 x1 : ffffffffffffffed x0 : ffff0000c1e= ef000 [ 11.661878] Call trace: [ 11.662103] __power_supply_is_supplied_by+0x18/0x100 (P) [ 11.662596] __power_supply_am_i_supplied+0x40/0xb8 [ 11.663040] psy_for_each_psy_cb+0x20/0x40 [ 11.663416] class_for_each_device+0x110/0x150 [ 11.663825] power_supply_am_i_supplied+0x68/0x100 [ 11.664262] bq257xx_external_power_changed+0x58/0x140 [ 11.664733] __power_supply_changed_work+0x60/0x80 [ 11.665170] psy_for_each_psy_cb+0x20/0x40 [ 11.665545] class_for_each_device+0x110/0x150 [ 11.665953] power_supply_changed_work+0x98/0x1b8 [ 11.666382] process_one_work+0x164/0x4c0 [ 11.666758] worker_thread+0x19c/0x320 [ 11.667104] kthread+0x138/0x150 [ 11.667408] ret_from_fork+0x10/0x20 [ 11.667744] Code: d503233f a9bd7bfd 910003fd a90153f3 (f9400c34) [ 11.668294] ---[ end trace 0000000000000000 ]--- Add a read-write semaphore between external_power_changed() and power_supply_unregister() to prevent the latter from returning (and thus the driver from freeing its data) while the callback is still running. Fixes: bc1540561c9e ("power_supply: Add API for safe access of power supply= function attrs") Signed-off-by: Alexey Charkov --- drivers/power/supply/power_supply_core.c | 26 +++++++++++++++++++++++++- include/linux/power_supply.h | 10 ++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/suppl= y/power_supply_core.c index 47e307709e5e..1279785645fb 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -1530,6 +1530,19 @@ void power_supply_external_power_changed(struct powe= r_supply *psy) !psy->desc->external_power_changed) return; =20 + /* + * Keep power_supply_unregister() from returning, and thus from letting + * the driver's data be freed, while the callback is running. The + * ->removing check has to happen under the lock: on its own, just like + * the use_cnt check above, it only tells us the supply was still there + * when we looked, not that it still is by the time the callback + * dereferences its driver data. + */ + guard(rwsem_read)(&psy->epc_sem); + + if (psy->removing) + return; + psy->desc->external_power_changed(psy); } EXPORT_SYMBOL_GPL(power_supply_external_power_changed); @@ -1774,6 +1787,7 @@ __power_supply_register(struct device *parent, } =20 spin_lock_init(&psy->changed_lock); + init_rwsem(&psy->epc_sem); init_rwsem(&psy->extensions_sem); INIT_LIST_HEAD(&psy->extensions); =20 @@ -1914,7 +1928,17 @@ EXPORT_SYMBOL_GPL(devm_power_supply_register); void power_supply_unregister(struct power_supply *psy) { WARN_ON(atomic_dec_return(&psy->use_cnt)); - psy->removing =3D true; + + /* + * Publish ->removing so that no new ->external_power_changed() call can + * start, and wait via semaphore for one that is already running: it may + * be a supplier's changed_work, which cancel_work_sync() below does not + * cover, and it may still dereference driver data that the caller is + * about to free. + */ + scoped_guard(rwsem_write, &psy->epc_sem) + psy->removing =3D true; + cancel_work_sync(&psy->changed_work); cancel_delayed_work_sync(&psy->deferred_register_work); sysfs_remove_link(&psy->dev.kobj, "powers"); diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index e749d2189335..131cafded72f 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -351,6 +351,16 @@ struct power_supply { bool removing; atomic_t use_cnt; struct power_supply_battery_info *battery_info; + /* + * Held for read while ->external_power_changed() runs, and for write by + * power_supply_unregister() when it publishes @removing, so that it + * waits for an in-flight callback to finish. Without this a driver's + * data, typically devm-allocated on its own device, can be freed while + * the callback is still using it. + * Must not be shared with extensions_sem: callbacks may read their own + * properties, which takes that one for read. + */ + struct rw_semaphore epc_sem; struct rw_semaphore extensions_sem; /* protects "extensions" */ struct list_head extensions; #ifdef CONFIG_THERMAL --=20 2.55.0 From nobody Fri Sep 25 18:27:11 2026 Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A440F563FB4 for ; Wed, 9 Sep 2026 15:42:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788968532; cv=none; b=hpkRiZ5HJuBiQGvYt7BKivfz5ESvqbcb5eB2KfSzGXXIx13UAvMgajI0x4WPHdLtqMZUp5PaX/N7qqWgGLlE13mX5PqA7SzNI6iYZWKqgjsVGHgKk6B1rLy8p9IbwNTOr+jV/ftfDPDjfc89CgiacnPKY6KhUlPbWSmVaQMnweM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788968532; c=relaxed/simple; bh=0NwXSncFwR6YuS62Kx37owltw4umKj8bQFmER1oSXrg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=QZ08UUcjHrUQ4rWjr6aJds0QrGhTYn35dseglaLN07Zj6rcM2ntNTnj68o6FK+71Ssn0bpIxwHp93DvJT73UWlmWrCB3aVtYYX6/FA6mrGlcsgs7lq4pPoZcyZay+RT2KhYwL2kvRSrAp6q79hJhnpacOhjgKqDxxNdQeRh39Tc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=flipper.net; spf=pass smtp.mailfrom=flipper.net; dkim=pass (2048-bit key) header.d=flipper.net header.i=@flipper.net header.b=Hlt9i9zC; arc=none smtp.client-ip=209.85.128.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=flipper.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flipper.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=flipper.net header.i=@flipper.net header.b="Hlt9i9zC" Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-49b8e527d63so73945695e9.2 for ; Wed, 09 Sep 2026 08:42:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=flipper.net; s=google; t=1788968529; x=1789573329; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=HJYkl8jNFFOfbd0XkHiDP5XOYtWq4UTRk/hZ80PHvcA=; b=Hlt9i9zC5Tyd6hvkQb390grplxqryfoxwXgHtBbFoIhwEVKSkQBcbNglmgzEbLqNLF eLTmUJUJzpye4a2wH+1d1SdkIRG7aaA6KQKBHjqrM842uywIm/Z8FCEY/E16DMXglGjI v5vDfiuSwovQc8WZRKZZYxq1EoJ+Efn80dhMpx6DBN+XY4uIBpKwsSsVEOBL9M0lAlD1 pG5bRCwK11RN+jDBqEEf1G9wZ1i6hteyzH/HeQC5bEOa9ScSjADPFqbj8l7upagqw0RX UXHQOzL4tx1gCrn8aU3xoQOEeWq0AqXraMuLU2aPVfXOGt38IpOd6LdbRb97VYd7dFhW U9og== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788968529; x=1789573329; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=HJYkl8jNFFOfbd0XkHiDP5XOYtWq4UTRk/hZ80PHvcA=; b=AV7Paz9j1nzXXVer+E9P9UAqL2cJLVGmksD3OsGg0c4CkMln+K9BtQKaFGpplfEJOX +sZvAuQRAWEwAxashAdUq1AyP6JS0uqzbjJK6G6oWnBq0EKTvHb1kmfjPUi0vpQyp4oR Lh6/kE1z9NXItlILOCwkgyse0tdq6rk/3KBLamUwt9hg0R+VPqH9XCqtNuK688lwrUqs eEVOHz7wS/QdbGa+Glyu4AWIXMrK/8lt7j3/L92RyNNcaZIDKnK6oqfItmHgttBHxDSX wVgcyV93D8PG/tJTRv/1aM9XJAqU/VuzbhjdPWh35bu8RELZ1ifMfs6BECrx7UBbuGcA HUkg== X-Forwarded-Encrypted: i=1; AKwUvBwbmIHW5Jy9tP7al3KwvlhEafi24cHJEcp2U/l3ARpBODa4jA38IY+a//l88W8M2PJdHBZGRVa8QtyfDzA=@vger.kernel.org X-Gm-Message-State: AFuF++nYHVlENVXTT1kYQfmws4/od57RGq9VwOlqpREdoreAO/Mj1Nxa 4nWRV4ocrItyQRA0jeChydOOe4jheqTDBeXaReRCjqht2nDJToiyIK6yWSSRkaLennI= X-Gm-Gg: AYBFou2VoI4y0htNa34dISvc7pnjTjeTE7lue9SQEyCO9BNPL4LBPvPqtPYv12is3f/ OB1Yj1MKGpYrtL4SlnSP9cozFA6y1AQBrY9l0uhGwLDTcnKgFjzvbgChC3od6v+dSa+e+lWY3fV mOcCM6/5daclfgFTPBHo8YZP7XNrNkTL4PRvUvdL6t1Z2/Tt6U3UYOh6QzWlHkOQuVy6OeFpNRb /lrQzPhukfjvQQkrOcqEBC9ANoptWc7s3fyJG0yya1G/U2+H9USm9a0Tdm1ShZ+M7H06+Tsd7fw UgNYidusWOpQ3nbNCm+O75y6Q81vBe9NKaMkPtvuDB6kSnMChVx3DaAKLQVQ6wSHXthZXJPjJs1 hwE2F+X3QhbafNfOKpuZ/5LCGIpQ+LUIO1rAOv65fX9H8dQ/+ZlXJE7QMUMKIivXdsSdQCSa5gk cj93jwXC75SKsUvd+CMMLJXHs7Y4l2ratnL7LB6sgz4qdOwAvGyAsZq50B5SVWbNo7yOBzMoH9j w5XvhjTuHO7enh+xld5KG60hooFHbG/wEQ76UhsHD6kU75BJ0c= X-Received: by 2002:a05:600c:1914:b0:49c:ff23:a6d5 with SMTP id 5b1f17b1804b1-49cff23a70bmr322804815e9.0.1788968528792; Wed, 09 Sep 2026 08:42:08 -0700 (PDT) Received: from alchark-surface.localdomain (bba-2-51-220-108.alshamil.net.ae. [2.51.220.108]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49cf7740d44sm1042068015e9.15.2026.09.09.08.42.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 08:42:08 -0700 (PDT) From: Alexey Charkov Date: Wed, 09 Sep 2026 19:41:45 +0400 Subject: [PATCH v2 2/4] power: supply: core: Allow getting battery info before psy is registered Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-bq257xx-init-v2-2-deb4076b1f02@flipper.net> References: <20260909-bq257xx-init-v2-0-deb4076b1f02@flipper.net> In-Reply-To: <20260909-bq257xx-init-v2-0-deb4076b1f02@flipper.net> To: Sebastian Reichel , Lee Jones , Chris Morgan , Pavel Machek , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz Cc: Sebastian Reichel , linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, Alexey Charkov X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=10260; i=alchark@flipper.net; h=from:subject:message-id; bh=0NwXSncFwR6YuS62Kx37owltw4umKj8bQFmER1oSXrg=; b=owGbwMvMwCW2adGNfoHIK0sZT6slMWQtrHObbC5hFPP/d9Gmn7FyHmqvWdSzf79IOH+SxWGBi EKpnPSSjoksDGJcDJZiiixzvy2xnWrEN2uXh8dXmDmsTCBDpEUaGICAhYEvNzGv1EjHSM9U21DP 0EjHWMeIgYtTAKb6sAHDf4epzL9m2UcdczcwC3n++qOKnM/x7p871n05vWy36tkf9Y0M/4sTm41 SNTP3Za68djLInXv7q0cJfBEtedmi86/NNo26xwkA X-Developer-Key: i=alchark@flipper.net; a=openpgp; fpr=9DF6A43D95320E9ABA4848F5B2A2D88F1059D4A5 Some power supplies, such as battery chargers, may need to program the device parameters based on what their connected battery allows. Current API requires registering the power supply to access battery information, which is problematic because a registered power supply is immediately available to the rest of the system, but the battery parameters may not be set yet in the charger. Given that the battery info helpers really only need a fwnode and a struct device to hang devres-allocated resourses on, add a pure dev-based get/put API alongside the existing psy-based one, which can be used to query the battery information before registering the power supply. Signed-off-by: Alexey Charkov --- drivers/power/supply/power_supply_core.c | 102 ++++++++++++++++++++++-----= ---- include/linux/power_supply.h | 4 ++ 2 files changed, 77 insertions(+), 29 deletions(-) diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/suppl= y/power_supply_core.c index 1279785645fb..09473361772f 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -725,21 +725,18 @@ struct power_supply *devm_power_supply_get_by_referen= ce(struct device *dev, } EXPORT_SYMBOL_GPL(devm_power_supply_get_by_reference); =20 -int power_supply_get_battery_info(struct power_supply *psy, - struct power_supply_battery_info **info_out) +static int __power_supply_get_battery_info(struct device *dev, + struct fwnode_handle *srcnode, + struct power_supply_battery_info **info_out) { struct power_supply_resistance_temp_table *resist_table; struct power_supply_battery_info *info; - struct fwnode_handle *srcnode, *fwnode; + struct fwnode_handle *fwnode; const char *value; int err, len, index, proplen; u32 *propdata __free(kfree) =3D NULL; u32 min_max[2]; =20 - srcnode =3D dev_fwnode(&psy->dev); - if (!srcnode && psy->dev.parent) - srcnode =3D dev_fwnode(psy->dev.parent); - fwnode =3D fwnode_find_reference(srcnode, "monitored-battery", 0); if (IS_ERR(fwnode)) return PTR_ERR(fwnode); @@ -750,7 +747,7 @@ int power_supply_get_battery_info(struct power_supply *= psy, =20 =20 /* Try static batteries first */ - err =3D samsung_sdi_battery_get_info(&psy->dev, value, &info); + err =3D samsung_sdi_battery_get_info(dev, value, &info); if (!err) goto out_ret_pointer; else if (err =3D=3D -ENODEV) @@ -765,7 +762,7 @@ int power_supply_get_battery_info(struct power_supply *= psy, goto out_put_node; } =20 - info =3D devm_kzalloc(&psy->dev, sizeof(*info), GFP_KERNEL); + info =3D devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); if (!info) { err =3D -ENOMEM; goto out_put_node; @@ -826,7 +823,7 @@ int power_supply_get_battery_info(struct power_supply *= psy, else if (!strcmp("lithium-ion-manganese-oxide", value)) info->technology =3D POWER_SUPPLY_TECHNOLOGY_LiMn; else - dev_warn(&psy->dev, "%s unknown battery type\n", value); + dev_warn(dev, "%s unknown battery type\n", value); } =20 fwnode_property_read_u32(fwnode, "energy-full-design-microwatt-hours", @@ -877,7 +874,7 @@ int power_supply_get_battery_info(struct power_supply *= psy, err =3D len; goto out_put_node; } else if (len > POWER_SUPPLY_OCV_TEMP_MAX) { - dev_err(&psy->dev, "Too many temperature values\n"); + dev_err(dev, "Too many temperature values\n"); err =3D -EINVAL; goto out_put_node; } else if (len > 0) { @@ -892,28 +889,28 @@ int power_supply_get_battery_info(struct power_supply= *psy, char *propname __free(kfree) =3D kasprintf(GFP_KERNEL, "ocv-capacity-tab= le-%d", index); if (!propname) { - power_supply_put_battery_info(psy, info); + power_supply_put_battery_info_from_dev(dev, info); err =3D -ENOMEM; goto out_put_node; } proplen =3D fwnode_property_count_u32(fwnode, propname); if (proplen < 0 || proplen % 2 !=3D 0) { - dev_err(&psy->dev, "failed to get %s\n", propname); - power_supply_put_battery_info(psy, info); + dev_err(dev, "failed to get %s\n", propname); + power_supply_put_battery_info_from_dev(dev, info); err =3D -EINVAL; goto out_put_node; } =20 u32 *propdata __free(kfree) =3D kzalloc_objs(*propdata, proplen); if (!propdata) { - power_supply_put_battery_info(psy, info); + power_supply_put_battery_info_from_dev(dev, info); err =3D -EINVAL; goto out_put_node; } err =3D fwnode_property_read_u32_array(fwnode, propname, propdata, propl= en); if (err < 0) { - dev_err(&psy->dev, "failed to get %s\n", propname); - power_supply_put_battery_info(psy, info); + dev_err(dev, "failed to get %s\n", propname); + power_supply_put_battery_info_from_dev(dev, info); goto out_put_node; } =20 @@ -921,9 +918,9 @@ int power_supply_get_battery_info(struct power_supply *= psy, info->ocv_table_size[index] =3D tab_len; =20 info->ocv_table[index] =3D table =3D - devm_kcalloc(&psy->dev, tab_len, sizeof(*table), GFP_KERNEL); + devm_kcalloc(dev, tab_len, sizeof(*table), GFP_KERNEL); if (!info->ocv_table[index]) { - power_supply_put_battery_info(psy, info); + power_supply_put_battery_info_from_dev(dev, info); err =3D -ENOMEM; goto out_put_node; } @@ -939,14 +936,14 @@ int power_supply_get_battery_info(struct power_supply= *psy, err =3D 0; goto out_ret_pointer; } else if (proplen < 0 || proplen % 2 !=3D 0) { - power_supply_put_battery_info(psy, info); + power_supply_put_battery_info_from_dev(dev, info); err =3D (proplen < 0) ? proplen : -EINVAL; goto out_put_node; } =20 propdata =3D kzalloc_objs(*propdata, proplen); if (!propdata) { - power_supply_put_battery_info(psy, info); + power_supply_put_battery_info_from_dev(dev, info); err =3D -ENOMEM; goto out_put_node; } @@ -954,17 +951,17 @@ int power_supply_get_battery_info(struct power_supply= *psy, err =3D fwnode_property_read_u32_array(fwnode, "resistance-temp-table", propdata, proplen); if (err < 0) { - power_supply_put_battery_info(psy, info); + power_supply_put_battery_info_from_dev(dev, info); goto out_put_node; } =20 info->resist_table_size =3D proplen / 2; - info->resist_table =3D resist_table =3D devm_kcalloc(&psy->dev, + info->resist_table =3D resist_table =3D devm_kcalloc(dev, info->resist_table_size, sizeof(*resist_table), GFP_KERNEL); if (!info->resist_table) { - power_supply_put_battery_info(psy, info); + power_supply_put_battery_info_from_dev(dev, info); err =3D -ENOMEM; goto out_put_node; } @@ -982,22 +979,69 @@ int power_supply_get_battery_info(struct power_supply= *psy, fwnode_handle_put(fwnode); return err; } + +int power_supply_get_battery_info(struct power_supply *psy, + struct power_supply_battery_info **info_out) +{ + struct fwnode_handle *srcnode; + + srcnode =3D dev_fwnode(&psy->dev); + if (!srcnode && psy->dev.parent) + srcnode =3D dev_fwnode(psy->dev.parent); + + return __power_supply_get_battery_info(&psy->dev, srcnode, info_out); +} EXPORT_SYMBOL_GPL(power_supply_get_battery_info); =20 -void power_supply_put_battery_info(struct power_supply *psy, - struct power_supply_battery_info *info) +/** + * power_supply_get_battery_info_from_dev() - Get battery info without a s= upply + * @dev: Device holding the "monitored-battery" reference, which also owns= the + * devres allocations made for the returned info + * @info_out: Pointer to store the resulting battery info + * + * Same as power_supply_get_battery_info(), but keyed off a plain device r= ather + * than a registered power supply. Chargers that program hardware limits t= aken + * from the battery node need those values *before* they can safely regist= er + * their power supply: registering makes the supply callable, so a later p= robe + * failure would free driver data underneath a running callback. + * + * Release the result with power_supply_put_battery_info_from_dev(). + * + * Return: 0 on success or an error code on failure. + */ +int power_supply_get_battery_info_from_dev(struct device *dev, + struct power_supply_battery_info **info_out) +{ + return __power_supply_get_battery_info(dev, dev_fwnode(dev), info_out); +} +EXPORT_SYMBOL_GPL(power_supply_get_battery_info_from_dev); + +/** + * power_supply_put_battery_info_from_dev() - Release battery info + * @dev: Device passed to power_supply_get_battery_info_from_dev() + * @info: Battery info to release + */ +void power_supply_put_battery_info_from_dev(struct device *dev, + struct power_supply_battery_info *info) { int i; =20 for (i =3D 0; i < POWER_SUPPLY_OCV_TEMP_MAX; i++) { if (info->ocv_table[i]) - devm_kfree(&psy->dev, info->ocv_table[i]); + devm_kfree(dev, info->ocv_table[i]); } =20 if (info->resist_table) - devm_kfree(&psy->dev, info->resist_table); + devm_kfree(dev, info->resist_table); + + devm_kfree(dev, info); +} +EXPORT_SYMBOL_GPL(power_supply_put_battery_info_from_dev); =20 - devm_kfree(&psy->dev, info); +void power_supply_put_battery_info(struct power_supply *psy, + struct power_supply_battery_info *info) +{ + power_supply_put_battery_info_from_dev(&psy->dev, info); } EXPORT_SYMBOL_GPL(power_supply_put_battery_info); =20 diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 131cafded72f..f42ae4e3bf81 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -865,6 +865,10 @@ extern int power_supply_get_battery_info(struct power_= supply *psy, struct power_supply_battery_info **info_out); extern void power_supply_put_battery_info(struct power_supply *psy, struct power_supply_battery_info *info); +extern int power_supply_get_battery_info_from_dev(struct device *dev, + struct power_supply_battery_info **info_out); +extern void power_supply_put_battery_info_from_dev(struct device *dev, + struct power_supply_battery_info *info); extern bool power_supply_battery_info_has_prop(struct power_supply_battery= _info *info, enum power_supply_property psp); extern int power_supply_battery_info_get_prop(struct power_supply_battery_= info *info, --=20 2.55.0 From nobody Fri Sep 25 18:27:11 2026 Received: from mail-wm2-f12.google.com (mail-wm2-f12.google.com [74.125.225.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 18DA557267E for ; Wed, 9 Sep 2026 15:42:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.225.140 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788968535; cv=none; b=MG36/PbHcAIhqb0MpAq9gdz+ap/7VTBu8m1YDVtAFFafZ49vB6wNw885/ShVojRsk2SIRS9B8ZRK7A1OevghsBfLt1z+Xthdqwi8VCpFqEyNCDu/aiKz9CdhcZ8nIosFqgFPHLITcTpIvRGqx/UrplIDC9c8yEYXLPB+dW8KJ/A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788968535; c=relaxed/simple; bh=puqbhfoUN1h0hVmNuH0sDEYWMQDzUtBnG/jCV80xhEI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KE9SKjLKH0ef9/phkqLC1rVSOEMRL3kyWj9p+JmEEMxJcc3JPTs1yL414nkJoL0ILIoBR8vVQFwrWtN03sHC9UE5Zx70pHwDgZGT0bJrgecj0Nrzp2DwLpJd9s8YRrg4uGcE+pMx+MbowYSHplmL7lfQW1X05Dx21ATTG7pjal0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=flipper.net; spf=pass smtp.mailfrom=flipper.net; dkim=pass (2048-bit key) header.d=flipper.net header.i=@flipper.net header.b=cQ+wrfL/; arc=none smtp.client-ip=74.125.225.140 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=flipper.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flipper.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=flipper.net header.i=@flipper.net header.b="cQ+wrfL/" Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49b912e2406so10185655e9.1 for ; Wed, 09 Sep 2026 08:42:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=flipper.net; s=google; t=1788968532; x=1789573332; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=xZ2NMqgSdO9GLsjUUfKBwt+Y9+3g0pO5mWSs9o4+92M=; b=cQ+wrfL/2kn1Rwt8oJhk898KpHs/AVKnITX733vwmmURdGklXbf0dEEupISDzOtRyC XArGwPt72724nFN2UuGZ76ZDtjacEeDC8KWehRQPIxnApoG1OxAGIOj8K3TmE3mJ5OE9 ffWwlIF6msvO170hz/ZW31zDl8I3gsVQG1BOs7LtECYrVo2Q7YBMJWyswggx0y+W7YdN 6caXsCkMyHecTAAoCIE5R+52yiktrRV7Cak9NP3acVXW1HJjAwtZaxSzv3IO0kzqVJ87 ySSzTkonyy17pL2+1IPfUC3Vu9LU3GVaKmyrRZdFPcUcSm1ouDDwZ4+gCF7CYu7mq6uN 69nw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788968532; x=1789573332; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=xZ2NMqgSdO9GLsjUUfKBwt+Y9+3g0pO5mWSs9o4+92M=; b=NIfpX6yUUujGcWFoWmr/J5VLHnf7XgRj0A2bOHcK6Cw3PDfwcwDY7/AYm02gC00gIZ GsfiaOrywlmc6Iz4f8SEXBTZwauMGV/o81/4aV/zQt6Um7YEk495vhadT9SYnfvC+qKM OzuFritSKmj8BX15nCy+KLA+oGehA0eoGaiU1A5vqDtVx8U+IcRjAbgR1tzV2KDq7iQ8 pMMY31/mRki8SXks7sJhhK4tHxMBfUlUyyqxGX6MI7PLleio6QM6qK7QOp0NYkX9OXTF HE9qbpbrp2jNaDjXJRGIr2UqR6Y2SloqduY28u3mutVVkTNgDgFteqmMcZ0665YmwTRW ngWg== X-Forwarded-Encrypted: i=1; AKwUvBzWmX7GEw+5/8BBMdo9Eg50S0CpP+REPKlU/T86L+l/EHJ8TRZlNMsXizdHB37uMplns33RJolRkB5IqeM=@vger.kernel.org X-Gm-Message-State: AFuF++lktiIOJhLzlfcYj78hfrUSfqsysML+4fjDuA/+pYR0ugWAgiFb Z+Pl4zwCZsrH6lQTMh3MHZqkpTW05mrNLqxt2PHdS0jgHZ4i8O42WFThjNqduKXf1bY= X-Gm-Gg: AYBFou3mC8oW1hakj2swRakYioEAqfGTt5z1E9qFq951Q/lKjgs6XrPjlWS3Mj1jk24 mSF1mZJq/k9DhvFCqsslf63tR4gGQfNvc5ix8OIzK8tnCZfiIYePYzBFhJijmD+MS58Uj87eubm ViCHUlZiikDNNmIOplgq6Is7xxZ9+WFxnzXWWaCWns1xfDCS6Va197hB7JL4/9OH93YYHNlwAZH 9mMvIWQYFvfx+88JfNmba0WT7XJfSJ/iE7hkYKBEksfKjxD6CAF2K0HWc9R9bjaTvGgG7uGzE17 t1Kw8gcF7FFnwPcR/mtkbVKMU4pfCR891cQJq+/vBMnSUrLEoqpuww6CaheBIctyyx/gHBx7q5j yrwG4MOmnJpaIVN/JMEkiR8SBiRkoodSO6/TKqLFwCo7/hKoPNvqrHlb7LTzKkN/IRfb2/5QeXv hs0VUFiEKGPyUUGGPq6MnsIjM6MlNnpLiw/EJ8uwXnYfr+4HM3vmzhaLYgKzmWqdNfR6IjFsZ0q e+UUpeDHfiO9fElv/IKwyY1s+J72wevF01ZU/AwrJpUvSNG1Mw= X-Received: by 2002:a05:600c:6216:b0:49c:799a:177b with SMTP id 5b1f17b1804b1-49d1754394emr171890905e9.2.1788968532280; Wed, 09 Sep 2026 08:42:12 -0700 (PDT) Received: from alchark-surface.localdomain (bba-2-51-220-108.alshamil.net.ae. [2.51.220.108]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49cf7740d44sm1042068015e9.15.2026.09.09.08.42.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 08:42:11 -0700 (PDT) From: Alexey Charkov Date: Wed, 09 Sep 2026 19:41:46 +0400 Subject: [PATCH v2 3/4] power: supply: bq257xx: Use psy directly instead of driver data Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-bq257xx-init-v2-3-deb4076b1f02@flipper.net> References: <20260909-bq257xx-init-v2-0-deb4076b1f02@flipper.net> In-Reply-To: <20260909-bq257xx-init-v2-0-deb4076b1f02@flipper.net> To: Sebastian Reichel , Lee Jones , Chris Morgan , Pavel Machek , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz Cc: Sebastian Reichel , linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, Alexey Charkov X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1213; i=alchark@flipper.net; h=from:subject:message-id; bh=puqbhfoUN1h0hVmNuH0sDEYWMQDzUtBnG/jCV80xhEI=; b=owGbwMvMwCW2adGNfoHIK0sZT6slMWQtrHNL/Mq6LiMnM/fkt50nlaPbfCsCi5lWTbwt5ZwbN zfh7KGrHRNZGMS4GCzFFFnmfltiO9WIb9YuD4+vMHNYmUCGSIs0MAABCwNfbmJeqZGOkZ6ptqGe oZGOsY4RAxenAEz17ySG/5XLr5durz26SHHOlbz7THMuL7k55d2VbQccd2eKsFsVdX5gZPik0nn krqWlkBrLLD3Nits6279w7ebdp++8/UTxPJ7FvnwA X-Developer-Key: i=alchark@flipper.net; a=openpgp; fpr=9DF6A43D95320E9ABA4848F5B2A2D88F1059D4A5 bq257xx_external_power_changed() is handed the power supply it is called for, but passes pdata->charger to power_supply_am_i_supplied(). Those are not equivalent during probe or teardown, and a supplier's changed_work can reach power_supply_external_power_changed() when pdata->charger doesn't point anywhere meaningful (e.g. freed memory during teardown). Use the psy argument, which is valid whenever the callback runs. Fixes: 1cc017b7f9c7 ("power: supply: bq257xx: Add support for BQ257XX charg= er") Signed-off-by: Alexey Charkov --- drivers/power/supply/bq257xx_charger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/bq257xx_charger.c b/drivers/power/supply/= bq257xx_charger.c index b735bb02a8e0..ab3519454193 100644 --- a/drivers/power/supply/bq257xx_charger.c +++ b/drivers/power/supply/bq257xx_charger.c @@ -1055,7 +1055,7 @@ static void bq257xx_external_power_changed(struct pow= er_supply *psy) =20 pdata->chip->bq257xx_get_state(pdata); =20 - pdata->supplied =3D power_supply_am_i_supplied(pdata->charger); + pdata->supplied =3D power_supply_am_i_supplied(psy); if (pdata->supplied < 0) return; =20 --=20 2.55.0 From nobody Fri Sep 25 18:27:11 2026 Received: from mail-wm2-f12.google.com (mail-wm2-f12.google.com [74.125.225.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D728576EBD for ; Wed, 9 Sep 2026 15:42:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.225.140 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788968538; cv=none; b=cQI2tjo8oi076nRwR66JHGElsaDzD99ywuf3RRcH5gdhkbTz0mlqjAfabcyDJn74H0FO3v5fSq2+0s6DFSTV61Z0LoCYx/DX4keEW63qT+sOsmBNWJ6dl9wKlY44SgGhJKrgL91efYU5hFOGk++ewckcNttMinA8L7xGnh2Yaes= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788968538; c=relaxed/simple; bh=hq4YQs4noVM+rPsJgnR/8SpC8jKglHwZ0DNfFfqjORo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SOKMUd2I5HOvp95tJTJ+bBwuIKFZmmIy33ArawE0/GLn2wVSWW1C1xRgBpVKBtZQmlaUJL8O4Y5IF4A3IxOyD+KlGAvLuESeYkvFZ2dH8psGQSQFunrsbsb9WYM6USsN314+vctgFaoNuXTIy74QR9g7SrX7SzB12p7ecO8mCW0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=flipper.net; spf=pass smtp.mailfrom=flipper.net; dkim=pass (2048-bit key) header.d=flipper.net header.i=@flipper.net header.b=aoNn0W62; arc=none smtp.client-ip=74.125.225.140 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=flipper.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flipper.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=flipper.net header.i=@flipper.net header.b="aoNn0W62" Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49cd38e0e5dso4733355e9.2 for ; Wed, 09 Sep 2026 08:42:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=flipper.net; s=google; t=1788968535; x=1789573335; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=F0u+L+nVL9C1tUREs61N7WVbEpyXchQ6479yncGceLg=; b=aoNn0W62kDQ3Oe+94dtP0gJWE5L0PQ+s7Bk0hXHjxUCJ8ULldYsFsucghSkdO1H//F UHAOUP7Ez7NBkcLmfHXOV24YIwNWsbrs4dyFb5+XvDabeNC4N2sOzciH70Pt9uXGPHul slnMmVoqh/N8/WaM5ILcUlzFJShvCNhJ3PC2B/uVVozCwPRvVFurkEwPaCdrHhc69stZ zVzn5SUbPipMssXlZ/HLOJFxkeTetU9tiMyfk4+FasYQRutHBo6P1ZFAY2tmLSikqda+ C9BXYE4tCn0WWpTfoOTt3xIf9DEzPDmJo2NaIi9kFkR7tTO52XI/JWCClesppj/mlyAI qQ/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788968535; x=1789573335; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=F0u+L+nVL9C1tUREs61N7WVbEpyXchQ6479yncGceLg=; b=hsCCA9IM/1OeoXymRK31eBXlZM7A+n7CEKb8pbC2KM3mHtAYYEqiSnNNJphZdwFePd qbgCkRmhKiT2ulouPmvc9xgon6/JUhCjOgD/Yqv7gC8CBwk047cYy+YGmxphjIHz8YK+ iZzojEyIhtK5OSw1LoMZ7BgTH6JBOhHfwhjD6Bo32XDuKH8gUbQo+mpyuq02L1zNChqm /MFojcDIKhUlhB3KWHr0pUOW/IBEIH4srkClgvxxhe8YasE1L1aIXu5+sOxhz45t8Afs Fzx4pZ/LI5EWDPNZUROM/h0rw2ipX3BucqXNiyr59F65zgqvzobBPJ0zTiBrXPj6NM4e SY1A== X-Forwarded-Encrypted: i=1; AKwUvBxENsNNhHMH557aWlUFKQ7vo4tHSxN7M01Z0Bn2TrR//JncaO38zsuoXEllrZo0lKy1Rs9J8ZAfwOmeZwY=@vger.kernel.org X-Gm-Message-State: AFuF++kI4IUw02ZBKFpCTmzfJuZnVcn44pwK5M5Zun1TO+rqhTazsJET KQxyetT5QEyo1biFhpNC1+kwX3XpzYP+quPb880Mlul7CPyvsG3SNxFufVnWxkGj1rw= X-Gm-Gg: AYBFou350N3L5G9gHGUgsMZT6tzF99pvo7t2a2O2ZFFCFV2aCA2fv2u66GcghK3EysO kcKa4IcE75TCOQzUtM4NEXbzsIDg6CIarfiEk8SCZEv4KLMVq8FqSVOiNILmiqPLLPcHMwEgeyE yvIZ0GCOfDCc1iBiYpZ23tY+Iy+E8KpkwHLfj/KMnBjGSIXACDdcSxxm/1CL3YkXLlID6T6E48W G1M2n/XSIUbOk+t4/S4k78i2sM0yq/DQzMqgO1sWvUMFBgCloB+rGQr46TrS9eIHNY/NHysO+O6 ahsb6K0x1GrnCOwGx0eSGqq9til9y4h0L/+LBdifV7PG8DeMNfLuL7fCIkX4Fo23sXHGaS3XQfT Wz1slyGfpLseJuLDrSnEJfemZKJcuv1EWl/pLZAn+g+h0IwdXH8Hwe1HzhKi7eO4Dd9ANuSXCv3 HA92ME2gUFZi//4BzXsc/Oohzj7xiuGyS1Pa8oa0Y3xK9FKu7NDtyWjA88l82lS1QoXHKzD6ADS KdQdEn+hECATznkrflDvOciFKz5Z2b2UQ3Eo/j83a/T1GEIh/o= X-Received: by 2002:a05:600c:1d9a:b0:498:943:ccc0 with SMTP id 5b1f17b1804b1-49d258ef83amr41366425e9.6.1788968534764; Wed, 09 Sep 2026 08:42:14 -0700 (PDT) Received: from alchark-surface.localdomain (bba-2-51-220-108.alshamil.net.ae. [2.51.220.108]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49cf7740d44sm1042068015e9.15.2026.09.09.08.42.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 08:42:14 -0700 (PDT) From: Alexey Charkov Date: Wed, 09 Sep 2026 19:41:47 +0400 Subject: [PATCH v2 4/4] power: supply: bq257xx: Parse battery info before registering power supply Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-bq257xx-init-v2-4-deb4076b1f02@flipper.net> References: <20260909-bq257xx-init-v2-0-deb4076b1f02@flipper.net> In-Reply-To: <20260909-bq257xx-init-v2-0-deb4076b1f02@flipper.net> To: Sebastian Reichel , Lee Jones , Chris Morgan , Pavel Machek , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz Cc: Sebastian Reichel , linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, Alexey Charkov X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=4653; i=alchark@flipper.net; h=from:subject:message-id; bh=hq4YQs4noVM+rPsJgnR/8SpC8jKglHwZ0DNfFfqjORo=; b=owGbwMvMwCW2adGNfoHIK0sZT6slMWQtrHOz+rDvXhzv1arCxV0XFa5tYXQqZOt78n2u0Ib8Z PVNl7iWd0xkYRDjYrAUU2SZ+22J7VQjvlm7PDy+wsxhZQIZIi3SwAAELAx8uYl5pUY6Rnqm2oZ6 hkY6xjpGDFycAjDV6yUZGZ5/7D/apLJm1x1H72xWjzC2uh0prbvPHg8LOhbot2eehzTDH26WJ+Z 8BtMEBJTKljQc973nIGu18uBhw++XEv58mvqxhwMA X-Developer-Key: i=alchark@flipper.net; a=openpgp; fpr=9DF6A43D95320E9ABA4848F5B2A2D88F1059D4A5 Switch to a dev-based battery get/put interface to parse battery info before registering the power supply, so that nobody tries to access the power supply until we finish programming the device parameters. Signed-off-by: Alexey Charkov --- drivers/power/supply/bq257xx_charger.c | 50 ++++++++++++++++++++----------= ---- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/drivers/power/supply/bq257xx_charger.c b/drivers/power/supply/= bq257xx_charger.c index ab3519454193..a02d293c7395 100644 --- a/drivers/power/supply/bq257xx_charger.c +++ b/drivers/power/supply/bq257xx_charger.c @@ -1163,38 +1163,38 @@ static const struct bq257xx_chip_info bq25792_chip_= info =3D { /** * bq257xx_parse_dt() - Parse the device tree for required properties * @pdata: driver platform data - * @psy_cfg: power supply config data * @dev: device struct * * Read the device tree to identify the minimum system voltage, the * maximum charge current, the maximum charge voltage, and the maximum - * input current. + * input current. Deliberately keyed off @dev rather than the charger power + * supply, so that it can run before the supply is registered. * * Return: Returns 0 on success or error code on error. */ -static int bq257xx_parse_dt(struct bq257xx_chg *pdata, - struct power_supply_config *psy_cfg, struct device *dev) +static int bq257xx_parse_dt(struct bq257xx_chg *pdata, struct device *dev) { struct power_supply_battery_info *bat_info; int ret; =20 - ret =3D power_supply_get_battery_info(pdata->charger, - &bat_info); + ret =3D power_supply_get_battery_info_from_dev(dev, &bat_info); if (ret) return dev_err_probe(dev, ret, "Unable to get battery info\n"); =20 if ((bat_info->voltage_min_design_uv <=3D 0) || (bat_info->constant_charge_voltage_max_uv <=3D 0) || - (bat_info->constant_charge_current_max_ua <=3D 0)) + (bat_info->constant_charge_current_max_ua <=3D 0)) { + power_supply_put_battery_info_from_dev(dev, bat_info); return dev_err_probe(dev, -EINVAL, "Required bat info missing or invalid\n"); + } =20 pdata->vsys_min =3D bat_info->voltage_min_design_uv; pdata->vbat_max =3D bat_info->constant_charge_voltage_max_uv; pdata->ichg_max =3D bat_info->constant_charge_current_max_ua; =20 - power_supply_put_battery_info(pdata->charger, bat_info); + power_supply_put_battery_info_from_dev(dev, bat_info); =20 ret =3D device_property_read_u32(dev, "input-current-limit-microamp", @@ -1210,9 +1210,14 @@ static int bq257xx_parse_dt(struct bq257xx_chg *pdat= a, * @pdev: platform device * * Probe the charger device, allocate driver data structure, select the - * appropriate chip-specific function pointers, register the power supply, - * parse device tree properties for battery limits, initialize hardware, - * and set up the interrupt handler if available. + * appropriate chip-specific function pointers, parse device tree properti= es + * for battery limits, initialize hardware, register the power supply, and= set + * up the interrupt handler if available. + * + * The power supply is registered only once the hardware is up, because + * registering it lets the core call ->external_power_changed() at any tim= e. A + * probe failure after that point would have devres free @pdata while such= a + * callback is still running on it. * * Return: Returns 0 on success or error code on failure. */ @@ -1245,6 +1250,14 @@ static int bq257xx_charger_probe(struct platform_dev= ice *pdev) =20 platform_set_drvdata(pdev, pdata); =20 + ret =3D bq257xx_parse_dt(pdata, dev); + if (ret) + return ret; + + ret =3D pdata->chip->bq257xx_hw_init(pdata); + if (ret) + return dev_err_probe(dev, ret, "Cannot initialize the charger\n"); + psy_cfg.drv_data =3D pdata; psy_cfg.fwnode =3D dev_fwnode(dev); =20 @@ -1255,16 +1268,11 @@ static int bq257xx_charger_probe(struct platform_de= vice *pdev) return dev_err_probe(dev, PTR_ERR(pdata->charger), "Power supply register charger failed\n"); =20 - ret =3D bq257xx_parse_dt(pdata, &psy_cfg, dev); - if (ret) - return ret; - - ret =3D pdata->chip->bq257xx_hw_init(pdata); - if (ret) - return dev_err_probe(dev, ret, "Cannot initialize the charger\n"); - - platform_set_drvdata(pdev, pdata); - + /* + * Requested after the supply is registered so that devres tears it down + * first, quiescing the interrupt before the supply it reports on goes + * away. + */ if (bq->client->irq) { ret =3D devm_request_threaded_irq(dev, bq->client->irq, NULL, bq257xx_irq_handler_thread, --=20 2.55.0