From nobody Mon Feb 9 01:21:09 2026 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (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 02D67230BCC for ; Mon, 5 Jan 2026 14:16:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767622577; cv=none; b=VAzlLqamQit75e68PAz67D05CLMeO0zGXei5wG3NbIU/MnJtEJJYgK3F2mFyNP3P/1V4oGzHisrlgug6O76zFVj7uECumDEE30xTZEzU68709uXpJ9ByQ25LM1vnssBGfGShuQGppMU4WwCEKnwj9JxsH2gdNHlYcJi+4bP04q4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767622577; c=relaxed/simple; bh=Q/9ydyqgWlC7G/Ll1xIXU0tlasgJPO5S9952wX8thhE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=erWlKC0g4/KyMDvvcyJ1MyOBFObBybfvL06jBRkw7jhC92NyfK0ohvc1DBKQXXf5Os28UgwNeM3jNrwjzX2+0ZHGHc0vqZlvrdvGS6fIlTQ3Po0+d44HZG6v57Jnk2cUzWvM+DIgMhsJ/3U7N1LvrXLOitWG0OX4+ICShJaguSU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=k/umUtWC; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=S2pZ/ivn; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="k/umUtWC"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="S2pZ/ivn" Received: from pps.filterd (m0279867.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6058w84G593923 for ; Mon, 5 Jan 2026 14:16:14 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= x2R65rdVq6O1ohPjRkX9Q9XnBbonnHsuOI4OfPjIU+w=; b=k/umUtWCVX8XeBuI hzt43o3SIcphI33y0oq7m1ku5EM2aRrLVBur8acTTn+GyBV3OTA63RN9IERn+Y5w yckvwTetB2LHo58F0KeIHgukK2jjyjbjRQgg2S0ERSA+bXtNRdlBNL4l7c++QXoC 0b4PNc1wXOXysq08NRMmxjbaDXfhQQKsmN91jD73on9gUv00Va8kyNSZNKZEtmq4 1ZmFm9DOYLhDnJ18j1POpD6wZnT5BFP/G39nPrVIgMhrFsYKlN3OBQfkR6hqhfFr ZlK+h+p06oiN/+SAHOQ7pqY+MFGj5L1qrTrUjG+FeNn8TPstv0w986c4uxUlCnRf fD7/Mw== Received: from mail-vk1-f199.google.com (mail-vk1-f199.google.com [209.85.221.199]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4bga8pgt8f-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Mon, 05 Jan 2026 14:16:14 +0000 (GMT) Received: by mail-vk1-f199.google.com with SMTP id 71dfb90a1353d-55b26ece522so14865343e0c.2 for ; Mon, 05 Jan 2026 06:16:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1767622573; x=1768227373; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=x2R65rdVq6O1ohPjRkX9Q9XnBbonnHsuOI4OfPjIU+w=; b=S2pZ/ivnl5ZEJDpwEGef95N/6MXrHfdrjErH8DDsIw8/hCVOR6R3RfDchxXH/9/iG0 Rsy6KDQxQE7PwWR0ceAFjco2NhFxxLCU6U/pHydh+I56Dglkvv11KZ5Qp24njoZM+aya zEUQPhAAwioYXSqXafp7Sw8i0wBeAdsY+6OaqGYgf83ETc5DsH8Zw1dbr9g/iu96r9kT ONVkpi+QNWZDkk2kmAowe0ZX4OhUidFRKtCjmZMwPI5uesyW/hEJnLkdB8v67bxXc5pD S7LacDuk9bfL0+oBnWstZ2xWgl1EFfJU7PFHHjo1cRE2gV2UeiVFlilrPXunoYMdqmCE /8UA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767622573; x=1768227373; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=x2R65rdVq6O1ohPjRkX9Q9XnBbonnHsuOI4OfPjIU+w=; b=Y3H8w8Oq85W5r1uu2Cyd/Wui7GZSUYathK8I8levZzf5yMYqoR0TOX0qVAl8Wqon2Y 4orTAcTTqQ/zPp06snmHb7FoEw4huXkQTeKNHrNGY9taiX/2mTMSc9z7y83Hpf43fJ7G yXW345iFiX0ub/QsE0VuE1MJtBB7jVlRhfB3MiSNn0VCd64YJvK+wlL0yrGY2mFTqqYX IeeA9pZOdAY9fjz3TNtTxq69ctBxnVtzJBiL90SlQNy43fY1HqtXpbiMjwBViU21yEEf COBeiiWi6A7jPltWZ8ghvOb2XUReFpT0Jq0sjNOMmF6RlwKcaoZu1NU5GJLwpu0mMU9d jgVw== X-Gm-Message-State: AOJu0Yxfz7qjNby2K74BeeTIqo9V5iLucgSqOUzbA3C1aCk6uuakut7U ggdgsSa9aQxs9Gne8vvSXhW9V1/KlET67NiEMnZIW2NMzfdi2E7GXDD09BT+ShVf1f8oOyPwyGB TVVfGA0KlowEJ6lYkYVaRyB0KPbeHQ/M4yTU8s6+2YCnlqevJ3Pn/oTnd1QQoHaLsWEI= X-Gm-Gg: AY/fxX4h3vcwUsNfQLdVKiFCt3RfbJYi2c84npcpWQfZJi7IMg3etB2pSyZJO6fMT8U i5FbASMRCMh+OaPswp9tB3TK/cagcv/rrywBlRhuXLpLuINmf5dzISioXtceIhdeqN7/nHqF6Ig ymrADi+pKjZAgR4QE7ZQlRAgnd+WOeeIF10NQNnVp0nUhA6jQTeRE2zH/do8QZsW5DTetGdfw5A Czzww0ae22A5RWqSnaTpIq6m9EOUMGLeY+l0+CUmu+3kqqanSsBlN7S0/Jt/0xHNWlpI+38sk2o ds218zy7VeCtCP3VP2XlOONhePbomvmPmQYNP8rKXgpl94qHuxEYItVKXNmQAMElrbtgLSq0f8U xNVEocW6i8UaixPFkqXVTWFJy6qRmnvZCyYIODe8= X-Received: by 2002:a05:6122:180d:b0:559:7294:da85 with SMTP id 71dfb90a1353d-5615be31c9fmr13517484e0c.12.1767622572894; Mon, 05 Jan 2026 06:16:12 -0800 (PST) X-Google-Smtp-Source: AGHT+IG+VjPf+qeJFtf3bkoUAR8vN9R0AZ9XejBMxsKRObXJyNKvjXH1SHhnoE0Cl5Ibcuqy0UkL2g== X-Received: by 2002:a05:6122:180d:b0:559:7294:da85 with SMTP id 71dfb90a1353d-5615be31c9fmr13517452e0c.12.1767622572336; Mon, 05 Jan 2026 06:16:12 -0800 (PST) Received: from brgl-qcom.local ([2a01:cb1d:dc:7e00:dd3b:c635:dd06:9574]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-4324ea1aef7sm100774703f8f.7.2026.01.05.06.16.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Jan 2026 06:16:11 -0800 (PST) From: Bartosz Golaszewski Date: Mon, 05 Jan 2026 15:15:28 +0100 Subject: [PATCH 09/15] reset: handle removing supplier before consumers 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: <20260105-reset-core-refactor-v1-9-ac443103498d@oss.qualcomm.com> References: <20260105-reset-core-refactor-v1-0-ac443103498d@oss.qualcomm.com> In-Reply-To: <20260105-reset-core-refactor-v1-0-ac443103498d@oss.qualcomm.com> To: Krzysztof Kozlowski , Philipp Zabel Cc: linux-kernel@vger.kernel.org, Bartosz Golaszewski X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=10031; i=bartosz.golaszewski@oss.qualcomm.com; h=from:subject:message-id; bh=Q/9ydyqgWlC7G/Ll1xIXU0tlasgJPO5S9952wX8thhE=; b=owEBbQKS/ZANAwAKAQWdLsv/NoTDAcsmYgBpW8ecxkKr08rQDLASMdh1d7wJ/hz7Cs2wauwr6 OGBtG8q6niJAjMEAAEKAB0WIQSR5RMt5bVGHXuiZfwFnS7L/zaEwwUCaVvHnAAKCRAFnS7L/zaE w0S6D/9QxNau387zFlvEw2Ohb+8O9wo9jhF3wmd77tSeeTsfEsz2yeRGgQ9JsxQDekJPRLFk6xH +TznCB231Ydo2ZCRQbvfaSjpmGFz029CvOMQeHo1viFiIswAMl3oWs+yxBV1vK5Ph5kMYdOzkYL 336MamA6b/fBSukt14vq1erBJNO1tJUGNmm7RBubyCLAiGr+uTMk2RWzPUHOqy/JPJBcsZ8unWN vuY+UVVk45LYKHZRNV/cPU6YV22rRvql/9jXZe0HqBSvUx9S8WS3v11bDtW8HyxQXVO19Vm0bh9 RzwFsf1/0EF45MyjX9ZR6BIzySscE2wRCNTi62jjaq0TV9QDA3axjTbsTZAxanbkt5/K/yR/2zX VuEcJVp6Q2XcvRmXmRzbaXsjwwOPsI5HGj7MNQS8wvaxpVFn/T228NBIaCWfJMKFHVLIJFfev+i rDforg+GV+OWXOZBbro8LQcfdXPkJoTl81HOZhbHW4VJ6VY4QU65J8t/AhzNFo44EB503V0dGgQ fANadbR49fJx1umtZVbxuG/1htgvjreGlaF7sPStG3FzgxAR095XO4HWnvQXTqMf/C9IGtBJFu2 ViFszFy5B5+7+Z0kiTI+bf1SR46zBWQUcXFnGjnDOJMIOMFsLPmUTgDdLrSKCOBpOeHY1q25l83 1uPuJYqKzVVEJSQ== X-Developer-Key: i=bartosz.golaszewski@oss.qualcomm.com; a=openpgp; fpr=169DEB6C0BC3C46013D2C79F11A72EA01471D772 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMTA1MDEyNSBTYWx0ZWRfX2DP9yplsHN/k 8s6tdjjydqsKLa9niNvOjGwq24uLhLSCkHgWhhLDczNGTsvEL3NAXImXTXz/hS9ZKthc+JRLw+U BYm+ITigIZx4Q15cHOReci21Fu1hveWr5Qf6OhRoss/sM5n2vNe9ys5sLX0uqBbVZ1SY4vsl7bV jstr6AN3tp4bYZpNR3tI3IU0lt14xzVClepk4TcRveF2MxIu8u4319SFEYAaQNhyFnvRn4J5f14 HnjCk9fUaQvJGDhuF0lgOh3G/wljodLm0+JMoUsEyxxQCm1cBDIv056cGkHXs/UwSsfwnTI3RRK ep8eiOvpDHTdcMwsUfKGrMGgWAAmspZ8g7JqSNeDqk8jXf2nNCOGZ3JRLFgXG7FbVhygwXD16dE mV/ceSk/PO+qEd0d20NPKjC5696GMNaJhCd3x7O3hqN4sGvO2CcvmhQt3dqdX7AT+s+Ch3BQrhc h8SYLimtafwaDM649yQ== X-Authority-Analysis: v=2.4 cv=JfWxbEKV c=1 sm=1 tr=0 ts=695bc7ae cx=c_pps a=+D9SDfe9YZWTjADjLiQY5g==:117 a=xqWC_Br6kY4A:10 a=IkcTkHD0fZMA:10 a=vUbySO9Y5rIA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=EUspDBNiAAAA:8 a=GiwafSNXLQ0EgbbDNmMA:9 a=QEXdDO2ut3YA:10 a=vmgOmaN-Xu0dpDh8OwbV:22 X-Proofpoint-ORIG-GUID: 8e3AlkIB6OkdvPbPysymX7TN0V6JYMAl X-Proofpoint-GUID: 8e3AlkIB6OkdvPbPysymX7TN0V6JYMAl X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.100.49 definitions=2026-01-05_01,2026-01-05_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 adultscore=0 suspectscore=0 clxscore=1015 priorityscore=1501 malwarescore=0 lowpriorityscore=0 spamscore=0 impostorscore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2512120000 definitions=main-2601050125 Except for the reset-gpio, all reset drivers use device tree - and as such - benefit from the device links set up by driver core. This means, that no reset supplier will be unbound before all its consumers have been. For this reason, nobody bothered making the reset core resiliant to the object life-time issues that are plagueing the kernel. In this case: reset control handles referencing the reset provider device with no serialization or NULL-pointer checking. We now want to make the reset core fwnode-agnostic but before we do, we must make sure it can survive unbinding of suppliers with consumers still holding reset control handles. To that end: use SRCU to protect the rcdev pointer inside struct reset_control. We protect all sections using the pointer with SRCU read-only critical sections and synchronize SRCU after every modification of the pointer. This is in line with what the GPIO subsystem does and what the proposed revocable API tries to generalize. When and if the latter makes its way into the kernel, reset core could potentially also be generalized to use it. Signed-off-by: Bartosz Golaszewski --- drivers/reset/core.c | 108 +++++++++++++++++++++++++++++++++++++++++++----= ---- 1 file changed, 91 insertions(+), 17 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 48eb64654b6de08030674ce3b994021b5f57060e..a7992b8ad1c1fbd974d221544da= 00d4ab3938f70 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -23,6 +23,7 @@ #include #include #include +#include =20 static DEFINE_MUTEX(reset_list_mutex); static LIST_HEAD(reset_controller_list); @@ -36,6 +37,7 @@ static DEFINE_IDA(reset_gpio_ida); * struct reset_control - a reset control * @rcdev: a pointer to the reset controller device * this reset control belongs to + * @srcu: protects the rcdev pointer from removal during consumer access * @list: list entry for the rcdev's reset controller list * @id: ID of the reset controller in the reset * controller device @@ -49,7 +51,8 @@ static DEFINE_IDA(reset_gpio_ida); * will be either 0 or 1. */ struct reset_control { - struct reset_controller_dev *rcdev; + struct reset_controller_dev __rcu *rcdev; + struct srcu_struct srcu; struct list_head list; unsigned int id; struct kref refcnt; @@ -137,15 +140,35 @@ int reset_controller_register(struct reset_controller= _dev *rcdev) } EXPORT_SYMBOL_GPL(reset_controller_register); =20 +static void reset_controller_remove(struct reset_controller_dev *rcdev, + struct reset_control *rstc) +{ + list_del(&rstc->list); + module_put(rcdev->owner); + put_device(rcdev->dev); +} + /** * reset_controller_unregister - unregister a reset controller device * @rcdev: a pointer to the reset controller device */ void reset_controller_unregister(struct reset_controller_dev *rcdev) { + struct reset_control *rstc, *pos; + guard(mutex)(&reset_list_mutex); =20 list_del(&rcdev->list); + + /* + * Numb but don't free the remaining reset control handles that are + * still held by consumers. + */ + list_for_each_entry_safe(rstc, pos, &rcdev->reset_control_head, list) { + rcu_assign_pointer(rstc->rcdev, NULL); + synchronize_srcu(&rstc->srcu); + reset_controller_remove(rcdev, rstc); + } } EXPORT_SYMBOL_GPL(reset_controller_unregister); =20 @@ -322,6 +345,7 @@ static inline bool reset_control_is_array(struct reset_= control *rstc) */ int reset_control_reset(struct reset_control *rstc) { + struct reset_controller_dev *rcdev; int ret; =20 if (!rstc) @@ -333,7 +357,13 @@ int reset_control_reset(struct reset_control *rstc) if (reset_control_is_array(rstc)) return reset_control_array_reset(rstc_to_array(rstc)); =20 - if (!rstc->rcdev->ops->reset) + guard(srcu)(&rstc->srcu); + + rcdev =3D srcu_dereference(rstc->rcdev, &rstc->srcu); + if (!rcdev) + return -ENODEV; + + if (!rcdev->ops->reset) return -ENOTSUPP; =20 if (rstc->shared) { @@ -347,7 +377,7 @@ int reset_control_reset(struct reset_control *rstc) return -EPERM; } =20 - ret =3D rstc->rcdev->ops->reset(rstc->rcdev, rstc->id); + ret =3D rcdev->ops->reset(rcdev, rstc->id); if (rstc->shared && ret) atomic_dec(&rstc->triggered_count); =20 @@ -437,6 +467,8 @@ EXPORT_SYMBOL_GPL(reset_control_rearm); */ int reset_control_assert(struct reset_control *rstc) { + struct reset_controller_dev *rcdev; + if (!rstc) return 0; =20 @@ -446,6 +478,12 @@ int reset_control_assert(struct reset_control *rstc) if (reset_control_is_array(rstc)) return reset_control_array_assert(rstc_to_array(rstc)); =20 + guard(srcu)(&rstc->srcu); + + rcdev =3D srcu_dereference(rstc->rcdev, &rstc->srcu); + if (!rcdev) + return -ENODEV; + if (rstc->shared) { if (WARN_ON(atomic_read(&rstc->triggered_count) !=3D 0)) return -EINVAL; @@ -460,7 +498,7 @@ int reset_control_assert(struct reset_control *rstc) * Shared reset controls allow the reset line to be in any state * after this call, so doing nothing is a valid option. */ - if (!rstc->rcdev->ops->assert) + if (!rcdev->ops->assert) return 0; } else { /* @@ -468,17 +506,17 @@ int reset_control_assert(struct reset_control *rstc) * is no way to guarantee that the reset line is asserted after * this call. */ - if (!rstc->rcdev->ops->assert) + if (!rcdev->ops->assert) return -ENOTSUPP; =20 if (!rstc->acquired) { WARN(1, "reset %s (ID: %u) is not acquired\n", - rcdev_name(rstc->rcdev), rstc->id); + rcdev_name(rcdev), rstc->id); return -EPERM; } } =20 - return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id); + return rcdev->ops->assert(rcdev, rstc->id); } EXPORT_SYMBOL_GPL(reset_control_assert); =20 @@ -525,6 +563,8 @@ EXPORT_SYMBOL_GPL(reset_control_bulk_assert); */ int reset_control_deassert(struct reset_control *rstc) { + struct reset_controller_dev *rcdev; + if (!rstc) return 0; =20 @@ -534,6 +574,12 @@ int reset_control_deassert(struct reset_control *rstc) if (reset_control_is_array(rstc)) return reset_control_array_deassert(rstc_to_array(rstc)); =20 + guard(srcu)(&rstc->srcu); + + rcdev =3D srcu_dereference(rstc->rcdev, &rstc->srcu); + if (!rcdev) + return -ENODEV; + if (rstc->shared) { if (WARN_ON(atomic_read(&rstc->triggered_count) !=3D 0)) return -EINVAL; @@ -543,7 +589,7 @@ int reset_control_deassert(struct reset_control *rstc) } else { if (!rstc->acquired) { WARN(1, "reset %s (ID: %u) is not acquired\n", - rcdev_name(rstc->rcdev), rstc->id); + rcdev_name(rcdev), rstc->id); return -EPERM; } } @@ -555,10 +601,10 @@ int reset_control_deassert(struct reset_control *rstc) * case, the reset controller driver should implement .deassert() and * return -ENOTSUPP. */ - if (!rstc->rcdev->ops->deassert) + if (!rcdev->ops->deassert) return 0; =20 - return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id); + return rcdev->ops->deassert(rcdev, rstc->id); } EXPORT_SYMBOL_GPL(reset_control_deassert); =20 @@ -600,14 +646,22 @@ EXPORT_SYMBOL_GPL(reset_control_bulk_deassert); */ int reset_control_status(struct reset_control *rstc) { + struct reset_controller_dev *rcdev; + if (!rstc) return 0; =20 if (WARN_ON(IS_ERR(rstc)) || reset_control_is_array(rstc)) return -EINVAL; =20 - if (rstc->rcdev->ops->status) - return rstc->rcdev->ops->status(rstc->rcdev, rstc->id); + guard(srcu)(&rstc->srcu); + + rcdev =3D srcu_dereference(rstc->rcdev, &rstc->srcu); + if (!rcdev) + return -ENODEV; + + if (rcdev->ops->status) + return rcdev->ops->status(rcdev, rstc->id); =20 return -ENOTSUPP; } @@ -635,6 +689,7 @@ EXPORT_SYMBOL_GPL(reset_control_status); */ int reset_control_acquire(struct reset_control *rstc) { + struct reset_controller_dev *rcdev; struct reset_control *rc; =20 if (!rstc) @@ -651,7 +706,13 @@ int reset_control_acquire(struct reset_control *rstc) if (rstc->acquired) return 0; =20 - list_for_each_entry(rc, &rstc->rcdev->reset_control_head, list) { + guard(srcu)(&rstc->srcu); + + rcdev =3D srcu_dereference(rstc->rcdev, &rstc->srcu); + if (!rcdev) + return -ENODEV; + + list_for_each_entry(rc, &rcdev->reset_control_head, list) { if (rstc !=3D rc && rstc->id =3D=3D rc->id) { if (rc->acquired) return -EBUSY; @@ -743,6 +804,7 @@ __reset_control_get_internal(struct reset_controller_de= v *rcdev, bool shared =3D flags & RESET_CONTROL_FLAGS_BIT_SHARED; bool acquired =3D flags & RESET_CONTROL_FLAGS_BIT_ACQUIRED; struct reset_control *rstc; + int ret; =20 lockdep_assert_held(&reset_list_mutex); =20 @@ -773,12 +835,19 @@ __reset_control_get_internal(struct reset_controller_= dev *rcdev, if (!rstc) return ERR_PTR(-ENOMEM); =20 + ret =3D init_srcu_struct(&rstc->srcu); + if (ret) { + kfree(rstc); + return ERR_PTR(ret); + } + if (!try_module_get(rcdev->owner)) { + cleanup_srcu_struct(&rstc->srcu); kfree(rstc); return ERR_PTR(-ENODEV); } =20 - rstc->rcdev =3D rcdev; + rcu_assign_pointer(rstc->rcdev, rcdev); list_add(&rstc->list, &rcdev->reset_control_head); rstc->id =3D index; kref_init(&rstc->refcnt); @@ -793,13 +862,18 @@ static void __reset_control_release(struct kref *kref) { struct reset_control *rstc =3D container_of(kref, struct reset_control, refcnt); + struct reset_controller_dev *rcdev; =20 lockdep_assert_held(&reset_list_mutex); =20 - module_put(rstc->rcdev->owner); + scoped_guard(srcu, &rstc->srcu) { + rcdev =3D rcu_replace_pointer(rstc->rcdev, NULL, true); + if (rcdev) + reset_controller_remove(rcdev, rstc); + } =20 - list_del(&rstc->list); - put_device(rstc->rcdev->dev); + synchronize_srcu(&rstc->srcu); + cleanup_srcu_struct(&rstc->srcu); kfree(rstc); } =20 --=20 2.47.3