From nobody Sat Sep 26 05:33:47 2026 Received: from mail-pj1-f72.google.com (mail-pj1-f72.google.com [209.85.216.72]) (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 2542348C8D7 for ; Fri, 4 Sep 2026 11:00:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788519624; cv=none; b=CZ9GUD+fhb7+8yBuijzpQnlrvqB3K0MmuSuqjou3oaGMnfNJZumJ6Kkxd+iCVFlhMYoGyBrmF5HgRpRBhgxcWb5PSWf6GNoDVmqRxhm9ukNPPHudiu03WdGFjHdQT7PwEEyK3gFUa/I5ulOL2CnRIp/okRDrmgzV5WgfDwM3Org= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788519624; c=relaxed/simple; bh=zV+id8hgrmOYZ2zkH5wVp805A1ipbO2BAvtEYS6rNqM=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ZIMMYggAgPpYZNUjb75QIo0JqHe/I8zQQXqWBrgj88rZ4vDnWeilS+USZbqWyH8a2kN/6Xa2cXSZ5c5dmniY12sv/ss9WgD/IoVC8XXAsQInQdwfzSpNscaTuQ8NwmrPGxZlyKLWL3Ys1UmCS5WzYqeAu+1KipzJ8xDzOHXcSyU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--stanleyjhu.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=PtALMpdO; arc=none smtp.client-ip=209.85.216.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--stanleyjhu.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="PtALMpdO" Received: by mail-pj1-f72.google.com with SMTP id 98e67ed59e1d1-3968bb86fb7so1227180a91.2 for ; Fri, 04 Sep 2026 04:00:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1788519621; x=1789124421; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=u84Mc5AIsSgNc1vzS18uPhdCuLSJJI70tZiWSF1FywQ=; b=PtALMpdOrBUcZkbWuQoAlZxwXACb00sfkDVO2LRqht2VnDzK+LwEMpRls0xzylDt/i dhufOY9+M8iZXakodqdtL2KtCKYlWVuCRF1mClwY7sW8eN0sf9vbJlcsoVr9eB5Of8J3 bv0Mro6oX+1DwhGz8V7Lc0BKaoqnDEY5ubOkJun+A2D2KFxEIizb6zmU1kD4KhZ8omay oKsL4KgRz7gTxgF5+PggaUBwnyiJxeD8UQgbAarlYs0cJVYqfqE3jH0KzwJ39O7yW9VO D3YRZ5dQ6n8M3NfMV3myAM2tMBD1plw2WL1yPQMjHIKr7V0KaNIDLmSyg40IHXrPqQXT dJrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788519621; x=1789124421; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=u84Mc5AIsSgNc1vzS18uPhdCuLSJJI70tZiWSF1FywQ=; b=arPD5Rylm6I8Bx1O4rt2ozteyuejpOkYCuHGhbEujB5b2StpUgTBvf6P0r29mtmey/ eQgMEK3xLqK01/MoM5OQWoiwFyu80/5xTg5x6cPbW7+xGlNr3GqAgBDj2WknaP78ErzP fScvyhw8mpf/FsHnTYAPXFB4UCIQ1/iaF23p79g+y2FOtA9dygDC2AWhwAoE5EuB4WPI ODBorF9ROnh9iVjTEbUAOusngFlRhga6X8yJymoMQXq3CMxfYDwtL/2LbWSevlFr20b4 dwnIj72x1avoMkv3UrlP9GabFuOVEXXBFnRpUgE1AMLdiGDEFaQLV8PpvbRWZgge1nb3 p2Bg== X-Forwarded-Encrypted: i=1; AKwUvBzMPshv+SkIpfnQN9GEYaUHGu8GRdpqAgLx6WbKC/udKRY3gqqunSTSI1uTccZb9yWi7h0F7gBEb5DG7Wg=@vger.kernel.org X-Gm-Message-State: AFuF++lONrRtjZfemkX1ghdRf9AakF8d1/On5Eb9tsTIJDTyl5RLobqj YdiC1oqDZb2tceKI2YW6hE1xPsomHZcMtc+ymZYX4j9DmkxluquONq72L+nkiDTUqf5ytXRa6mY G451W9E0HDeHbgS/9nKRTQA== X-Received: from pjye12.prod.google.com ([2002:a17:90a:ee0c:b0:39b:1aab:f8c3]) (user=stanleyjhu job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:2ccf:b0:398:a2a3:b631 with SMTP id 98e67ed59e1d1-39b262aaf3dmr8893505a91.19.1788519621001; Fri, 04 Sep 2026 04:00:21 -0700 (PDT) Date: Fri, 4 Sep 2026 19:00:16 +0800 In-Reply-To: <20260904110017.3444852-1-stanleyjhu@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260904110017.3444852-1-stanleyjhu@google.com> X-Mailer: git-send-email 2.55.0.979.g7e5102b832-goog Message-ID: <20260904110017.3444852-2-stanleyjhu@google.com> Subject: [PATCH 1/2] scsi: ufs: rpmb: Decouple device lifecycle from devres to avoid UAF From: Stanley Jhu To: "Martin K . Petersen" , "James E . J . Bottomley" , linux-scsi@vger.kernel.org Cc: Brian Kao , Bean Huo , Bart Van Assche , Alim Akhtar , Avri Altman , Can Guo , Peter Wang , linux-kernel@vger.kernel.org, Stanley Jhu Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The UFS RPMB driver suffers from three architectural lifetime flaws: 1. Lifecycle mismatch: The driver allocates struct ufs_rpmb_dev via devres tied to the parent controller, even though it embeds a struct device. A struct device's lifetime must be governed by its own reference count. When the controller unbinds, devres prematurely frees the memory while references (such as sysfs nodes or userspace file descriptors) remain active, triggering a use-after-free (UAF) Oops: "Unable to handle kernel paging request at virtual address 0x006b6b6b6b6b6b9c" 2. Unpinned transport hierarchy: The RPMB device relies on the underlying SCSI WLUN and host controller for command submission, but does not acquire a reference to the SCSI device. Unbinding the controller during in-flight I/O dereferences destroyed SCSI structures. 3. Inverted teardown and error handling: Subsystem registration is conflated with device memory lifecycle. The device release callback improperly attempts subsystem teardown, while driver removal and probe error paths unregister the driver core device without first unregistering from the RPMB subsystem. To resolve these issues, align the driver with standard kernel device model principles: 1. Reference-counted lifecycle: Decouple ufs_rpmb from devres. Manage its memory strictly through the embedded struct device's reference count, freeing it only in the device release callback. 2. Topological pinning: Pin the underlying SCSI device for the duration of the RPMB device's existence, ensuring the SCSI host hierarchy remains valid until all references to the RPMB device are dropped. 3. Symmetrical teardown and state validation: Unregister subsystem interfaces before driver core devices, correct error rollback paths, initialize fields before exposing the device to userspace, and reject requests if the underlying device goes offline. Fixes: b06b8c421485 ("scsi: ufs: core: Add OP-TEE based RPMB driver for UFS= devices") Signed-off-by: Stanley Jhu --- drivers/ufs/core/ufs-rpmb.c | 86 +++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 36 deletions(-) diff --git a/drivers/ufs/core/ufs-rpmb.c b/drivers/ufs/core/ufs-rpmb.c index aa925cbb07e8..4f41d0b64d20 100644 --- a/drivers/ufs/core/ufs-rpmb.c +++ b/drivers/ufs/core/ufs-rpmb.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -33,15 +34,19 @@ struct ufs_rpmb_dev { u8 region_id; struct device dev; struct rpmb_dev *rdev; - struct ufs_hba *hba; + struct scsi_device *sdev; struct list_head node; }; =20 -static int ufs_sec_submit(struct ufs_hba *hba, u16 spsp, void *buffer, siz= e_t len, bool send) +static int ufs_sec_submit(struct ufs_rpmb_dev *ufs_rpmb, u16 spsp, + void *buffer, size_t len, bool send) { - struct scsi_device *sdev =3D hba->ufs_rpmb_wlun; + struct scsi_device *sdev =3D ufs_rpmb->sdev; u8 cdb[12] =3D { }; =20 + if (!sdev || !scsi_device_online(sdev)) + return -ENODEV; + cdb[0] =3D send ? SECURITY_PROTOCOL_OUT : SECURITY_PROTOCOL_IN; cdb[1] =3D UFS_RPMB_SEC_PROTOCOL; put_unaligned_be16(spsp, &cdb[2]); @@ -53,13 +58,12 @@ static int ufs_sec_submit(struct ufs_hba *hba, u16 spsp= , void *buffer, size_t le =20 /* UFS RPMB route frames implementation */ static int ufs_rpmb_route_frames(struct device *dev, u8 *req, unsigned int= req_len, u8 *resp, - unsigned int resp_len) + unsigned int resp_len) { struct ufs_rpmb_dev *ufs_rpmb =3D dev_get_drvdata(dev); struct rpmb_frame *frm_out =3D (struct rpmb_frame *)req; bool need_result_read =3D true; u16 req_type, protocol_id; - struct ufs_hba *hba; int ret; =20 if (!ufs_rpmb) { @@ -67,8 +71,6 @@ static int ufs_rpmb_route_frames(struct device *dev, u8 *= req, unsigned int req_l return -ENODEV; } =20 - hba =3D ufs_rpmb->hba; - /* req_resp is at the end of an RPMB frame. */ if (req_len < sizeof(*frm_out)) return -EINVAL; @@ -101,7 +103,7 @@ static int ufs_rpmb_route_frames(struct device *dev, u8= *req, unsigned int req_l =20 protocol_id =3D ufs_rpmb->region_id << 8 | UFS_RPMB_SEC_PROTOCOL_ID; =20 - ret =3D ufs_sec_submit(hba, protocol_id, req, req_len, true); + ret =3D ufs_sec_submit(ufs_rpmb, protocol_id, req, req_len, true); if (ret) { dev_err(dev, "Command failed with ret=3D%d\n", ret); return ret; @@ -112,7 +114,7 @@ static int ufs_rpmb_route_frames(struct device *dev, u8= *req, unsigned int req_l =20 memset(frm_resp, 0, sizeof(*frm_resp)); put_unaligned_be16(RPMB_RESULT_READ, &frm_resp->req_resp); - ret =3D ufs_sec_submit(hba, protocol_id, resp, resp_len, true); + ret =3D ufs_sec_submit(ufs_rpmb, protocol_id, resp, resp_len, true); if (ret) { dev_err(dev, "Result read request failed with ret=3D%d\n", ret); return ret; @@ -120,7 +122,7 @@ static int ufs_rpmb_route_frames(struct device *dev, u8= *req, unsigned int req_l } =20 if (!ret) { - ret =3D ufs_sec_submit(hba, protocol_id, resp, resp_len, false); + ret =3D ufs_sec_submit(ufs_rpmb, protocol_id, resp, resp_len, false); if (ret) dev_err(dev, "Response read failed with ret=3D%d\n", ret); } @@ -130,22 +132,24 @@ static int ufs_rpmb_route_frames(struct device *dev, = u8 *req, unsigned int req_l =20 static void ufs_rpmb_device_release(struct device *dev) { - struct ufs_rpmb_dev *ufs_rpmb =3D dev_get_drvdata(dev); + struct ufs_rpmb_dev *ufs_rpmb =3D container_of(dev, struct ufs_rpmb_dev, = dev); =20 - rpmb_dev_unregister(ufs_rpmb->rdev); + scsi_device_put(ufs_rpmb->sdev); + kfree(ufs_rpmb); } =20 /* UFS RPMB device registration */ int ufs_rpmb_probe(struct ufs_hba *hba) { + struct scsi_device *sdev =3D hba->ufs_rpmb_wlun; struct ufs_rpmb_dev *ufs_rpmb, *it, *tmp; struct rpmb_dev *rdev; - char *cid =3D NULL; + char *cid; int region; u32 cap; int ret; =20 - if (!hba->ufs_rpmb_wlun || hba->dev_info.b_advanced_rpmb_en) { + if (!sdev || hba->dev_info.b_advanced_rpmb_en) { dev_info(hba->dev, "Skip OP-TEE RPMB registration\n"); return -ENODEV; } @@ -167,14 +171,23 @@ int ufs_rpmb_probe(struct ufs_hba *hba) if (!cap) continue; =20 - ufs_rpmb =3D devm_kzalloc(hba->dev, sizeof(*ufs_rpmb), GFP_KERNEL); + ufs_rpmb =3D kzalloc(sizeof(*ufs_rpmb), GFP_KERNEL); if (!ufs_rpmb) { ret =3D -ENOMEM; goto err_out; } =20 - ufs_rpmb->hba =3D hba; - ufs_rpmb->dev.parent =3D &hba->ufs_rpmb_wlun->sdev_gendev; + INIT_LIST_HEAD(&ufs_rpmb->node); + + ret =3D scsi_device_get(sdev); + if (ret) { + kfree(ufs_rpmb); + goto err_out; + } + + ufs_rpmb->sdev =3D sdev; + ufs_rpmb->region_id =3D region; + ufs_rpmb->dev.parent =3D &sdev->sdev_gendev; ufs_rpmb->dev.bus =3D &ufs_rpmb_bus_type; ufs_rpmb->dev.release =3D ufs_rpmb_device_release; dev_set_name(&ufs_rpmb->dev, "ufs_rpmb%d", region); @@ -185,16 +198,14 @@ int ufs_rpmb_probe(struct ufs_hba *hba) ret =3D device_register(&ufs_rpmb->dev); if (ret) { dev_err(hba->dev, "Failed to register UFS RPMB device %d\n", region); - put_device(&ufs_rpmb->dev); - goto err_out; + goto err_put; } =20 /* Create unique ID by appending region number to device_id */ cid =3D kasprintf(GFP_KERNEL, "%s-R%d", hba->dev_info.device_id, region); if (!cid) { - device_unregister(&ufs_rpmb->dev); ret =3D -ENOMEM; - goto err_out; + goto err_unreg; } =20 descr.dev_id =3D cid; @@ -203,29 +214,33 @@ int ufs_rpmb_probe(struct ufs_hba *hba) =20 /* Register RPMB device */ rdev =3D rpmb_dev_register(&ufs_rpmb->dev, &descr); + kfree(cid); if (IS_ERR(rdev)) { dev_err(hba->dev, "Failed to register UFS RPMB device.\n"); - device_unregister(&ufs_rpmb->dev); ret =3D PTR_ERR(rdev); - goto err_out; + goto err_unreg; } =20 - kfree(cid); - cid =3D NULL; - ufs_rpmb->rdev =3D rdev; - ufs_rpmb->region_id =3D region; - list_add_tail(&ufs_rpmb->node, &hba->rpmbs); =20 dev_info(hba->dev, "UFS RPMB region %d registered (capacity=3D%u)\n", re= gion, cap); } =20 return 0; + +err_unreg: + device_unregister(&ufs_rpmb->dev); + goto err_out; +err_put: + put_device(&ufs_rpmb->dev); err_out: - kfree(cid); list_for_each_entry_safe(it, tmp, &hba->rpmbs, node) { - list_del(&it->node); + list_del_init(&it->node); + if (it->rdev) { + rpmb_dev_unregister(it->rdev); + it->rdev =3D NULL; + } device_unregister(&it->dev); } =20 @@ -242,14 +257,13 @@ void ufs_rpmb_remove(struct ufs_hba *hba) =20 /* Remove all registered RPMB devices */ list_for_each_entry_safe(ufs_rpmb, tmp, &hba->rpmbs, node) { - dev_info(hba->dev, "Removing UFS RPMB region %d\n", ufs_rpmb->region_id); - /* Remove from list first */ - list_del(&ufs_rpmb->node); - /* Unregister device */ + list_del_init(&ufs_rpmb->node); + if (ufs_rpmb->rdev) { + rpmb_dev_unregister(ufs_rpmb->rdev); + ufs_rpmb->rdev =3D NULL; + } device_unregister(&ufs_rpmb->dev); } - - dev_info(hba->dev, "All UFS RPMB devices unregistered\n"); } =20 MODULE_LICENSE("GPL v2"); --=20 2.55.0.979.g7e5102b832-goog From nobody Sat Sep 26 05:33:47 2026 Received: from mail-pj1-f70.google.com (mail-pj1-f70.google.com [209.85.216.70]) (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 1EE8048F822 for ; Fri, 4 Sep 2026 11:00:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.70 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788519626; cv=none; b=KKfCRka5WS6Y5Qd/tgtkPZ0vg74TNY6rYmuWGmMKzCSje/IcuLW849yXdurWSDZomhjfowMIIOaciTbnl3d6nNHtpR4cMbEojhSwHWKMWWhQKxScU+g0VeK53d9Oeaqgj1ABqwP/YP5KHtRep4nO0cgEgpJOEblg1s2kGTrMo/8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788519626; c=relaxed/simple; bh=ec3f2c/2ovVBbSwOHdK1oiWlSRb218cenPSOQvS+b1E=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=LKB7mCPqaW4bi9tpy2JZlYRMIVL1Xq486WfsG/e/KRwFL1wOMk/0gwCna5bKPlDgbmnI1f1W4cL/3OicAJ957kYUot23LAChlrNpNOHQptUYgl6+CIqCpy/EJhO/TXd3ela8nt2Rr1IcEX+rjNQ3hBgJnlPdGMGLSLZ8XqzCpb8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--stanleyjhu.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=dkBfu3Cs; arc=none smtp.client-ip=209.85.216.70 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--stanleyjhu.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="dkBfu3Cs" Received: by mail-pj1-f70.google.com with SMTP id 98e67ed59e1d1-39512608fb1so2067945a91.1 for ; Fri, 04 Sep 2026 04:00:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1788519623; x=1789124423; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=zo7VwFgsbtJ8UJqRREQfIoxVumyrpqsEREUtKGw4Baw=; b=dkBfu3CsCjYICrP+RgbLcA7k/mX3cJnwLzQ8qYboK/5hMbEu0b4lleC+DbsAWMkw6h UIqWJBXqIg9NLKtxcQQaYBIPQQlMSy628uQax4DnhcifP/xWBK1QWd2ZJmq+xjWWBpfs yrKXsOMfJ7AdbRtw19uhTkEGmkwBUMcfBtPUfO89zjbylv2H6yttgUqoDcllXuYi61Zr MktX407CUW08k0w+r3MtHgjSOoDqMSBkDAiHfR4cqFeT42qM/3Vb2FyU9PT/juveBf/0 uMgdL05V3ObtFyqsbk3oFYPw+7Pgb6OJD/BKZDgrEDWsG8K1PGSkiKkjHYA2L2EJvt+7 o1QA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788519623; x=1789124423; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=zo7VwFgsbtJ8UJqRREQfIoxVumyrpqsEREUtKGw4Baw=; b=D0Z1N7Lai9Y1moS+sHeBtunvpFzxrLgVrIXPOS8zAaoQXIIu1Th70MMUBqm/2bmGZ+ m4b4nC9LU1QURvMTxOkiqofc+5tmBB9FjWZZOIGgU9sdWA4ymOzpL8rBdcxVxdzT1kxy hZKU4HquNiJUfP22ni1kBU3NVL0A3YBb/XL3lT5c4+bKxHwqJF/2JekkG2lm9Xf1QMBT H5xrB/2lFaS5UolzlWkfgpdl+QZY8S6J7gtthb1UoeNLw20bqTT9uOVVj38Mbcc2RtZD 99wUHpIUEY9VXXmftagCCkRsVqXObfsXjyva7D4p0zPUlMSVCHfvMnzeSlV65zAUmN0p G6LA== X-Forwarded-Encrypted: i=1; AKwUvByN3LNMZRIYOrg5sQuOLoVeCqqrPM72vngbxwlFZprv/hBpfEJiUUNPt/jll5ByB1Dd25vUCm8gw13QinI=@vger.kernel.org X-Gm-Message-State: AFuF++nYf8HSY5KYbVfnd0Ra5MnjLsMb22Aq0PwzINZwfM/AdDizVRsV BfHa3aUeFVC/eTezxKHHUWJqtz7lHEAa3SXixz9nNjTaI6ByEtW6XhjIvV3whquplVDZ1vTzBM/ gZPkaa2Pmcww7IVJ8YVMc7A== X-Received: from pjye1.prod.google.com ([2002:a17:90a:ee01:b0:398:d6ef:834]) (user=stanleyjhu job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:3943:b0:398:d8eb:cb2a with SMTP id 98e67ed59e1d1-39b26273e31mr9007463a91.23.1788519623111; Fri, 04 Sep 2026 04:00:23 -0700 (PDT) Date: Fri, 4 Sep 2026 19:00:17 +0800 In-Reply-To: <20260904110017.3444852-1-stanleyjhu@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260904110017.3444852-1-stanleyjhu@google.com> X-Mailer: git-send-email 2.55.0.979.g7e5102b832-goog Message-ID: <20260904110017.3444852-3-stanleyjhu@google.com> Subject: [PATCH 2/2] scsi: ufs: rpmb: Register and unregister ufs_rpmb_bus_type From: Stanley Jhu To: "Martin K . Petersen" , "James E . J . Bottomley" , linux-scsi@vger.kernel.org Cc: Brian Kao , Bean Huo , Bart Van Assche , Alim Akhtar , Avri Altman , Can Guo , Peter Wang , linux-kernel@vger.kernel.org, Stanley Jhu Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The UFS RPMB driver assigns its devices to a custom ufs_rpmb_bus_type, but never registers this bus with the driver core. As a result, device_register() fails during probe because the driver core rejects devices attached to unregistered buses with -EINVAL: "bus_add_device: cannot add device 'ufs_rpmb0' to unregistered bus 'ufs_rpmb'" "ufshcd: Failed to register UFS RPMB device 0" Resolve this by integrating the bus into the UFS core lifecycle: 1. Bus registration and lifecycle: Register ufs_rpmb_bus_type during ufshcd_core_init() before any device probe occurs, and unregister it during ufshcd_core_exit(). Annotate the registration helper with __init to allow init memory reclamation. 2. Modular reachability: Guard bus helper prototypes with IS_REACHABLE(CONFIG_RPMB) and provide inline stubs, preventing link failures when UFS is built-in and RPMB is compiled as a module. Fixes: b06b8c421485 ("scsi: ufs: core: Add OP-TEE based RPMB driver for UFS= devices") Signed-off-by: Stanley Jhu --- drivers/ufs/core/ufs-rpmb.c | 10 ++++++++++ drivers/ufs/core/ufshcd-priv.h | 11 ++++++++++- drivers/ufs/core/ufshcd.c | 16 ++++++++++++++-- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/drivers/ufs/core/ufs-rpmb.c b/drivers/ufs/core/ufs-rpmb.c index 4f41d0b64d20..cf8982824b14 100644 --- a/drivers/ufs/core/ufs-rpmb.c +++ b/drivers/ufs/core/ufs-rpmb.c @@ -29,6 +29,16 @@ static const struct bus_type ufs_rpmb_bus_type =3D { .name =3D "ufs_rpmb", }; =20 +int __init ufs_rpmb_bus_register(void) +{ + return bus_register(&ufs_rpmb_bus_type); +} + +void ufs_rpmb_bus_unregister(void) +{ + bus_unregister(&ufs_rpmb_bus_type); +} + /* UFS RPMB device structure */ struct ufs_rpmb_dev { u8 region_id; diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h index e55c2a02c1f5..415f9230b164 100644 --- a/drivers/ufs/core/ufshcd-priv.h +++ b/drivers/ufs/core/ufshcd-priv.h @@ -493,10 +493,19 @@ static inline u32 ufshcd_mcq_get_sq_head_slot(struct = ufs_hw_queue *q) return val / sizeof(struct utp_transfer_req_desc); } =20 -#if IS_ENABLED(CONFIG_RPMB) +#if IS_REACHABLE(CONFIG_RPMB) +int __init ufs_rpmb_bus_register(void); +void ufs_rpmb_bus_unregister(void); int ufs_rpmb_probe(struct ufs_hba *hba); void ufs_rpmb_remove(struct ufs_hba *hba); #else +static inline int ufs_rpmb_bus_register(void) +{ + return 0; +} +static inline void ufs_rpmb_bus_unregister(void) +{ +} static inline int ufs_rpmb_probe(struct ufs_hba *hba) { return 0; diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index a25b6a0cb5c6..4470e3d65c5c 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -11584,16 +11584,28 @@ static int __init ufshcd_core_init(void) =20 ufs_debugfs_init(); =20 + ret =3D ufs_rpmb_bus_register(); + if (ret) + goto err_debugfs; + ret =3D scsi_register_driver(&ufs_dev_wlun_template); if (ret) - ufs_debugfs_exit(); + goto err_rpmb_bus; + + return 0; + +err_rpmb_bus: + ufs_rpmb_bus_unregister(); +err_debugfs: + ufs_debugfs_exit(); return ret; } =20 static void __exit ufshcd_core_exit(void) { - ufs_debugfs_exit(); scsi_unregister_driver(&ufs_dev_wlun_template); + ufs_rpmb_bus_unregister(); + ufs_debugfs_exit(); } =20 module_init(ufshcd_core_init); --=20 2.55.0.979.g7e5102b832-goog