From nobody Tue Jun 16 08:53:02 2026 Received: from mail-pf1-f175.google.com (mail-pf1-f175.google.com [209.85.210.175]) (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 133EF3845AB for ; Fri, 17 Apr 2026 13:35:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776432942; cv=none; b=hNcTPeCIZGRlkSfHKEyBE8eRgxCCgfQ3r4eXxE/63WcL6l9j42SAC6P0+i8QNwdLiwJjN9B3rs0eRkzMa9OAkm60bUuXbrcttomqZc/udln/TdZcRssT/rZUESQ0B9B19dDu4H4/cZAHPvc+xsrJTdaqlTExQEikcntvcPqhJsE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776432942; c=relaxed/simple; bh=Lc9ZuZRMssPJ6LdhNV62mIiuc51WiGNvfhGCMgaLY2A=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=E1Y8c+IbvUfUIy09aTkBqH1ikJSoczZ60nAIrNCACXzwVK5AxTOtCPdDf96kOJjSMvWT4QHYL1RDlpJ7T1z90y4AfKpVCapJp+W0JVPrBCRWVnBqsEZ8G7ZYfA0AFD5FMvJzrBubt8JWeVqEItVpeJDToHK7PU7PMH1NfyLwyy4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=QNim93E6; arc=none smtp.client-ip=209.85.210.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QNim93E6" Received: by mail-pf1-f175.google.com with SMTP id d2e1a72fcca58-82f37c09352so1229983b3a.0 for ; Fri, 17 Apr 2026 06:35:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776432940; x=1777037740; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fdDAtCg/5gWiORhKSpZnqdKkvEwJP2sVvd/SKqDyQdQ=; b=QNim93E6udF0iJMiXaQCZj3mZgLmsIKMYRGfEyMzLEe8Du+dDQZ6Hljshnhd7SWznx GhT4s2zTW1MWdUAm92/pAASsMl0vF1KRXsfZbSEnn2Ax8/Ste2nYt+SB4b9eJDGtqgvu b0zI48J2UIvOiTWNxRRjCVQ+7AGxF1BYdw6FJV53DbjKAFen9mSp1f1uS+C8hvpN/RNy owCgAIg6JEtPksVjYJXAEl41MmPG6XKM01BVLr0Jh623iXhgr3dQ4RV6kBsHLlsWxMYe XF+K8cboG90wMPrC8oIchjweZgaznOPoCsisA/r3RFHob9ur9n0tHZxExG/CtNe4y4cV d/AA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776432940; x=1777037740; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=fdDAtCg/5gWiORhKSpZnqdKkvEwJP2sVvd/SKqDyQdQ=; b=pOYpANAwG53oX+LtyrwneJoo9UiPXBnlFbMOaX4UVVQwrxtAzgIyNfCvF2rtiW1p7G 0XAYueZbRYVUWyqQ9+5awJwInCn79V1kQU+r9M0/QtuMlwHC3Rr78mYuh+/NFa+TxTnJ 9x85AtImMLXQeVpeAvQqn3BZQASJq5ZnSZwC/69SPaYjLx60ai+GyQLeYh4RbNyLTTEp v1Orr4AgBCPjZrSfX09Z2d2xpgpIg8U/BF6VBatHHmwjfpbEqn06G0jAfKbgCJloa9nA cGGGXRK3mEGqhM+mZBrSnQ8iVedsMxz4wNZlB8RZ3UDFqg98rNgt0BLXegWGhY0H96dx KzEw== X-Forwarded-Encrypted: i=1; AFNElJ+NkOAvMjfrDs5AIgBquyL0bYXhTF1lxaR4vVQ5gTtKqNQrZZsg4VY3KPEVasBvv+tEj4WsRqqtX0hUuhg=@vger.kernel.org X-Gm-Message-State: AOJu0YwsXTOPwS0gKzuzHmOCd7DTUEvuTONkN9o8q0uoLJvWy+ciQQPj OkbHYSgLDy6zdswuwMbuYaVBP1aAyFOUqmqeEd8KEMV5lnlxGX7ULLXG X-Gm-Gg: AeBDievw9xhwYETtNkv1PfbW1fJr2pvVxYzOosuhlqyMyG/8ywPdtE3azPAaMt5eAbe j2p4Z4ZrBPji1cqu3RQg9/5Gs9ZG1xK4aJbpvMVHxmpynep7VcHx2iL+1qdAO7Z0u1dXFSPwIGP TJFGu+UNwondAh1UrBcXXTXs8EQzKY3Zx0o/8YKjeHVCA9v3FpPUBjZSKRHMlkFNxi2VaiGYlqb ZsPL2hAw5s2/nn8KSPGeouOT0H80aaN3JVbEEXEgt1Ka/Bs/FxwPkMt3lBxDxkEJekvY+x9oIGs 9i9qzKUs6T79YJv+UZzbPTsJySGmoD/JcNWN8vRs+pSYUSMC7oBPSMT87zH+JUTdmQp6zh5VSSx iiD/JX3MTh2KeiHUWW0mhYvn+3nbhYSU2QtShEjj1F/h/L+8fMRRLzetAdkeo2BXn/97JgvgHkr sFnPb6UvS1OmPRSJ8PL8qZibLnd1myu1TbBIv81a/FJZApjgQdQcU0qHC5+eUA4yaV3iGIgTidj ko+AoP8l/agqO3hTHoiP9q2eEupKRij9Po0rQ== X-Received: by 2002:a05:6a20:729c:b0:39f:582c:aa8a with SMTP id adf61e73a8af0-3a08ca73cf4mr2590496637.19.1776432940119; Fri, 17 Apr 2026 06:35:40 -0700 (PDT) Received: from baver-zenith.localdomain ([124.49.88.131]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c7976fa3604sm1421272a12.14.2026.04.17.06.35.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Apr 2026 06:35:39 -0700 (PDT) From: Sungho Bae To: mst@redhat.com, jasowang@redhat.com Cc: xuanzhuo@linux.alibaba.com, eperezma@redhat.com, virtualization@lists.linux.dev, linux-kernel@vger.kernel.org, Sungho Bae Subject: [RFC PATCH v2 1/4] virtio: separate PM restore and reset_done paths Date: Fri, 17 Apr 2026 22:34:27 +0900 Message-Id: <20260417133430.507-2-baver.bae@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260417133430.507-1-baver.bae@gmail.com> References: <20260417133430.507-1-baver.bae@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Sungho Bae Refactor virtio_device_restore_priv() by extracting the common device re-initialization sequence into virtio_device_reinit(). This helper performs the full bring-up sequence: reset, status acknowledgment, feature finalization, and feature negotiation. virtio_device_restore() and virtio_device_reset_done() now each call virtio_device_reinit() directly instead of going through a boolean- dispatched wrapper. This makes each path independently readable and extensible without further complicating the dispatch logic. A follow-up series will add noirq PM callbacks that only affect the restore path; having the two paths separated avoids adding more conditionals to a shared function. No functional change. Signed-off-by: Sungho Bae --- drivers/virtio/virtio.c | 78 +++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 5bdc6b82b30b..b0668434ac21 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -588,7 +588,7 @@ void unregister_virtio_device(struct virtio_device *dev) } EXPORT_SYMBOL_GPL(unregister_virtio_device); =20 -static int virtio_device_restore_priv(struct virtio_device *dev, bool rest= ore) +static int virtio_device_reinit(struct virtio_device *dev) { struct virtio_driver *drv =3D drv_to_virtio(dev->dev.driver); int ret; @@ -613,35 +613,9 @@ static int virtio_device_restore_priv(struct virtio_de= vice *dev, bool restore) =20 ret =3D dev->config->finalize_features(dev); if (ret) - goto err; - - ret =3D virtio_features_ok(dev); - if (ret) - goto err; - - if (restore) { - if (drv->restore) { - ret =3D drv->restore(dev); - if (ret) - goto err; - } - } else { - ret =3D drv->reset_done(dev); - if (ret) - goto err; - } - - /* If restore didn't do it, mark device DRIVER_OK ourselves. */ - if (!(dev->config->get_status(dev) & VIRTIO_CONFIG_S_DRIVER_OK)) - virtio_device_ready(dev); - - virtio_config_core_enable(dev); - - return 0; + return ret; =20 -err: - virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); - return ret; + return virtio_features_ok(dev); } =20 #ifdef CONFIG_PM_SLEEP @@ -668,7 +642,30 @@ EXPORT_SYMBOL_GPL(virtio_device_freeze); =20 int virtio_device_restore(struct virtio_device *dev) { - return virtio_device_restore_priv(dev, true); + struct virtio_driver *drv =3D drv_to_virtio(dev->dev.driver); + int ret; + + ret =3D virtio_device_reinit(dev); + if (ret) + goto err; + + if (drv && drv->restore) { + ret =3D drv->restore(dev); + if (ret) + goto err; + } + + /* If restore didn't do it, mark device DRIVER_OK ourselves. */ + if (!(dev->config->get_status(dev) & VIRTIO_CONFIG_S_DRIVER_OK)) + virtio_device_ready(dev); + + virtio_config_core_enable(dev); + + return 0; + +err: + virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); + return ret; } EXPORT_SYMBOL_GPL(virtio_device_restore); #endif @@ -698,11 +695,30 @@ EXPORT_SYMBOL_GPL(virtio_device_reset_prepare); int virtio_device_reset_done(struct virtio_device *dev) { struct virtio_driver *drv =3D drv_to_virtio(dev->dev.driver); + int ret; =20 if (!drv || !drv->reset_done) return -EOPNOTSUPP; =20 - return virtio_device_restore_priv(dev, false); + ret =3D virtio_device_reinit(dev); + if (ret) + goto err; + + ret =3D drv->reset_done(dev); + if (ret) + goto err; + + /* If reset_done didn't do it, mark device DRIVER_OK ourselves. */ + if (!(dev->config->get_status(dev) & VIRTIO_CONFIG_S_DRIVER_OK)) + virtio_device_ready(dev); + + virtio_config_core_enable(dev); + + return 0; + +err: + virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); + return ret; } EXPORT_SYMBOL_GPL(virtio_device_reset_done); =20 --=20 2.43.0 From nobody Tue Jun 16 08:53:02 2026 Received: from mail-pg1-f179.google.com (mail-pg1-f179.google.com [209.85.215.179]) (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 B15D8363C46 for ; Fri, 17 Apr 2026 13:35:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776432945; cv=none; b=SG++wdYadHCkD4boKyVmlTZPAcS9cnOLoNRC23Lk9urENB+BGfJorSzVAEp8/6/kYhgeHyj6fcr8i8SBKiMld/6Lte8iLFiJCZuCB3HMVkFXgl/Bq5rdpwnGbJa+hX+t1JQsLzqODM8osDGj2wRt642nkDCLSdd0jhX3NCTF7Xg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776432945; c=relaxed/simple; bh=eTMe5owLpd6fJTbocIxLhNrLvVXdrBoqyF5Kn1ZFt6Y=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=HX28ZtG89PcTFrNplUmcdT8Vw+NHJZkhTdgTi7Zk5nWj1E2kpKo5RU1Mq2lPLAeElsvfoG53DoUmwWrwfsD83gNeA7hFDIdJWShtSUt9Z9i0wwmqc4/It6GXc2DiHVq1P2ojWRXbzGpRhvIB7djMTA7iLoDnyQkUD1cF+gNmysU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=bapG++Bh; arc=none smtp.client-ip=209.85.215.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="bapG++Bh" Received: by mail-pg1-f179.google.com with SMTP id 41be03b00d2f7-c795a88e8acso235220a12.3 for ; Fri, 17 Apr 2026 06:35:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776432944; x=1777037744; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=/5XV/aTMjGl4rij/mQzWRn5Aq74xFtFSJgvscfZnyWI=; b=bapG++Bh7sQarPAJ7m71bCs+oy9vLJ3IDYfBN0U3/DQ6C/or7IQqaePBMP6MIyD5pu 9Un1EchOAY17YbJcU6zqRXaRCIOEc+mhMLmYQNWCsFstzVhgbBKgazRSG163zM5lIr4Q 583XXXMntpiAipkERgABzxP4MeECICsmVEqBFKVpv3/qY1Bp0DHSj2xDO1EDFrlSjoFp E6UiIdDa8IUdih33clnw4Bc4DJ0ITS6kfF0/r+VD4d9qwS9/97iJzVWZoXLZoJfErT8S fnM6J9X4gqpMxRKzGFLkVs53dcUgJ8fBr0UlnOenyzIkt2n42QLTqP/z+JC7yJuWnrEh wHkw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776432944; x=1777037744; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=/5XV/aTMjGl4rij/mQzWRn5Aq74xFtFSJgvscfZnyWI=; b=ZRa/gIMm7SLgD8iw89nzWpr6GB1W0EpuYmvGgLavZSLxXrsjJdOKzOMTung42D+2OA Do9oGW9itomxcUvV5I2EEtsnqCf4vMvLikkXScgLeZYUVOQer/mjwi8VTb9LkhAhfFLL y3YjduWYaDs6z50tNjWBK3b+eiNYQAxuxfcpifjLhG2pCj98TgaO7PIfIADbjOysFDxO afjDEwWyWwQr9iIQA7aXtIi4XnYPrC+hfaCCbGXd4k4IAhFmsGSps8mtq5NxJzgUx+3j RfSxlYd3w42GuXgNY23w9fT3Ki3u5D+s4JMlq6Xkww1RUxa7WAo9ITACHa+vierQiOVY u5YA== X-Forwarded-Encrypted: i=1; AFNElJ+pVbW983uxeLmrS3L0up+yxcJ7t9CrPROSU9fV7Mtq27JsIdtXKnGQ4pbFp/CqneOdT1y8OWA7HOcleKs=@vger.kernel.org X-Gm-Message-State: AOJu0Yw44/0cnb9FLQT5voHpwnhWupcgoBsFnxyViW3ztnLtCRoFVcNp fit6pLbxx6jnkov5EvIK+KUmBVpxmAJIGNRvLY0HwAQPTvuJsxARWLuY X-Gm-Gg: AeBDietkpRIE8d0LBAO5CsH1XdNqyeFITLhotYgSYP/k4vdV/MKp06dV7Sp+g5vps7J 7j8XYEZL+7OmTLz5Q9ijgK9GG4u3wpxSfu6LDOrEU/6U9HVv6Df8Dwg8AO/vNTXWeUvvXIHTk/8 +JV3e40ksnReJo/kvtChtN86hsL+zvh3dCk8iHStWnREgt0EAPGfO38RQIfdvyFivkHLBvhQKh+ 61ahKs8FIzCN4zBZkcH4hdrwt6pxpd40g4k8Uh6fiZJY8NY59W+2pzXjPtTSyZLWKeqWSTUNs/A a+7mRQrhtafO4/SHFYLqirLf5KpRlxNND5B++gZRd3m6db5/PVgXcnACszxqvQ/TkhWL5+muHXy D+27Ouq2DPh3H7SQYTsgx/hn6pJBSr3cFxnPHlDv60FqnNS/S+WYYZkldwtnVo+a63Lnm0bysSi kFwVc8K3O5H3LjZzIYkHzqflt4x0zAQfux1lBNoozQJh8TrhQZzK2FJWNpvoZg77j7zIokfXakZ mIjOlkd6OfFfQjsPsTPiHjNYARs5CsAt8E/yQ== X-Received: by 2002:a05:6a20:a109:b0:398:9403:49f4 with SMTP id adf61e73a8af0-3a08d89fa27mr3174513637.30.1776432943930; Fri, 17 Apr 2026 06:35:43 -0700 (PDT) Received: from baver-zenith.localdomain ([124.49.88.131]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c7976fa3604sm1421272a12.14.2026.04.17.06.35.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Apr 2026 06:35:43 -0700 (PDT) From: Sungho Bae To: mst@redhat.com, jasowang@redhat.com Cc: xuanzhuo@linux.alibaba.com, eperezma@redhat.com, virtualization@lists.linux.dev, linux-kernel@vger.kernel.org, Sungho Bae Subject: [RFC PATCH v2 2/4] virtio_ring: export virtqueue_reinit_vring() for noirq restore Date: Fri, 17 Apr 2026 22:34:28 +0900 Message-Id: <20260417133430.507-3-baver.bae@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260417133430.507-1-baver.bae@gmail.com> References: <20260417133430.507-1-baver.bae@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Sungho Bae After a device reset in noirq context the existing vrings must be re-initialized without any memory allocation, because GFP_KERNEL is not available. The internal helpers virtqueue_reset_split() and virtqueue_reset_packed() already reset vring indices and descriptor state in place. Add a thin exported wrapper, virtqueue_reinit_vring(), that dispatches to the appropriate helper based on the ring layout. This will be used by a subsequent patch that adds noirq system-sleep PM callbacks for virtio-mmio. Signed-off-by: Sungho Bae --- drivers/virtio/virtio_ring.c | 19 +++++++++++++++++++ include/linux/virtio_ring.h | 3 +++ 2 files changed, 22 insertions(+) diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index fbca7ce1c6bf..a57c625b5936 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -3936,5 +3936,24 @@ void virtqueue_map_sync_single_range_for_device(cons= t struct virtqueue *_vq, } EXPORT_SYMBOL_GPL(virtqueue_map_sync_single_range_for_device); =20 +/** + * virtqueue_reinit_vring - reinitialize vring state without reallocation + * @_vq: the virtqueue + * + * Reset the avail/used indices and descriptor state of an existing + * virtqueue so it can be reused after a device reset. No memory is + * allocated or freed, making this safe for use in noirq context. + */ +void virtqueue_reinit_vring(struct virtqueue *_vq) +{ + struct vring_virtqueue *vq =3D to_vvq(_vq); + + if (virtqueue_is_packed(vq)) + virtqueue_reset_packed(vq); + else + virtqueue_reset_split(vq); +} +EXPORT_SYMBOL_GPL(virtqueue_reinit_vring); + MODULE_DESCRIPTION("Virtio ring implementation"); MODULE_LICENSE("GPL"); diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h index c97a12c1cda3..26c7c9d0a151 100644 --- a/include/linux/virtio_ring.h +++ b/include/linux/virtio_ring.h @@ -118,6 +118,9 @@ void vring_del_virtqueue(struct virtqueue *vq); /* Filter out transport-specific feature bits. */ void vring_transport_features(struct virtio_device *vdev); =20 +/* Reinitialize a virtqueue without reallocation (safe in noirq context) */ +void virtqueue_reinit_vring(struct virtqueue *_vq); + irqreturn_t vring_interrupt(int irq, void *_vq); =20 u32 vring_notification_data(struct virtqueue *_vq); --=20 2.43.0 From nobody Tue Jun 16 08:53:02 2026 Received: from mail-pf1-f174.google.com (mail-pf1-f174.google.com [209.85.210.174]) (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 6C5562D8DBB for ; Fri, 17 Apr 2026 13:35:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776432950; cv=none; b=RRTLcIQankVRcmwNrfd+wNAKB57SvBJIBMsfi95lY5WYRmDFRCyOVRk5mfe6KFhjoJhPaTbuOkFjubiJ2A3KZ8Bcnhl/qgM+r62IUL2r5F82k4evAUdf74sWll1DtETLowO9SPgZ65blerWiA/DCdzqabQernZdg5TLOlObFEDE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776432950; c=relaxed/simple; bh=0Tte3gLrWHNsIUgPgTgCELoAaeW5T9C34WqXQLOJDkw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=uPXTKP5yXkTH0QnLRWg9f4e3NECpGRty0Sui8cxuXCMcd/v/vndI+hMeWTWJutLDRitLcwht9Dp0XhCfqtRJO/wHUrRt8pxO2lzBiqwpVV0Gk3aybAEwJ+m68pguCLEXA4al0hPUk5rO/ztvRRDh8QfHVPYGiBRLE85g1hsfMhc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=C11y44R9; arc=none smtp.client-ip=209.85.210.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="C11y44R9" Received: by mail-pf1-f174.google.com with SMTP id d2e1a72fcca58-82f431c0ab6so334956b3a.0 for ; Fri, 17 Apr 2026 06:35:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776432948; x=1777037748; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=F39AWoSIXRQDMzqtsZNiaPIoubFbCGy2F/eLbM+PPPY=; b=C11y44R9d4a78zYgLrOoh2vOXcbVpCOSk9AWBjMvg5KoQRmlFrrpe8ja+Pdma3ROJC m6boea7gQY3nblGGlEoZU9JiVQiBIda2ZvCw+bfR4xvhSz6wsnD0/7jvyYrXIBFJBShG tyTXQLXX8RrvQJo829vaHoYQoz7JoaefBc9HZ/OTLZKfU5D5RS1ngnx6/D+n73KcdbGu K8bf11GPgjM/RoFcYbukY548dcpfTUZlUPtjv/2uj+k4PytSOqcnyYRsJArhRQvsRc8C sJhLTvBd3ihq9/zxbV1z8330NfhnvJT/ZZMII4Oun+YWURWBilnmTu+d9Z7iqwYPXrs/ Wj7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776432948; x=1777037748; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=F39AWoSIXRQDMzqtsZNiaPIoubFbCGy2F/eLbM+PPPY=; b=ied3KClj4cobvLfDOUKWo5FFHRuAir5P/zNR1Rqvr7tnpPfsnqudVvzebdy0TA67KF Mo6Xax6YhsXRgkzXLr0MJrSXwwg5Kyb2yo0qVUsjFb87zWFdM3RnUfFsvC2Yis9/PAEB 7mkOKVX1DWsvTHDbv16zNF5oUYkOR/fzM2YbPZ+7JUaZ20Qn+y9atAal0zNuAbpPv1Aj YHZ4wIzm7nOKVHzgZQ6CIY4875TYz0ISyrwGmG49Ql1+wiscuANEjycvMy1xDI9Wjghe 2HhnEsp1BnKUYknNRWvSpbWM5KmrHho4LxXhFzQQfIHI7ygcfzbB40exvFDh9Hct8NJc Y7kw== X-Forwarded-Encrypted: i=1; AFNElJ/wdfuMRpxtyHgs3Un10FiKVsK5ePuEgIObzSeCmAWP+Kvz9bCw/nhtK0GvDRfgGs6iiyJQin1OwDOmKbo=@vger.kernel.org X-Gm-Message-State: AOJu0YxtDljZ7Vc5UohRpds2ZRIAytrScIBxPpJ9A17k2SHG4Nzd3I/Q XHaWxRN7P0HRdvOiMpzLtHNI77JM/6hDxQCeevz0YzpP4mtLdF41RIko X-Gm-Gg: AeBDieuMKelZGBs5pvaJBBIfV0COMhgeOgZGLi2a3SEOLoBwDC7sGzXHOJabfnxI1hj IQR2owAociOlhwVlgyjG9dx6pWsyVUeA5P7UnbAuB0HvD5Nsh45QTSmFQoGXI4GrBfm+rnPIMlC pzX+8wm7psSjpAXo0FCGEqTdHoU7EuxzNGBrA6dU3FsVS4twwlkNsUzJl1YOy1HNumQnLbK8RvG Ti0fd3OAZDRTM2r5aq1HFS69YlVte429p4eFtX1rb8jDHwgQ4kwT7lvcWuxOkoLBgedMGv0RjMq vCGTZmjFThmoY2Hke8hbyPni7T9pXMBtPWFIFQAM3PA6kvjKqKRPrW/l0Ps8V7+pxvb8sM/QEcM Yp8r9rGS+eUXTkr1UTEkxtXG94yntKtMkxRR0oJu0ZGo1XKWs/itsR7Zv59UMZksg/dbyLYgY3/ ViY+Gi2ZAO7dlNqn19OF8ztKEHnz1vh55bARp7LLtTBOrfwnIC91TWdAPJnAaKLGrVdW5zJZclt 5zS8CfhdqUXSgViPhlaaD+6R7y1GGbSvjOEPVkKjMpFoxAx X-Received: by 2002:a05:6300:6d82:20b0:398:aea8:a9c0 with SMTP id adf61e73a8af0-3a08d6f258dmr1972814637.19.1776432947550; Fri, 17 Apr 2026 06:35:47 -0700 (PDT) Received: from baver-zenith.localdomain ([124.49.88.131]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c7976fa3604sm1421272a12.14.2026.04.17.06.35.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Apr 2026 06:35:47 -0700 (PDT) From: Sungho Bae To: mst@redhat.com, jasowang@redhat.com Cc: xuanzhuo@linux.alibaba.com, eperezma@redhat.com, virtualization@lists.linux.dev, linux-kernel@vger.kernel.org, Sungho Bae Subject: [RFC PATCH v2 3/4] virtio: add noirq system sleep PM infrastructure Date: Fri, 17 Apr 2026 22:34:29 +0900 Message-Id: <20260417133430.507-4-baver.bae@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260417133430.507-1-baver.bae@gmail.com> References: <20260417133430.507-1-baver.bae@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Sungho Bae Some virtio-mmio devices, such as virtio-clock or virtio-regulator, must become operational before the regular PM restore callback runs because other devices may depend on them. Add the core infrastructure needed to support noirq system-sleep PM callbacks for virtio transports: - virtio_add_status_noirq(): status helper without might_sleep(). - virtio_features_ok_noirq(): feature negotiation without might_sleep(). - virtio_reset_device_noirq(): device reset that skips virtio_synchronize_cbs() (IRQ handlers are already quiesced in the noirq phase). - virtio_device_reinit_noirq(): full noirq bring-up sequence using the above helpers. - virtio_config_core_enable_noirq(): config enable with irqsave locking. - virtio_device_ready_noirq(): marks DRIVER_OK without virtio_synchronize_cbs(). Add freeze_noirq/restore_noirq callbacks to struct virtio_driver and provide matching helper wrappers in the virtio core: - virtio_device_freeze_noirq(): forwards to drv->freeze_noirq(). - virtio_device_restore_noirq(): runs the noirq bring-up sequence, resets existing vrings via the new config_ops->reset_vqs() hook, then calls drv->restore_noirq(). Modify virtio_device_restore() so that when a driver provides restore_noirq, the normal-phase restore skips the re-initialization that was already done in the noirq phase. Signed-off-by: Sungho Bae --- drivers/virtio/virtio.c | 172 +++++++++++++++++++++++++++++++++- include/linux/virtio.h | 8 ++ include/linux/virtio_config.h | 29 ++++++ 3 files changed, 206 insertions(+), 3 deletions(-) diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index b0668434ac21..4fcb6b8c797f 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -193,6 +193,17 @@ static void virtio_config_core_enable(struct virtio_de= vice *dev) spin_unlock_irq(&dev->config_lock); } =20 +static void virtio_config_core_enable_noirq(struct virtio_device *dev) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->config_lock, flags); + dev->config_core_enabled =3D true; + if (dev->config_change_pending) + __virtio_config_changed(dev); + spin_unlock_irqrestore(&dev->config_lock, flags); +} + void virtio_add_status(struct virtio_device *dev, unsigned int status) { might_sleep(); @@ -200,6 +211,20 @@ void virtio_add_status(struct virtio_device *dev, unsi= gned int status) } EXPORT_SYMBOL_GPL(virtio_add_status); =20 +/* + * Same as virtio_add_status() but without the might_sleep() assertion, + * so it is safe to call from noirq context. + * + * This assumes that the device's get_status and set_status operations are + * also noirq-safe. Therefore, the device must garantee that get_status and + * set_status can be called from noirq context. + */ +void virtio_add_status_noirq(struct virtio_device *dev, unsigned int statu= s) +{ + dev->config->set_status(dev, dev->config->get_status(dev) | status); +} +EXPORT_SYMBOL_GPL(virtio_add_status_noirq); + /* Do some validation, then set FEATURES_OK */ static int virtio_features_ok(struct virtio_device *dev) { @@ -234,6 +259,38 @@ static int virtio_features_ok(struct virtio_device *de= v) return 0; } =20 +/* noirq-safe variant: no might_sleep(), uses virtio_add_status_noirq() */ +static int virtio_features_ok_noirq(struct virtio_device *dev) +{ + unsigned int status; + + if (virtio_check_mem_acc_cb(dev)) { + if (!virtio_has_feature(dev, VIRTIO_F_VERSION_1)) { + dev_warn(&dev->dev, + "device must provide VIRTIO_F_VERSION_1\n"); + return -ENODEV; + } + + if (!virtio_has_feature(dev, VIRTIO_F_ACCESS_PLATFORM)) { + dev_warn(&dev->dev, + "device must provide VIRTIO_F_ACCESS_PLATFORM\n"); + return -ENODEV; + } + } + + if (!virtio_has_feature(dev, VIRTIO_F_VERSION_1)) + return 0; + + virtio_add_status_noirq(dev, VIRTIO_CONFIG_S_FEATURES_OK); + status =3D dev->config->get_status(dev); + if (!(status & VIRTIO_CONFIG_S_FEATURES_OK)) { + dev_err(&dev->dev, "virtio: device refuses features: %x\n", + status); + return -ENODEV; + } + return 0; +} + /** * virtio_reset_device - quiesce device for removal * @dev: the device to reset @@ -267,6 +324,24 @@ void virtio_reset_device(struct virtio_device *dev) } EXPORT_SYMBOL_GPL(virtio_reset_device); =20 +/** + * virtio_reset_device_noirq - noirq-safe variant of virtio_reset_device() + * @dev: the device to reset + */ +void virtio_reset_device_noirq(struct virtio_device *dev) +{ +#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION + /* + * The noirq stage runs with device IRQ handlers disabled, so + * virtio_synchronize_cbs() must not be called here. + */ + virtio_break_device(dev); +#endif + + dev->config->reset(dev); +} +EXPORT_SYMBOL_GPL(virtio_reset_device_noirq); + static int virtio_dev_probe(struct device *_d) { int err, i; @@ -618,6 +693,41 @@ static int virtio_device_reinit(struct virtio_device *= dev) return virtio_features_ok(dev); } =20 +/* noirq-safe variant of virtio_device_reinit() */ +static int virtio_device_reinit_noirq(struct virtio_device *dev) +{ + struct virtio_driver *drv =3D drv_to_virtio(dev->dev.driver); + int ret; + + /* + * We always start by resetting the device, in case a previous + * driver messed it up. + */ + virtio_reset_device_noirq(dev); + + /* Acknowledge that we've seen the device. */ + virtio_add_status_noirq(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); + + /* + * Maybe driver failed before freeze. + * Restore the failed status, for debugging. + */ + if (dev->failed) + virtio_add_status_noirq(dev, VIRTIO_CONFIG_S_FAILED); + + if (!drv) + return 0; + + /* We have a driver! */ + virtio_add_status_noirq(dev, VIRTIO_CONFIG_S_DRIVER); + + ret =3D dev->config->finalize_features(dev); + if (ret) + return ret; + + return virtio_features_ok_noirq(dev); +} + #ifdef CONFIG_PM_SLEEP int virtio_device_freeze(struct virtio_device *dev) { @@ -645,9 +755,15 @@ int virtio_device_restore(struct virtio_device *dev) struct virtio_driver *drv =3D drv_to_virtio(dev->dev.driver); int ret; =20 - ret =3D virtio_device_reinit(dev); - if (ret) - goto err; + /* + * If this device was already brought up in the noirq phase, + * skip the re-initialization here. + */ + if (!drv || !drv->restore_noirq) { + ret =3D virtio_device_reinit(dev); + if (ret) + goto err; + } =20 if (drv && drv->restore) { ret =3D drv->restore(dev); @@ -668,6 +784,56 @@ int virtio_device_restore(struct virtio_device *dev) return ret; } EXPORT_SYMBOL_GPL(virtio_device_restore); + +int virtio_device_freeze_noirq(struct virtio_device *dev) +{ + struct virtio_driver *drv =3D drv_to_virtio(dev->dev.driver); + + if (drv && drv->freeze_noirq) + return drv->freeze_noirq(dev); + + return 0; +} +EXPORT_SYMBOL_GPL(virtio_device_freeze_noirq); + +int virtio_device_restore_noirq(struct virtio_device *dev) +{ + struct virtio_driver *drv =3D drv_to_virtio(dev->dev.driver); + int ret; + + if (!drv || !drv->restore_noirq) + return 0; + + ret =3D virtio_device_reinit_noirq(dev); + if (ret) + goto err; + + if (!list_empty(&dev->vqs)) { + if (!dev->config->reset_vqs) { + ret =3D -EOPNOTSUPP; + goto err; + } + + ret =3D dev->config->reset_vqs(dev); + if (ret) + goto err; + } + + ret =3D drv->restore_noirq(dev); + if (ret) + goto err; + + /* If restore_noirq set DRIVER_OK, enable config now. */ + if (dev->config->get_status(dev) & VIRTIO_CONFIG_S_DRIVER_OK) + virtio_config_core_enable_noirq(dev); + + return 0; + +err: + virtio_add_status_noirq(dev, VIRTIO_CONFIG_S_FAILED); + return ret; +} +EXPORT_SYMBOL_GPL(virtio_device_restore_noirq); #endif =20 int virtio_device_reset_prepare(struct virtio_device *dev) diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 3bbc4cb6a672..31267334e4de 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -209,8 +209,12 @@ void virtio_config_driver_enable(struct virtio_device = *dev); #ifdef CONFIG_PM_SLEEP int virtio_device_freeze(struct virtio_device *dev); int virtio_device_restore(struct virtio_device *dev); +int virtio_device_freeze_noirq(struct virtio_device *dev); +int virtio_device_restore_noirq(struct virtio_device *dev); #endif void virtio_reset_device(struct virtio_device *dev); +void virtio_reset_device_noirq(struct virtio_device *dev); +void virtio_add_status_noirq(struct virtio_device *dev, unsigned int statu= s); int virtio_device_reset_prepare(struct virtio_device *dev); int virtio_device_reset_done(struct virtio_device *dev); =20 @@ -237,6 +241,8 @@ size_t virtio_max_dma_size(const struct virtio_device *= vdev); * changes; may be called in interrupt context. * @freeze: optional function to call during suspend/hibernation. * @restore: optional function to call on resume. + * @freeze_noirq: optional function to call during noirq suspend/hibernati= on. + * @restore_noirq: optional function to call on noirq resume. * @reset_prepare: optional function to call when a transport specific res= et * occurs. * @reset_done: optional function to call after transport specific reset @@ -258,6 +264,8 @@ struct virtio_driver { void (*config_changed)(struct virtio_device *dev); int (*freeze)(struct virtio_device *dev); int (*restore)(struct virtio_device *dev); + int (*freeze_noirq)(struct virtio_device *dev); + int (*restore_noirq)(struct virtio_device *dev); int (*reset_prepare)(struct virtio_device *dev); int (*reset_done)(struct virtio_device *dev); void (*shutdown)(struct virtio_device *dev); diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index 69f84ea85d71..496897bc417e 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h @@ -70,6 +70,9 @@ struct virtqueue_info { * vqs_info: array of virtqueue info structures * Returns 0 on success or error status * @del_vqs: free virtqueues found by find_vqs(). + * @reset_vqs: reinitialize existing virtqueues without allocating or + * freeing them (optional). Used during noirq restore. + * Returns 0 on success or error status. * @synchronize_cbs: synchronize with the virtqueue callbacks (optional) * The function guarantees that all memory operations on the * queue before it are visible to the vring_interrupt() that is @@ -123,6 +126,7 @@ struct virtio_config_ops { struct virtqueue_info vqs_info[], struct irq_affinity *desc); void (*del_vqs)(struct virtio_device *); + int (*reset_vqs)(struct virtio_device *vdev); void (*synchronize_cbs)(struct virtio_device *); u64 (*get_features)(struct virtio_device *vdev); void (*get_extended_features)(struct virtio_device *vdev, @@ -371,6 +375,31 @@ void virtio_device_ready(struct virtio_device *dev) dev->config->set_status(dev, status | VIRTIO_CONFIG_S_DRIVER_OK); } =20 +/** + * virtio_device_ready_noirq - noirq-safe variant of virtio_device_ready() + * @dev: the virtio device + * + * This assumes that the device's get_status and set_status operations are + * noirq-safe. + */ +static inline +void virtio_device_ready_noirq(struct virtio_device *dev) +{ + unsigned int status =3D dev->config->get_status(dev); + + WARN_ON(status & VIRTIO_CONFIG_S_DRIVER_OK); + +#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION + /* + * The noirq stage runs with device IRQ handlers disabled, so + * virtio_synchronize_cbs() must not be called here. + */ + __virtio_unbreak_device(dev); +#endif + + dev->config->set_status(dev, status | VIRTIO_CONFIG_S_DRIVER_OK); +} + static inline const char *virtio_bus_name(struct virtio_device *vdev) { --=20 2.43.0 From nobody Tue Jun 16 08:53:02 2026 Received: from mail-pg1-f170.google.com (mail-pg1-f170.google.com [209.85.215.170]) (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 22E983A3E64 for ; Fri, 17 Apr 2026 13:35:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776432953; cv=none; b=Dj0ZNYG4KTm09jaht6Nc02mdMfRzlYHz1Xi/SBoK+26TR7W46kqdVC+FENL+QkLj7v7jQXklF/RBwsl5kk72dG/AtaI1KbG/PVnecMpCU94j9gFBCyumDnxRPCOPdpPV2ou3OdR/KYq8pGzCQjI3sQkfpqql2TvgipB6UtoWnO8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776432953; c=relaxed/simple; bh=tJQmTWfO326kdUEX0KHUrK6HcbNOKPA2N0r/07lyJRU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=BF2fyftnd94g0UhQDWqD1ldjmjswM00/8TGTY9TxFKPxOx5ctFpI1jRmruBZ0uD1+9alfDiJusctXFAQJsbhlfhK5UWUjQpNp7rw1+ZF+64W9ZqzAaYDDKNxQDfqX5fAu6sj2g6rLL5KjbmerDQhGxZZplZs0uWk3QUg404fKbg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=bEUXQfGd; arc=none smtp.client-ip=209.85.215.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="bEUXQfGd" Received: by mail-pg1-f170.google.com with SMTP id 41be03b00d2f7-c76b994f7a8so280087a12.3 for ; Fri, 17 Apr 2026 06:35:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776432951; x=1777037751; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=nXcUGIfcha85KeTtKQKluvJ7CZSCtoU5lC4yHHMNuyE=; b=bEUXQfGdzGnfA+q/3mbqGuz6HoUmsbwVzCDHZiRnqN1lbxUwugn8tFRuvASdA+AKaP 2qnejVguTr0gcqrkEn9aM/ZgIe8BNCVO1UN3bvCHfs59CeixuEgaf9oz3S3OCqs4S7DE 9tNqDeAjV2J7+57k50GO5oOPDZzcis1+0jGdiSDcJgivy6+pMRQFk4D7Sge/sf0ZObJK 1kQnH5iAQsCOMuHqSdHz9unmC+X+2e4fdNKbMM/36ZxHvVA8L52llKCoGDClwtztsUg7 C1TeA8Au1J1oB81rTweOBuDCQaXTLWlhAHBdsvWWw+EyvoBfUNNhAaEIfNB1Y8cx6p3t lVfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776432951; x=1777037751; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=nXcUGIfcha85KeTtKQKluvJ7CZSCtoU5lC4yHHMNuyE=; b=gBLmMPEqozdTGrUDcyXlMdKtp9ekSuLwjT1yW1SE4VWQmusTu8uif6wZRVyvN7wrt4 gH+6g6Vm3zjRy4fS0ZYH2Se9KcdmyHqYqpvmLGfMY9Mf60UNWBseIvBETdTOFRLjsufe rSAE4NYqEqWvqVu1dxB4B/hUaNLHgUWm2NG1LBUF3gV8IqE2e5pLB6M4Ese89RXJRdag kE5n/E1Pe0S1JZWu9dXQJx2LoWS+AIFVwmNQRiQcyS4wnsB5uGW8juVDmO3cENP3TSRU JOH2LsuSYJ8dE5RBfww32spbqe7T29yukX6NfNP0VYhx7hUxmqe30zNm0+lWUigZW4QP QCag== X-Forwarded-Encrypted: i=1; AFNElJ/XtXS8Kv1VioHSN46u9ZwLvvTbtxrix9A/PuQUie1ZDf1hXqnbapOklNo6rBB8I0JZfiwfzcHXHDL1pIs=@vger.kernel.org X-Gm-Message-State: AOJu0Yyj7bBDiE5C1YSy/y0SzR0p5u7RvhyD6syzUG/t9CuOvC7rgEVj JNylaiabOISGoFdBcILXQogsy0DDvE8HQ/JEtisQiscSSM0laFg4GhPIHVM5D1JZ X-Gm-Gg: AeBDietRmpjtqLjtjyJFNnN7aDrtuXUFzH2FhvVeEvupzKs2ieCTexh5fKG4FCeVPPW /Bb4Lw76HQg6uMnzR1cXs1K1JYbUxzBMmkEQsgGG7wwTUw5NY+lwrbhLPznA6h4R7ui7rME2kLo UPmxBE/y1lATNrsQ8/sYdGvs+noWgiXTzxKo9DCsEKroybm0/mbCbU5SsfWxza7/HLRFpyETlm2 11ULEGewQwOTQ50CbxW04b3GSzenAapPTAe8RdjERvlE1T7a3o37vl77CqQDbeC4gWZvIY1CrNn mvi0VVN4eOdIPfMmZ20uWEYtqIhfVxUxhZMgkP1PJHpiy2zr0ANt2y98jFEDJ563ElRuMWJKZL9 2QcEHsIdKgyDQqDnejU1GvWQRMvKpjiQ5vudanezi/WhB7GmnEFL5SDbI/qHDa0enUok/iJhdt1 GgNtpSAzlDBmva/0dDoNaX4md5lVDfacF58jWz2p0doqrOiPRM3IhJwR7NdA6mydPV52agYSjj0 dC/CQnE4r5IR2ZzoO0czgZqdTlj3Td5Ay+qxQ== X-Received: by 2002:a05:6a20:4306:b0:389:8f3f:50ce with SMTP id adf61e73a8af0-3a08d939437mr3218253637.56.1776432951186; Fri, 17 Apr 2026 06:35:51 -0700 (PDT) Received: from baver-zenith.localdomain ([124.49.88.131]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c7976fa3604sm1421272a12.14.2026.04.17.06.35.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Apr 2026 06:35:50 -0700 (PDT) From: Sungho Bae To: mst@redhat.com, jasowang@redhat.com Cc: xuanzhuo@linux.alibaba.com, eperezma@redhat.com, virtualization@lists.linux.dev, linux-kernel@vger.kernel.org, Sungho Bae Subject: [RFC PATCH v2 4/4] virtio-mmio: wire up noirq system sleep PM callbacks Date: Fri, 17 Apr 2026 22:34:30 +0900 Message-Id: <20260417133430.507-5-baver.bae@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260417133430.507-1-baver.bae@gmail.com> References: <20260417133430.507-1-baver.bae@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Sungho Bae Implement the transport side of noirq system-sleep PM for virtio-mmio: - vm_reset_vqs(): iterate all virtqueues, call virtqueue_reinit_vring() to reset the vring state in place, then reprogram the MMIO queue registers (QUEUE_SEL, QUEUE_NUM, descriptor/avail/used addresses, QUEUE_READY) so the device can use the same rings immediately after restore. No memory is allocated or freed. - virtio_mmio_freeze_noirq() / virtio_mmio_restore_noirq(): thin wrappers that forward to the virtio core noirq helpers. The restore_noirq path also writes GUEST_PAGE_SIZE for legacy (v1) devices, matching the existing restore callback. - Wire vm_reset_vqs into virtio_mmio_config_ops and register the noirq callbacks via SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(). With this in place, a virtio-mmio driver can implement freeze_noirq / restore_noirq to participate in the noirq PM phase, enabling use cases such as virtio-clock or virtio-regulator that must be operational before other devices are restored. Signed-off-by: Sungho Bae --- drivers/virtio/virtio_mmio.c | 131 ++++++++++++++++++++++++----------- 1 file changed, 92 insertions(+), 39 deletions(-) diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 595c2274fbb5..7cde042e15ac 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -336,6 +336,75 @@ static void vm_del_vqs(struct virtio_device *vdev) free_irq(platform_get_irq(vm_dev->pdev, 0), vm_dev); } =20 +static int vm_active_vq(struct virtio_device *vdev, struct virtqueue *vq) +{ + struct virtio_mmio_device *vm_dev =3D to_virtio_mmio_device(vdev); + int q_num =3D virtqueue_get_vring_size(vq); + + writel(q_num, vm_dev->base + VIRTIO_MMIO_QUEUE_NUM); + if (vm_dev->version =3D=3D 1) { + u64 q_pfn =3D virtqueue_get_desc_addr(vq) >> PAGE_SHIFT; + + /* + * virtio-mmio v1 uses a 32bit QUEUE PFN. If we have something + * that doesn't fit in 32bit, fail the setup rather than + * pretending to be successful. + */ + if (q_pfn >> 32) { + dev_err(&vdev->dev, + "platform bug: legacy virtio-mmio must not be used with RAM above 0x%l= lxGB\n", + 0x1ULL << (32 + PAGE_SHIFT - 30)); + return -E2BIG; + } + + writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN); + writel(q_pfn, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); + } else { + u64 addr; + + addr =3D virtqueue_get_desc_addr(vq); + writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_LOW); + writel((u32)(addr >> 32), + vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_HIGH); + + addr =3D virtqueue_get_avail_addr(vq); + writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_LOW); + writel((u32)(addr >> 32), + vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_HIGH); + + addr =3D virtqueue_get_used_addr(vq); + writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_USED_LOW); + writel((u32)(addr >> 32), + vm_dev->base + VIRTIO_MMIO_QUEUE_USED_HIGH); + + writel(1, vm_dev->base + VIRTIO_MMIO_QUEUE_READY); + } + + return 0; +} + +static int vm_reset_vqs(struct virtio_device *vdev) +{ + struct virtio_mmio_device *vm_dev =3D to_virtio_mmio_device(vdev); + struct virtqueue *vq; + int err; + + virtio_device_for_each_vq(vdev, vq) { + /* Re-init vring */ + virtqueue_reinit_vring(vq); + + /* Select the queue we're interested in */ + writel(vq->index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL); + + /* Activate the queue */ + err =3D vm_active_vq(vdev, vq); + if (err < 0) + return err; + } + + return 0; +} + static void vm_synchronize_cbs(struct virtio_device *vdev) { struct virtio_mmio_device *vm_dev =3D to_virtio_mmio_device(vdev); @@ -388,45 +457,9 @@ static struct virtqueue *vm_setup_vq(struct virtio_dev= ice *vdev, unsigned int in vq->num_max =3D num; =20 /* Activate the queue */ - writel(virtqueue_get_vring_size(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NUM= ); - if (vm_dev->version =3D=3D 1) { - u64 q_pfn =3D virtqueue_get_desc_addr(vq) >> PAGE_SHIFT; - - /* - * virtio-mmio v1 uses a 32bit QUEUE PFN. If we have something - * that doesn't fit in 32bit, fail the setup rather than - * pretending to be successful. - */ - if (q_pfn >> 32) { - dev_err(&vdev->dev, - "platform bug: legacy virtio-mmio must not be used with RAM above 0x%l= lxGB\n", - 0x1ULL << (32 + PAGE_SHIFT - 30)); - err =3D -E2BIG; - goto error_bad_pfn; - } - - writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN); - writel(q_pfn, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); - } else { - u64 addr; - - addr =3D virtqueue_get_desc_addr(vq); - writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_LOW); - writel((u32)(addr >> 32), - vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_HIGH); - - addr =3D virtqueue_get_avail_addr(vq); - writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_LOW); - writel((u32)(addr >> 32), - vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_HIGH); - - addr =3D virtqueue_get_used_addr(vq); - writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_USED_LOW); - writel((u32)(addr >> 32), - vm_dev->base + VIRTIO_MMIO_QUEUE_USED_HIGH); - - writel(1, vm_dev->base + VIRTIO_MMIO_QUEUE_READY); - } + err =3D vm_active_vq(vdev, vq); + if (err < 0) + goto error_bad_pfn; =20 return vq; =20 @@ -528,6 +561,7 @@ static const struct virtio_config_ops virtio_mmio_confi= g_ops =3D { .reset =3D vm_reset, .find_vqs =3D vm_find_vqs, .del_vqs =3D vm_del_vqs, + .reset_vqs =3D vm_reset_vqs, .get_features =3D vm_get_features, .finalize_features =3D vm_finalize_features, .bus_name =3D vm_bus_name, @@ -553,8 +587,27 @@ static int virtio_mmio_restore(struct device *dev) return virtio_device_restore(&vm_dev->vdev); } =20 +static int virtio_mmio_freeze_noirq(struct device *dev) +{ + struct virtio_mmio_device *vm_dev =3D dev_get_drvdata(dev); + + return virtio_device_freeze_noirq(&vm_dev->vdev); +} + +static int virtio_mmio_restore_noirq(struct device *dev) +{ + struct virtio_mmio_device *vm_dev =3D dev_get_drvdata(dev); + + if (vm_dev->version =3D=3D 1) + writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE); + + return virtio_device_restore_noirq(&vm_dev->vdev); +} + static const struct dev_pm_ops virtio_mmio_pm_ops =3D { SET_SYSTEM_SLEEP_PM_OPS(virtio_mmio_freeze, virtio_mmio_restore) + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(virtio_mmio_freeze_noirq, + virtio_mmio_restore_noirq) }; #endif =20 --=20 2.43.0