From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.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 EAF74278156 for ; Wed, 29 Apr 2026 15:43:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777477442; cv=none; b=b2jVd+on5BafcTwwTAHWxvdodn+AElq9DnqgQFNvX5chW4FO8eIfXUn6TtK5IBi893nBk/y5oxazCtXpp2yTWcaB1+E0X+HB6Ny3riMNbyKvgw2LXMQP1EPm9dR3TeRgajXAaPXjTkdDenACqKX2B7i4bLi401ExMy2l5A4UIz8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777477442; c=relaxed/simple; bh=JkRbAkosbYwXMjVGmb7/jsp15VRJKDjiXWv7ws34qbo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Qdf+V0Xjnr9sHb3sjRHwKSuQTpm/DgXch2VPKwGh7PAqFj2fuAqqguIy77MYZi05bRNTl1vp/T98HNQZzecMv0X+2SjZp8s5ZxGdutH1809WayozaizIHoSswnvUpvF5WwkiacfPkPqHRjIcs+RjtVktXMriQWHMyRb/zSBn2fU= 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=kanHa1Gy; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=X7kgqEq6; arc=none smtp.client-ip=205.220.180.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="kanHa1Gy"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="X7kgqEq6" Received: from pps.filterd (m0279868.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 63TFXCjJ2094157 for ; Wed, 29 Apr 2026 15:43:54 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= Rjr1K2IITtSw1gXFkf9e6YRr+JYnJ9C8AOEcRn4gPxQ=; b=kanHa1Gylu0gC6F2 QYF+54OR1nA88TkUdKx/EnFerdy7sopLWwA6fhJS/lCoYiRWEpzaLXrp3epW5uyI HCQAwAo5JYOD8M1kgDr//W+KHISodKKNu/u3gUMek33X1edhzY/i6E3TyI+dFyM1 SC0Tf1XBfrFF3EHDd8AP2m31kNhF3S+sKC4RUsMipZTFKYJstqlj2wNnk1f5J1tc shRRZDi6uKuIZQqeXuYdsKtar6jyxwSMf70/PlNF3R4MwJJAWod7/1d1cOPkYsxO oAUdITVE9o5VAd3LwwtmyiAoS7dOPcuc4B9dePCFlk1K/zbxX9aEUMG4B6Rj25y7 fCE6ug== Received: from mail-vs1-f69.google.com (mail-vs1-f69.google.com [209.85.217.69]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4dudh3t172-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Wed, 29 Apr 2026 15:43:54 +0000 (GMT) Received: by mail-vs1-f69.google.com with SMTP id ada2fe7eead31-6104087f037so5812322137.0 for ; Wed, 29 Apr 2026 08:43:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1777477434; x=1778082234; 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=Rjr1K2IITtSw1gXFkf9e6YRr+JYnJ9C8AOEcRn4gPxQ=; b=X7kgqEq6NKP0yDnJtXKy/GpjOfTaONJB5ITeH+kC4AJkTs3bmsMupnaAFPt7+QI6HD AEmfMhUIhnZC78iYqocMqdXzS6I90ZaIarugY/YjukfdOkPlwNsriDVbtL9e7yqJUNtb +ITpq+0jMJjgj4YplEQPSlS5EM8xW/SSNv0yj7u9VxScArLwydGR7u7U4sZYKyDCoBOP t61mY4pj62tEQ5aMjlkLINOzPMwFNEBRxHB+SEGw8nhnCuvwoNrOcGvnC8331JW/lqqe DciVBe89fRVfJOPpnX1ke4ue2EF3Z3lBaiOg7En9W0CsWM6GHJ+n2w11wPftDgyfYHV6 2lww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777477434; x=1778082234; 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=Rjr1K2IITtSw1gXFkf9e6YRr+JYnJ9C8AOEcRn4gPxQ=; b=BBl8EZ0kjZvxB63d4Kv243hmf+sWdm9eJ0ImiBGNkuLiE8erz7f+CKLhUoLVU3nchI YGvqL8hD544ghCF/3ZbCWQl4tlHPTyOb3Xc42Z4ulhPu4cwKTAYjDN4HK7+ASsgZgR1C iP9HGXda8RB7ouHOJ1+0qr+XJp19ycYsUsQ1gPalczk1QQzgc3gMErnYr2N5XlXSlRc+ IniYpfXB7RM8UzBzOyJ6PCjo5ANsijmAxMGrSMnXYN/C0rwkuys44zUa6sG/JQKGoaSH R9EPThomOusVKWsL0TH5QRAda08ApFm47ZzYs7WdwcD0xTHfNiftPVCzwI0wrvQ6Lew9 ft7Q== X-Gm-Message-State: AOJu0YzEnq6Gr75yvVT0cmBmlKvIOjB7v9V/QYtbwmJZjh9D3R0HWf// bF+8ZVIrvlHS4bhGZuBtTsO+cZ2xcxmrdezA35ctLy384fwLNzAK3t9RQo5EOwGAxBzIFSQDn4V tzaCPG/Cin3E5v2lhpuXRdn9e1m/0kJOUfNPdCUC3kRc9k+NNBemIAC0GgHI9TloTAxo= X-Gm-Gg: AeBDietGANWL00mQLt+s56926mwXGmUPfuQoy2ddcsdnrW8L2LWUUSecaHXGsNihqCf J/NpJ+Y1YqDvoZFI2DT9IDmVsmgqAe4RnctEd8ld8mOxmhTXQVeBp78jttIgIG3/Z4flBpi+zrH dOsWWoC/zOBtR8/aZFBw5cX7ilKbL1bj/TGT8D9mFcAnsYwskYE0aOkyJ0yfNgJ/IWfVpWMw19t hZ4AWQzoyDX9jGPnQ/ZHkt61odKu7m5ocIuOqvQ8hOTa7bwx/s4WNOQAL8UYB52qjjlRzBsQ3Hf vTTPdCKN+MNLtZ61mNZ+qeTkKFneo/MsonWlxed8mjiqEQkO/8QYo4uIPyIsxV1Ef+tdb3OQvMz Knf0osuDEfd+ou1c4KdEFVjrtrkSZJsliTXRDE9wsg7KwMEgnHCBXB/t++7SJsg== X-Received: by 2002:a67:e705:0:b0:611:a5b6:f4d6 with SMTP id ada2fe7eead31-6280a3a7e53mr4275915137.18.1777477433686; Wed, 29 Apr 2026 08:43:53 -0700 (PDT) X-Received: by 2002:a67:e705:0:b0:611:a5b6:f4d6 with SMTP id ada2fe7eead31-6280a3a7e53mr4275879137.18.1777477433090; Wed, 29 Apr 2026 08:43:53 -0700 (PDT) Received: from brgl-qcom.local ([2a01:cb1d:dc:7e00:e9c0:e45a:1dbc:c82a]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-447b3d481b2sm6837552f8f.4.2026.04.29.08.43.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Apr 2026 08:43:52 -0700 (PDT) From: Bartosz Golaszewski Date: Wed, 29 Apr 2026 17:43:24 +0200 Subject: [PATCH v3 9/9] nvmem: protect nvmem_device::ops with SRCU 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: 7bit Message-Id: <20260429-nvmem-unbind-v3-9-2a694f95395b@oss.qualcomm.com> References: <20260429-nvmem-unbind-v3-0-2a694f95395b@oss.qualcomm.com> In-Reply-To: <20260429-nvmem-unbind-v3-0-2a694f95395b@oss.qualcomm.com> To: Srinivas Kandagatla , Bartosz Golaszewski , Johan Hovold Cc: linux-kernel@vger.kernel.org, brgl@kernel.org, Bartosz Golaszewski X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=5572; i=bartosz.golaszewski@oss.qualcomm.com; h=from:subject:message-id; bh=JkRbAkosbYwXMjVGmb7/jsp15VRJKDjiXWv7ws34qbo=; b=owEBbQKS/ZANAwAKAQWdLsv/NoTDAcsmYgBp8icpIZcF77wcdloJAEKzOd7m+WjOP1lNwdAxR ECSCXrSxtuJAjMEAAEKAB0WIQSR5RMt5bVGHXuiZfwFnS7L/zaEwwUCafInKQAKCRAFnS7L/zaE wwI5D/4lPWJtKjTiS9RCerF4uCfBd9CYPr2HCsgQht9Ky7CRp4xgr7NIsfV9C4C0kC2c5aKzuwm 00kgxDZazF5kPBLYc575T9ILt0Sov2+xHGgvEdQctmqBcjTuaTWHwW+UXrO1hbHgyNk4tcc2ZHj MSMwV+YFgheSpH4tf/GuBtxqLhxV0Ne7hMsJiIT09EOamkM39xxHcjTFGymj4oexMqtHAk8QZBK kLkX5ttS8Aqz4RI5bxklgpZUim3MmZ1E0t9aDFqNn4Vc85KMFUTg2NO12iPMwRmUM3I5pNhIuAx +t9kwamDqqTtvgsRgNt52PvV3o+lzJxmNWsmh/g4OYLcq7UIoNySIgxOlQTdOI7D/BXOoDqhpDv 3E7LG1Y4HOU9DHnF+p/CvrBR33KWTj7KxzQCWzkPtjdGDPLo5ck8DshMwFC14tKcJPljJY6g8Qd Hrd2QCMlyEFXgXsG6XD9U3mZrbHqOvTZTA2pMujmRETUJn/KWFpSUfps782HYsC6fk1i20LMM/W OlvkdOsClkCsD8QBxi3UHUZEXzLqk2lECH65bd4KttbEpgP5TRdr6A8G5dHtHTzySmZaFxUo0K3 8HXRTW6hsJRwvJOX4jpB9tgNRhsWrxYr/QWwDbtKgLDBH1VFUpAHMTrXS50j0oflQlntIb97NkS 976yw/N9veZWpXw== X-Developer-Key: i=bartosz.golaszewski@oss.qualcomm.com; a=openpgp; fpr=169DEB6C0BC3C46013D2C79F11A72EA01471D772 X-Proofpoint-GUID: z-uFJXVfBg2SpeN9REYHNuWcBCyki5Tg X-Authority-Analysis: v=2.4 cv=A4dc+aWG c=1 sm=1 tr=0 ts=69f2273a cx=c_pps a=5HAIKLe1ejAbszaTRHs9Ug==:117 a=xqWC_Br6kY4A:10 a=IkcTkHD0fZMA:10 a=A5OVakUREuEA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=ZpdpYltYx_vBUK5n70dp:22 a=EUspDBNiAAAA:8 a=ydBWjX_Uc0Q5hLJtmLYA:9 a=QEXdDO2ut3YA:10 a=gYDTvv6II1OnSo0itH1n:22 X-Proofpoint-ORIG-GUID: z-uFJXVfBg2SpeN9REYHNuWcBCyki5Tg X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNDI5MDE1NyBTYWx0ZWRfX0oUvztzUQwYY 1U89CxSP8L7si2HaUDRmO6XZQzE/sijxfCWarfU6HAwDL0Xhm30c8mAisaNn5myRW4DOWTLEebo PBvoB7Tlc1etq2LN1DMY0vrDR+voDEI5JQazRiW3UUgkgt7XQi8TAdNObznSy6dZNz8SOLdEXAa cyq5xlbQjt0f3Wild5R4Lb8gkLVZeRtRXEzrTgfnrf0hAXjH+xYpq8Q/DJZDQ4W0Yt34JQ+NzpZ uEIxoIiDhr/JttWQkxpiS6Ae1rMNr9Iy4yUsWypsDpOdWnlf0ylXuS8Bsk3R77pF0u6JzIGLP4v XzzLhWnPQhYLlX/KMdkdhG1UUWovfiognrk/CuckHUmkLwhdbBdFXpRRD2OI2TM/Jcmjqs15sHT g9jIuYkekbXRFSpymjFk8ERLW0NXitvGeEkY+tZbFsZv8QfO14CT6gXH1solsFurSgAgPXzrpDM gn9eZr1tk2ENHOIaYvg== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.51,FMLib:17.12.100.49 definitions=2026-04-29_01,2026-04-28_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 spamscore=0 suspectscore=0 malwarescore=0 lowpriorityscore=0 priorityscore=1501 phishscore=0 bulkscore=0 impostorscore=0 adultscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2604200000 definitions=main-2604290157 With the provider-owned data split out into a separate 'ops' structure, we can now protect it with SRCU. Protect all dereferences of nvmem->ops with an SRCU read lock. Synchronize SRCU in nvmem_unregister() after setting the implementation pointer to NULL. This has the effect of numbing down the device after nvmem_unregister() returns - it will no longer accept any consumer calls and return -ENODEV. The actual device will live on for as long as there are references to it but we will no longer reach into the consumer's memory which may be gone by this time. Nvmem cell entries are destroyed in .release() now as they may be still dereferenced via the nvmem_cell handles after nvmem_release(). The actual calls will still go through SRCU and fail with -ENODEV if the provider is gone. Signed-off-by: Bartosz Golaszewski --- drivers/nvmem/core.c | 42 ++++++++++++++++++++++++++++++++++++------ drivers/nvmem/internals.h | 4 +++- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 590d880ede944670c09dd62b394626a959e5cdd1..9ec2d831ece6e51f918b5a815e45db346f30be7f 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -57,7 +57,12 @@ static BLOCKING_NOTIFIER_HEAD(nvmem_notifier); static int __nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset, void *val, size_t bytes) { - struct nvmem_operations *ops = nvmem->ops; + struct nvmem_operations *ops; + + guard(srcu)(&nvmem->srcu); + ops = rcu_dereference(nvmem->ops); + if (!ops) + return -ENODEV; if (!ops->reg_read) return -EOPNOTSUPP; @@ -68,9 +73,14 @@ static int __nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset, static int __nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset, void *val, size_t bytes) { - struct nvmem_operations *ops = nvmem->ops; + struct nvmem_operations *ops; int ret, written; + guard(srcu)(&nvmem->srcu); + ops = rcu_dereference(nvmem->ops); + if (!ops) + return -ENODEV; + if (!ops->reg_write) return -EOPNOTSUPP; @@ -283,7 +293,7 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj, static umode_t nvmem_bin_attr_get_umode(struct nvmem_device *nvmem) { - struct nvmem_operations *ops = nvmem->ops; + struct nvmem_operations *ops = rcu_dereference_raw(nvmem->ops); umode_t mode = 0400; @@ -327,7 +337,7 @@ static umode_t nvmem_attr_is_visible(struct kobject *kobj, { struct device *dev = kobj_to_dev(kobj); struct nvmem_device *nvmem = to_nvmem_device(dev); - struct nvmem_operations *ops = nvmem->ops; + struct nvmem_operations *ops = rcu_dereference_raw(nvmem->ops); /* * If the device has no .reg_write operation, do not allow @@ -554,7 +564,7 @@ static void nvmem_release(struct device *dev) gpiod_put(nvmem->wp_gpio); nvmem_device_remove_all_cells(nvmem); ida_free(&nvmem_ida, nvmem->id); - kfree(nvmem->ops); + cleanup_srcu_struct(&nvmem->srcu); kfree(nvmem); } @@ -930,6 +940,18 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) nvmem->dev.bus = &nvmem_bus_type; nvmem->dev.parent = config->dev; + /* + * Must happen before we assign the release() callback in + * device_initialize(). + */ + rval = init_srcu_struct(&nvmem->srcu); + if (rval) { + ida_free(&nvmem_ida, nvmem->id); + kfree(ops); + kfree(nvmem); + return ERR_PTR(rval); + } + device_initialize(&nvmem->dev); if (!config->ignore_wp) @@ -947,7 +969,8 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) ops->reg_read = config->reg_read; ops->reg_write = config->reg_write; - nvmem->ops = ops; + rcu_assign_pointer(nvmem->ops, ops); + nvmem->owner = config->owner; if (!nvmem->owner && config->dev->driver) nvmem->owner = config->dev->driver->owner; @@ -1046,6 +1069,7 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) nvmem_sysfs_remove_compat(nvmem); err_put_device: put_device(&nvmem->dev); + kfree(ops); return ERR_PTR(rval); } @@ -1058,10 +1082,16 @@ EXPORT_SYMBOL_GPL(nvmem_register); */ void nvmem_unregister(struct nvmem_device *nvmem) { + struct nvmem_operations *ops; + blocking_notifier_call_chain(&nvmem_notifier, NVMEM_REMOVE, nvmem); + ops = rcu_replace_pointer(nvmem->ops, NULL, true); + synchronize_srcu(&nvmem->srcu); + nvmem_sysfs_remove_compat(nvmem); nvmem_destroy_layout(nvmem); + kfree(ops); device_unregister(&nvmem->dev); } diff --git a/drivers/nvmem/internals.h b/drivers/nvmem/internals.h index 60daa79c404dc915872481bd3b02de2258d33406..17418fd0dcc92b101b56082fc15d74042386107d 100644 --- a/drivers/nvmem/internals.h +++ b/drivers/nvmem/internals.h @@ -6,6 +6,7 @@ #include #include #include +#include /* Hold pointers to callbacks owned by the nvmem provider module. */ struct nvmem_operations { @@ -16,6 +17,7 @@ struct nvmem_operations { struct nvmem_device { struct module *owner; struct device dev; + struct srcu_struct srcu; int stride; int word_size; int id; @@ -33,7 +35,7 @@ struct nvmem_device { unsigned int nkeepout; struct gpio_desc *wp_gpio; struct nvmem_layout *layout; - struct nvmem_operations *ops; + struct nvmem_operations __rcu *ops; void *priv; bool sysfs_cells_populated; }; -- 2.47.3